nucleus-core-ts 0.9.78 → 0.9.82
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 +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,7 +57,7 @@ var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defP
|
|
|
57
57
|
</div>
|
|
58
58
|
</body>
|
|
59
59
|
</html>
|
|
60
|
-
`}getActiveAlerts(){return Array.from(this.state.activeAlerts.values())}acknowledgeAlert(alertId){for(let[_type,alert]of this.state.activeAlerts)if(alert.id===alertId)return alert.acknowledged=!0,!0;return!1}clearAlert(type){this.state.activeAlerts.delete(type)}}class ApplicationCollector{config;requestCount=0;responseTimes=[];errorCount=0;rateLimitBlocks=0;byEndpoint={};byMethod={};byStatus={};byErrorType={};lastCollectTime=Date.now();constructor(config){this.config=config}recordRequest(params){if(!this.config?.enabled)return;if(this.requestCount++,this.config.metrics?.responseTime!==!1){if(this.responseTimes.push(params.responseTimeMs),this.responseTimes.length>1e4)this.responseTimes=this.responseTimes.slice(-5000)}if(this.config.metrics?.requests!==!1)this.byEndpoint[params.endpoint]=(this.byEndpoint[params.endpoint]||0)+1,this.byMethod[params.method]=(this.byMethod[params.method]||0)+1,this.byStatus[String(params.status)]=(this.byStatus[String(params.status)]||0)+1;if(this.config.metrics?.errors!==!1&¶ms.isError){if(this.errorCount++,params.errorType)this.byErrorType[params.errorType]=(this.byErrorType[params.errorType]||0)+1}}recordRateLimitBlock(){if(!this.config?.enabled||this.config.metrics?.rateLimits===!1)return;this.rateLimitBlocks++}collect(){if(!this.config?.enabled)return null;let elapsed=(Date.now()-this.lastCollectTime)/1000/60,perMinute=elapsed>0?Math.round(this.requestCount/elapsed):0,blockedPerMinute=elapsed>0?Math.round(this.rateLimitBlocks/elapsed):0,sortedTimes=[...this.responseTimes].sort((a,b)=>a-b),len=sortedTimes.length;return{requests:{total:this.requestCount,perMinute,byEndpoint:{...this.byEndpoint},byMethod:{...this.byMethod},byStatus:{...this.byStatus}},responseTime:{avg:len>0?Math.round(sortedTimes.reduce((a,b)=>a+b,0)/len*100)/100:0,min:len>0?sortedTimes[0]??0:0,max:len>0?sortedTimes[len-1]??0:0,p50:len>0?sortedTimes[Math.floor(len*0.5)]??0:0,p95:len>0?sortedTimes[Math.floor(len*0.95)]??0:0,p99:len>0?sortedTimes[Math.floor(len*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}}}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 elapsed=(Date.now()-this.lastCollectTime)/1000/60;return elapsed>0?Math.round(this.requestCount/elapsed):0}getErrorRate(){return this.requestCount>0?this.errorCount/this.requestCount*100:0}getRateLimitBlocksPerMinute(){let elapsed=(Date.now()-this.lastCollectTime)/1000/60;return elapsed>0?Math.round(this.rateLimitBlocks/elapsed):0}getAvgResponseTime(){if(this.responseTimes.length===0)return 0;return this.responseTimes.reduce((a,b)=>a+b,0)/this.responseTimes.length}}import*as fs3 from"fs";import*as os from"os";class SystemCollector{config;lastCpuInfo=null;constructor(config){this.config=config}async collect(){if(!this.config?.enabled)return null;let metrics={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)metrics.cpu=this.collectCpu();if(this.config.metrics?.memory!==!1)metrics.memory=this.collectMemory();if(this.config.metrics?.disk!==!1)metrics.disk=await this.collectDisk();if(this.config.metrics?.network)metrics.network=this.collectNetwork();if(this.config.metrics?.process!==!1)metrics.process=await this.collectProcess();return metrics}collectCpu(){let cpus2=os.cpus(),cores=cpus2.length,idle=0,total=0;for(let cpu of cpus2)idle+=cpu.times.idle,total+=cpu.times.user+cpu.times.nice+cpu.times.sys+cpu.times.idle+cpu.times.irq;let usage=0;if(this.lastCpuInfo){let idleDiff=idle-this.lastCpuInfo.idle,totalDiff=total-this.lastCpuInfo.total;usage=totalDiff>0?Math.round((1-idleDiff/totalDiff)*100*100)/100:0}return this.lastCpuInfo={idle,total},{usage,cores}}collectMemory(){let total=os.totalmem(),free=os.freemem(),used=total-free,usagePercent=Math.round(used/total*100*100)/100,memUsage=process.memoryUsage();return{total,used,free,usagePercent,heapUsed:memUsage.heapUsed,heapTotal:memUsage.heapTotal}}async collectDisk(){try{let stats=fs3.statfsSync("/"),total=stats.blocks*stats.bsize,free=stats.bfree*stats.bsize,used=total-free,usagePercent=Math.round(used/total*100*100)/100;return{total,used,free,usagePercent}}catch{return{total:0,used:0,free:0,usagePercent:0}}}collectNetwork(){let interfaces=os.networkInterfaces(),bytesIn=0,bytesOut=0;for(let name in interfaces){let iface=interfaces[name];if(iface){for(let info of iface)if(!info.internal)bytesIn+=0,bytesOut+=0}}return{bytesIn,bytesOut}}async collectProcess(){let uptime=process.uptime(),pid=process.pid,lagStart=Date.now(),eventLoopLag=await new Promise((resolve)=>{setImmediate(()=>{resolve(Date.now()-lagStart)})});return{uptime,pid,eventLoopLag}}}var init_SystemCollector=()=>{};import{randomUUID as randomUUID3}from"crypto";import*as os2 from"os";class LiveMonitoringService{store;memoryInterval=null;cpuInterval=null;lastCpuInfo=null;isRunning=!1;constructor(config){let merged={...DEFAULT_LIVE_CONFIG,...config};this.store={requests:[],configs:{logMemory:merged.logMemory,logCpu:merged.logCpu,logDapr:merged.logDapr,logWebSocket:merged.logWebSocket,cpuLogInterval:merged.cpuLogInterval,memoryLogInterval:merged.memoryLogInterval},logs:{memory:[],cpu:[],dapr:[],ws:[]},logLimits:{memory:merged.memoryLogLimit,cpu:merged.cpuLogLimit,dapr:merged.daprLogLimit,ws:merged.wsLogLimit,request:merged.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 collect=()=>{if(!this.store.configs.logMemory)return;let mem=process.memoryUsage(),entry={timestamp:Date.now(),rss:mem.rss,heapUsed:mem.heapUsed,heapTotal:mem.heapTotal};if(this.store.logs.memory.push(entry),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=entry,this.store.worker.updatedAt=Date.now()};collect(),this.memoryInterval=setInterval(collect,this.store.configs.memoryLogInterval)}startCpuCollector(){if(this.cpuInterval)clearInterval(this.cpuInterval);let collect=()=>{if(!this.store.configs.logCpu)return;let cpus3=os2.cpus(),userTime=0,sysTime=0,idle=0,total=0;for(let cpu of cpus3)userTime+=cpu.times.user,sysTime+=cpu.times.sys,idle+=cpu.times.idle,total+=cpu.times.user+cpu.times.nice+cpu.times.sys+cpu.times.idle+cpu.times.irq;let userPercent=0,sysPercent=0;if(this.lastCpuInfo){let totalDiff=total-this.lastCpuInfo.total,idleDiff=idle-this.lastCpuInfo.idle;if(totalDiff>0){let activeDiff=totalDiff-idleDiff;userPercent=Math.round((userTime-0)/(activeDiff||1)*100*100)/100,sysPercent=Math.round((sysTime-0)/(activeDiff||1)*100*100)/100;let totalActive=Math.round((1-idleDiff/totalDiff)*100*100)/100;userPercent=Math.round(totalActive*0.7*100)/100,sysPercent=Math.round(totalActive*0.3*100)/100}}this.lastCpuInfo={idle,total};let entry={timestamp:Date.now(),user:userPercent,system:sysPercent};if(this.store.logs.cpu.push(entry),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=entry,this.store.worker.updatedAt=Date.now()};collect(),this.cpuInterval=setInterval(collect,this.store.configs.cpuLogInterval)}recordRequest(request){if(this.store.requests.push(request),this.store.requests.length>this.store.logLimits.request*2)this.store.requests=this.store.requests.slice(-this.store.logLimits.request)}recordDaprEvent(type,details){if(!this.store.configs.logDapr)return;let event={id:randomUUID3(),type,timestamp:Date.now(),...details};if(this.store.logs.dapr.push(event),this.store.daprEvents.push(event),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(type,details){if(!this.store.configs.logWebSocket)return;let event={id:randomUUID3(),type,timestamp:Date.now(),...details};if(this.store.logs.ws.push(event),this.store.wsEvents.push(event),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(timestamps){let memoryUpdates=this.store.logs.memory.filter((m)=>m.timestamp>timestamps.memory),cpuUpdates=this.store.logs.cpu.filter((c)=>c.timestamp>timestamps.cpu),requestUpdates=this.store.requests.filter((r)=>r.timestamp>timestamps.request),daprUpdates=this.store.logs.dapr.filter((d)=>d.timestamp>timestamps.dapr),wsUpdates=this.store.logs.ws.filter((w)=>w.timestamp>timestamps.ws);if(!(memoryUpdates.length>0||cpuUpdates.length>0||requestUpdates.length>0||daprUpdates.length>0||wsUpdates.length>0))return null;return{memory:memoryUpdates,cpu:cpuUpdates,requests:requestUpdates,dapr:daprUpdates,ws:wsUpdates,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(payload){if(payload.logMemory!==void 0)this.store.configs.logMemory=payload.logMemory;if(payload.logCpu!==void 0)this.store.configs.logCpu=payload.logCpu;if(payload.logDapr!==void 0)this.store.configs.logDapr=payload.logDapr;if(payload.logWebSocket!==void 0)this.store.configs.logWebSocket=payload.logWebSocket;if(payload.cpuLogInterval!==void 0){if(this.store.configs.cpuLogInterval=payload.cpuLogInterval,this.isRunning&&this.store.configs.logCpu)this.startCpuCollector()}if(payload.memoryLogInterval!==void 0){if(this.store.configs.memoryLogInterval=payload.memoryLogInterval,this.isRunning&&this.store.configs.logMemory)this.startMemoryCollector()}if(payload.memoryLogLimit!==void 0)this.store.logLimits.memory=payload.memoryLogLimit;if(payload.cpuLogLimit!==void 0)this.store.logLimits.cpu=payload.cpuLogLimit;if(payload.daprLogLimit!==void 0)this.store.logLimits.dapr=payload.daprLogLimit;if(payload.wsLogLimit!==void 0)this.store.logLimits.ws=payload.wsLogLimit;if(payload.requestLogLimit!==void 0)this.store.logLimits.request=payload.requestLogLimit;return{message:"Settings updated successfully",configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}getStore(){return this.store}isEnabled(){return this.isRunning}}var DEFAULT_LIVE_CONFIG;var init_LiveMonitoringService=__esm(()=>{DEFAULT_LIVE_CONFIG={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 MonitoringService{redis;logger;config;appId;flushToDb;systemCollector;applicationCollector;alertService;collectInterval=null;flushInterval=null;pendingMetrics=[];isRunning=!1;constructor(deps){this.redis=deps.redis,this.logger=deps.logger,this.config=this.mergeConfig(deps.config),this.appId=deps.appId,this.flushToDb=deps.flushToDb,this.systemCollector=new SystemCollector(this.config.system),this.applicationCollector=new ApplicationCollector(this.config.application),this.alertService=new AlertService({logger:deps.logger,emailService:deps.emailService,config:this.config,appId:deps.appId})}mergeConfig(config){return{enabled:config.enabled??DEFAULT_CONFIG3.enabled,system:{enabled:config.system?.enabled??DEFAULT_CONFIG3.system.enabled,collectInterval:config.system?.collectInterval??DEFAULT_CONFIG3.system.collectInterval,metrics:{cpu:config.system?.metrics?.cpu??DEFAULT_CONFIG3.system.metrics.cpu,memory:config.system?.metrics?.memory??DEFAULT_CONFIG3.system.metrics.memory,disk:config.system?.metrics?.disk??DEFAULT_CONFIG3.system.metrics.disk,network:config.system?.metrics?.network??DEFAULT_CONFIG3.system.metrics.network,process:config.system?.metrics?.process??DEFAULT_CONFIG3.system.metrics.process}},application:{enabled:config.application?.enabled??DEFAULT_CONFIG3.application.enabled,metrics:{requests:config.application?.metrics?.requests??DEFAULT_CONFIG3.application.metrics.requests,responseTime:config.application?.metrics?.responseTime??DEFAULT_CONFIG3.application.metrics.responseTime,errors:config.application?.metrics?.errors??DEFAULT_CONFIG3.application.metrics.errors,rateLimits:config.application?.metrics?.rateLimits??DEFAULT_CONFIG3.application.metrics.rateLimits}},database:{enabled:config.database?.enabled??DEFAULT_CONFIG3.database.enabled,metrics:{connections:config.database?.metrics?.connections??DEFAULT_CONFIG3.database.metrics.connections,queryTime:config.database?.metrics?.queryTime??DEFAULT_CONFIG3.database.metrics.queryTime,slowQueryThreshold:config.database?.metrics?.slowQueryThreshold??DEFAULT_CONFIG3.database.metrics.slowQueryThreshold}},redis:{enabled:config.redis?.enabled??DEFAULT_CONFIG3.redis.enabled},persistence:{enabled:config.persistence?.enabled??DEFAULT_CONFIG3.persistence.enabled,flushInterval:config.persistence?.flushInterval??DEFAULT_CONFIG3.persistence.flushInterval,retentionDays:config.persistence?.retentionDays??DEFAULT_CONFIG3.persistence.retentionDays},alerts:{enabled:config.alerts?.enabled??DEFAULT_CONFIG3.alerts.enabled,email:{enabled:config.alerts?.email?.enabled??DEFAULT_CONFIG3.alerts.email.enabled,recipients:config.alerts?.email?.recipients??DEFAULT_CONFIG3.alerts.email.recipients},thresholds:{cpuPercent:config.alerts?.thresholds?.cpuPercent??DEFAULT_CONFIG3.alerts.thresholds.cpuPercent,memoryPercent:config.alerts?.thresholds?.memoryPercent??DEFAULT_CONFIG3.alerts.thresholds.memoryPercent,diskPercent:config.alerts?.thresholds?.diskPercent??DEFAULT_CONFIG3.alerts.thresholds.diskPercent,errorRatePercent:config.alerts?.thresholds?.errorRatePercent??DEFAULT_CONFIG3.alerts.thresholds.errorRatePercent,responseTimeMs:config.alerts?.thresholds?.responseTimeMs??DEFAULT_CONFIG3.alerts.thresholds.responseTimeMs,rateLimitBlocksPerMinute:config.alerts?.thresholds?.rateLimitBlocksPerMinute??DEFAULT_CONFIG3.alerts.thresholds.rateLimitBlocksPerMinute},cooldown:config.alerts?.cooldown??DEFAULT_CONFIG3.alerts.cooldown}}}parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h|d)$/);if(!match||!match[1]||!match[2])return 1e4;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*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 collectIntervalMs=this.parseTimeToMs(this.config.system.collectInterval);if(this.collectInterval=setInterval(()=>{this.collect()},collectIntervalMs),this.config.persistence.enabled&&this.flushToDb){let flushIntervalMs=this.parseTimeToMs(this.config.persistence.flushInterval);this.flushInterval=setInterval(()=>{this.flush()},flushIntervalMs)}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 now=Date.now(),snapshot={timestamp:now};if(this.config.system.enabled){let systemMetrics=await this.systemCollector.collect();if(systemMetrics)snapshot.system=systemMetrics,this.addMetricPoints("system",systemMetrics,now)}if(this.config.application.enabled){let appMetrics=this.applicationCollector.collect();if(appMetrics)snapshot.application=appMetrics,this.addMetricPoints("application",appMetrics,now)}if(await this.storeSnapshot(snapshot),this.config.alerts.enabled)await this.alertService.checkAndAlert(snapshot)}addMetricPoints(type,metrics,timestamp){let flatten=(obj,prefix="")=>{for(let key in obj){let value=obj[key],newKey=prefix?`${prefix}.${key}`:key;if(typeof value==="number")this.pendingMetrics.push({timestamp,metricType:type,metricName:newKey,value});else if(typeof value==="object"&&value!==null&&!Array.isArray(value))flatten(value,newKey)}};flatten(metrics)}async storeSnapshot(snapshot){let key=`monitoring:${this.appId}:latest`;await this.redis.create(key,snapshot,3600);let historyKey=`monitoring:${this.appId}:history`,historyResult=await this.redis.read(historyKey),history=historyResult.success&&historyResult.data?historyResult.data:[];history.push(snapshot);let oneHourAgo=Date.now()-3600000,filteredHistory=history.filter((s)=>s.timestamp>oneHourAgo);await this.redis.create(historyKey,filteredHistory,3600)}async flush(){if(this.pendingMetrics.length===0)return;if(!this.flushToDb)return;let metricsToFlush=[...this.pendingMetrics];this.pendingMetrics=[];try{await this.flushToDb(metricsToFlush),this.logger.debug(`[Monitoring] Flushed ${metricsToFlush.length} metrics to database`)}catch(error){this.logger.error(`[Monitoring] Failed to flush metrics: ${error}`),this.pendingMetrics=[...metricsToFlush,...this.pendingMetrics]}}recordRequest(params){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRequest(params)}recordRateLimitBlock(){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRateLimitBlock()}async getLatestSnapshot(){let key=`monitoring:${this.appId}:latest`,result=await this.redis.read(key);return result.success?result.data:null}async getHistory(minutes=60){let key=`monitoring:${this.appId}:history`,result=await this.redis.read(key);if(!result.success||!result.data)return[];let cutoff=Date.now()-minutes*60000;return result.data.filter((s)=>s.timestamp>cutoff)}getActiveAlerts(){return this.alertService.getActiveAlerts()}acknowledgeAlert(alertId){return this.alertService.acknowledgeAlert(alertId)}isEnabled(){return this.config.enabled}getConfig(){return this.config}}var DEFAULT_CONFIG3;var init_Monitoring=__esm(()=>{init_SystemCollector();init_LiveMonitoringService();DEFAULT_CONFIG3={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 init_types4=()=>{};import{and as and3,desc,eq as eq7}from"drizzle-orm";function toCamel(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());result[camelKey]=value}return result}function fromCamel(obj){let result={};for(let[key,value]of Object.entries(obj)){let snakeKey=key.replace(/[A-Z]/g,(c)=>`_${c.toLowerCase()}`);result[snakeKey]=value}return result}class NotificationService{db;schemaTables;config;logger;emailService;constructor(serviceConfig){this.db=serviceConfig.db,this.schemaTables=serviceConfig.schemaTables,this.config=serviceConfig.config,this.logger=serviceConfig.logger,this.emailService=serviceConfig.emailService}getTable(name){return this.schemaTables[name]}getCol(table,col2){return table[col2]}isChannelEnabled(channel){let channels=this.config.channels;if(!channels)return channel==="portal";switch(channel){case"portal":return channels.portal!==!1;case"email":return channels.email===!0;case"sms":return channels.sms?.enabled===!0;case"telegram":return channels.telegram?.enabled===!0;case"webhook":return channels.webhook?.enabled===!0;default:return!1}}interpolateTemplate(template,context){let result=template;for(let[key,value]of Object.entries(context))result=result.replace(new RegExp(`{{${key}}}`,"g"),String(value??""));for(let[key,value]of Object.entries(this.config.templateVariables||{}))result=result.replace(new RegExp(`{{${key}}}`,"g"),value);return result}async triggerNotifications(params){let{trigger,flow_id,entity_name,entity_id,node_id,context={}}=params,rulesTable=this.getTable("verificationNotificationRules"),recipientsTable=this.getTable("verificationNotificationRecipients"),channelsTable=this.getTable("verificationNotificationChannels");if(!rulesTable||!recipientsTable){this.logger.warn("[Notification] Notification tables not found");return}let now=new Date,rules=await this.db.select().from(rulesTable).where(and3(eq7(this.getCol(rulesTable,"flowId"),flow_id),eq7(this.getCol(rulesTable,"trigger"),trigger)));this.logger.info(`[Notification] Found ${rules.length} rules for trigger=${trigger} flow_id=${flow_id}, filter_node_id=${node_id||"NONE"}`);for(let r of rules)this.logger.info(`[Notification] Rule ${r.id}: nodeId=${r.nodeId}, trigger=${r.trigger}, title=${JSON.stringify(r.titleTemplate)}`);let filteredRules=rules.filter((rule)=>{if(node_id&&rule.nodeId!==node_id)return this.logger.info(`[Notification] EXCLUDED rule ${rule.id}: rule.nodeId=${rule.nodeId} !== filter_node_id=${node_id}`),!1;if(rule.startsAt&&new Date(rule.startsAt)>now)return!1;if(rule.expiresAt&&new Date(rule.expiresAt)<now)return!1;return!0});for(let rule of filteredRules){let recipients=await this.db.select().from(recipientsTable).where(eq7(this.getCol(recipientsTable,"ruleId"),rule.id)),ruleChannels=["portal"];if(channelsTable){let channelEntries=await this.db.select().from(channelsTable).where(eq7(this.getCol(channelsTable,"ruleId"),rule.id));if(channelEntries.length>0)ruleChannels=channelEntries.map((c)=>c.channel)}let enabledChannels=ruleChannels.filter((ch)=>this.isChannelEnabled(ch));if(enabledChannels.length===0)continue;this.logger.info(`[Notification] Rule ${rule.id}: ${recipients.length} recipients, ${enabledChannels.length} channels (${enabledChannels.join(",")})`);let userIds=await this.resolveRecipients(recipients,params.verifier_id,flow_id,entity_name,entity_id);this.logger.info(`[Notification] Rule ${rule.id}: resolved ${userIds.length} user IDs: ${userIds.join(", ")}`);let enrichedContext={...context,entity_name,entity_id,trigger,decision:params.decision};this.logger.info(`[Notification] Rule ${rule.id}: titleTemplate=${JSON.stringify(rule.titleTemplate)}, bodyTemplate=${JSON.stringify(rule.bodyTemplate)}, context=${JSON.stringify(enrichedContext)}`);let title=rule.titleTemplate?this.interpolateTemplate(rule.titleTemplate,enrichedContext):`Verification ${trigger.replace("on_","").replace("_"," ")}`,body=rule.bodyTemplate?this.interpolateTemplate(rule.bodyTemplate,enrichedContext):void 0;this.logger.info(`[Notification] Rule ${rule.id}: final title="${title}", body="${body}"`);for(let userId of userIds)await this.send({user_id:userId,title,body,entity_name,entity_id,type:"verification",source:`flow:${flow_id}`,channels:enabledChannels})}this.logger.debug(`[Notification] Triggered ${filteredRules.length} rules for ${trigger} on ${entity_name}:${entity_id}`)}async resolveRecipients(recipients,currentVerifierId,flowId,entityName,entityId){let userIds=new Set,userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");for(let recipient of recipients)switch(recipient.recipientType){case"user":if(recipient.recipientUserId)userIds.add(recipient.recipientUserId);break;case"role":if(recipient.recipientRole&&userRolesTable&&rolesTable){let rolesCols=rolesTable,userRolesCols=userRolesTable,role=(await this.db.select().from(rolesTable).where(eq7(rolesCols.name,recipient.recipientRole)).limit(1))[0];if(role){let usersInRole=await this.db.select({user_id:userRolesCols.userId}).from(userRolesTable).where(eq7(userRolesCols.roleId,role.id));for(let ur of usersInRole)userIds.add(ur.user_id)}}break;case"step_verifier":if(currentVerifierId)userIds.add(currentVerifierId);break;case"entity_creator":{if(entityName&&entityId){let instancesTable=this.getTable("verificationInstances");if(instancesTable){let inst=(await this.db.select().from(instancesTable).where(and3(eq7(this.getCol(instancesTable,"entityName"),entityName),eq7(this.getCol(instancesTable,"entityId"),entityId))).orderBy(desc(this.getCol(instancesTable,"createdAt"))).limit(1))[0];if(inst?.startedBy)userIds.add(inst.startedBy)}}break}case"all_verifiers":{if(flowId){let verifierConfigsTable=this.getTable("verificationVerifierConfigs");if(verifierConfigsTable){let configs=await this.db.select().from(verifierConfigsTable).where(eq7(this.getCol(verifierConfigsTable,"flowId"),flowId));this.logger.info(`[Notification] all_verifiers: found ${configs.length} verifier configs for flow ${flowId}`);for(let cfg of configs){let row=cfg;if(this.logger.info(`[Notification] all_verifiers: config node_id=${row.nodeId}, type=${row.verifierType}, userId=${row.verifierUserId}, role=${row.verifierRole}`),row.verifierUserId)userIds.add(row.verifierUserId);if(row.verifierType==="role"&&row.verifierRole&&userRolesTable&&rolesTable){let rCols=rolesTable,urCols=userRolesTable,roleRow=(await this.db.select().from(rolesTable).where(eq7(rCols.name,row.verifierRole)).limit(1))[0];if(roleRow){let usersInRole=await this.db.select({user_id:urCols.userId}).from(userRolesTable).where(eq7(urCols.roleId,roleRow.id));for(let ur of usersInRole)userIds.add(ur.user_id)}}}}}break}}return Array.from(userIds)}async send(params){let{user_id,title,body,entity_name,entity_id,type,source,channels}=params;for(let channel of channels)switch(channel){case"portal":await this.sendPortalNotification(user_id,title,body,entity_name,entity_id,type,source);break;case"email":await this.sendEmailNotification(user_id,title,body);break;case"sms":this.logger.debug(`[Notification] SMS channel not yet implemented for user ${user_id}`);break;case"telegram":this.logger.debug(`[Notification] Telegram channel not yet implemented for user ${user_id}`);break;case"webhook":this.logger.debug(`[Notification] Webhook channel not yet implemented for user ${user_id}`);break}}async sendPortalNotification(userId,title,body,entityName,entityId,type,source){let notificationsTable=this.getTable("notifications");if(!notificationsTable){this.logger.warn("[Notification] notifications table not found");return}await this.db.insert(notificationsTable).values(toCamel({user_id:userId,title,body:body||null,entity_name:entityName||null,entity_id:entityId||null,type:type||"system",source:source||null,is_seen:!1})),this.logger.debug(`[Notification] Portal notification sent to ${userId}: ${title}`)}async sendEmailNotification(userId,title,body){if(!this.emailService?.isAvailable()){this.logger.warn("[Notification] Email service not available for email notification");return}let usersTable=this.getTable("users");if(!usersTable){this.logger.warn("[Notification] users table not found");return}let user=(await this.db.select({email:this.getCol(usersTable,"email")}).from(usersTable).where(eq7(this.getCol(usersTable,"id"),userId)).limit(1))[0];if(!user?.email){this.logger.warn(`[Notification] No email found for user ${userId}`);return}await this.emailService.sendEmail({to:user.email,subject:title,html:body||title}),this.logger.debug(`[Notification] Email notification sent to ${user.email}: ${title}`)}async getNotifications(userId,options){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return[];let conditions=[eq7(this.getCol(notificationsTable,"userId"),userId)];if(options?.type)conditions.push(eq7(this.getCol(notificationsTable,"type"),options.type));return(await this.db.select().from(notificationsTable).where(and3(...conditions)).orderBy(desc(this.getCol(notificationsTable,"createdAt"))).limit(options?.limit||50).offset(options?.offset||0)).map((r)=>fromCamel(r))}async getUnseenCount(userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return 0;return(await this.db.select().from(notificationsTable).where(and3(eq7(this.getCol(notificationsTable,"userId"),userId),eq7(this.getCol(notificationsTable,"isSeen"),!1)))).length}async markAsSeen(notificationId,userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return!1;return await this.db.update(notificationsTable).set(toCamel({is_seen:!0,seen_at:new Date})).where(and3(eq7(this.getCol(notificationsTable,"id"),notificationId),eq7(this.getCol(notificationsTable,"userId"),userId))),!0}async markAllAsSeen(userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return 0;return(await this.db.update(notificationsTable).set(toCamel({is_seen:!0,seen_at:new Date})).where(and3(eq7(this.getCol(notificationsTable,"userId"),userId),eq7(this.getCol(notificationsTable,"isSeen"),!1))).returning()).length}}var init_Notification=__esm(()=>{init_types4()});function buildGenericAuthUrl(config,state){if(!config.authorizationUrl)throw Error("Generic OAuth provider requires authorizationUrl");let scopes2=config.scopes??[],params=new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",state,...scopes2.length>0?{scope:scopes2.join(" ")}:{},...config.extraAuthParams});return`${config.authorizationUrl}?${params.toString()}`}async function exchangeGenericCode(code,config){if(!config.tokenUrl)throw Error("Generic OAuth provider requires tokenUrl");let tokenRes=await fetch(config.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Generic OAuth token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope};if(!config.userInfoUrl)return{profile:{providerAccountId:tokenData.access_token,rawProfile:tokenData},tokens};let userRes=await fetch(config.userInfoUrl,{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch user info from generic OAuth provider");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.id??rawProfile.sub??rawProfile.user_id??tokenData.access_token,email:rawProfile.email,name:rawProfile.name??rawProfile.display_name??rawProfile.username,avatarUrl:rawProfile.avatar_url??rawProfile.picture??rawProfile.photo,rawProfile},tokens}}function buildGithubAuthUrl(config,state){let scopes2=config.scopes??["read:user","user:email"];return`https://github.com/login/oauth/authorize?${new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,scope:scopes2.join(" "),state,...config.extraAuthParams}).toString()}`}async function exchangeGithubCode(code,config){let tokenRes=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,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`GitHub token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`GitHub OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${tokenData.access_token}`,Accept:"application/vnd.github+json"}});if(!userRes.ok)throw Error("Failed to fetch GitHub user info");let rawProfile=await userRes.json(),email=rawProfile.email;if(!email)try{let emailsRes=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${tokenData.access_token}`,Accept:"application/vnd.github+json"}});if(emailsRes.ok){let emails=await emailsRes.json();email=emails.find((e)=>e.primary&&e.verified)?.email??emails[0]?.email}}catch{}return{profile:{providerAccountId:String(rawProfile.id),email,name:rawProfile.name??rawProfile.login,avatarUrl:rawProfile.avatar_url,rawProfile},tokens}}function buildGoogleAuthUrl(config,state){let scopes2=config.scopes??["openid","email","profile"];return`https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",scope:scopes2.join(" "),state,access_type:"offline",prompt:"select_account",...config.extraAuthParams}).toString()}`}async function exchangeGoogleCode(code,config){let tokenRes=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Google token exchange failed: ${err}`)}let tokenData=await tokenRes.json(),tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://www.googleapis.com/oauth2/v3/userinfo",{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch Google user info");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.sub,email:rawProfile.email,name:rawProfile.name,avatarUrl:rawProfile.picture,rawProfile},tokens}}function getMicrosoftBaseUrl(config){return`https://login.microsoftonline.com/${config.tenantId??"common"}/oauth2/v2.0`}function buildMicrosoftAuthUrl(config,state){let scopes2=config.scopes??["openid","email","profile","User.Read"],params=new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",scope:scopes2.join(" "),state,response_mode:"query",...config.extraAuthParams});return`${getMicrosoftBaseUrl(config)}/authorize?${params.toString()}`}async function exchangeMicrosoftCode(code,config){let tokenRes=await fetch(`${getMicrosoftBaseUrl(config)}/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Microsoft token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`Microsoft OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://graph.microsoft.com/v1.0/me",{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch Microsoft user info");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.id,email:rawProfile.mail??rawProfile.userPrincipalName,name:rawProfile.displayName,avatarUrl:void 0,rawProfile},tokens}}import{randomBytes as randomBytes2}from"crypto";class OAuthService{config;stateStore=new Map;cleanupInterval=null;constructor(config){this.config=config;let ttl=(config.stateTtlSeconds??600)*1000;this.cleanupInterval=setInterval(()=>{let now=Date.now();for(let[key,val]of this.stateStore.entries())if(val.expiresAt<now)this.stateStore.delete(key)},ttl)}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isProviderEnabled(provider){return!!(this.config.enabled&&this.config.providers[provider])}getEnabledProviders(){if(!this.config.enabled)return[];return Object.keys(this.config.providers)}buildAuthorizationUrl(provider,linkUserId,redirectUrl){let providerConfig=this.config.providers[provider];if(!providerConfig)throw Error(`OAuth provider "${provider}" is not configured`);let statePayload={provider,linkUserId,redirectUrl,createdAt:Date.now()},state=randomBytes2(32).toString("hex"),ttl=(this.config.stateTtlSeconds??600)*1000;switch(this.stateStore.set(state,{payload:statePayload,expiresAt:Date.now()+ttl}),provider){case"google":return buildGoogleAuthUrl(providerConfig,state);case"github":return buildGithubAuthUrl(providerConfig,state);case"microsoft":return buildMicrosoftAuthUrl(providerConfig,state);default:return buildGenericAuthUrl(providerConfig,state)}}consumeState(state){let entry=this.stateStore.get(state);if(!entry)return null;if(entry.expiresAt<Date.now())return this.stateStore.delete(state),null;return this.stateStore.delete(state),entry.payload}async exchangeCode(provider,code){let providerConfig=this.config.providers[provider];if(!providerConfig)throw Error(`OAuth provider "${provider}" is not configured`);switch(provider){case"google":return exchangeGoogleCode(code,providerConfig);case"github":return exchangeGithubCode(code,providerConfig);case"microsoft":return exchangeMicrosoftCode(code,providerConfig);default:return exchangeGenericCode(code,providerConfig)}}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 init_OAuthService=()=>{};var init_OAuth=__esm(()=>{init_OAuthService()});class RateLimiter{redis;logger;config;constructor(deps){this.redis=deps.redis,this.logger=deps.logger,this.config=this.mergeConfig(deps.config)}mergeConfig(config){return{enabled:config.enabled??DEFAULT_CONFIG4.enabled,strategy:config.strategy??DEFAULT_CONFIG4.strategy,keyPrefix:config.keyPrefix??DEFAULT_CONFIG4.keyPrefix,authRoutes:{window:config.authRoutes?.window??DEFAULT_CONFIG4.authRoutes.window,max:config.authRoutes?.max??DEFAULT_CONFIG4.authRoutes.max,login:{window:config.authRoutes?.login?.window??DEFAULT_AUTH_LOGIN.window,max:config.authRoutes?.login?.max??DEFAULT_AUTH_LOGIN.max,blockDuration:config.authRoutes?.login?.blockDuration??DEFAULT_AUTH_LOGIN.blockDuration},register:{window:config.authRoutes?.register?.window??DEFAULT_AUTH_REGISTER.window,max:config.authRoutes?.register?.max??DEFAULT_AUTH_REGISTER.max,blockDuration:config.authRoutes?.register?.blockDuration??DEFAULT_AUTH_REGISTER.blockDuration},passwordReset:{window:config.authRoutes?.passwordReset?.window??DEFAULT_AUTH_PASSWORD_RESET.window,max:config.authRoutes?.passwordReset?.max??DEFAULT_AUTH_PASSWORD_RESET.max,blockDuration:config.authRoutes?.passwordReset?.blockDuration??DEFAULT_AUTH_PASSWORD_RESET.blockDuration},magicLink:{window:config.authRoutes?.magicLink?.window??DEFAULT_AUTH_MAGIC_LINK.window,max:config.authRoutes?.magicLink?.max??DEFAULT_AUTH_MAGIC_LINK.max,blockDuration:config.authRoutes?.magicLink?.blockDuration??DEFAULT_AUTH_MAGIC_LINK.blockDuration}},publicRoutes:{window:config.publicRoutes?.window??DEFAULT_CONFIG4.publicRoutes.window,max:config.publicRoutes?.max??DEFAULT_CONFIG4.publicRoutes.max},privateRoutes:{window:config.privateRoutes?.window??DEFAULT_CONFIG4.privateRoutes.window,max:config.privateRoutes?.max??DEFAULT_CONFIG4.privateRoutes.max},byIp:config.byIp??DEFAULT_CONFIG4.byIp,byUserId:config.byUserId??DEFAULT_CONFIG4.byUserId,byEndpoint:config.byEndpoint??DEFAULT_CONFIG4.byEndpoint,skipSuccessfulRequests:config.skipSuccessfulRequests??DEFAULT_CONFIG4.skipSuccessfulRequests,headers:{remaining:config.headers?.remaining??DEFAULT_CONFIG4.headers.remaining,reset:config.headers?.reset??DEFAULT_CONFIG4.headers.reset,limit:config.headers?.limit??DEFAULT_CONFIG4.headers.limit},whitelist:config.whitelist??DEFAULT_CONFIG4.whitelist,blacklist:config.blacklist??DEFAULT_CONFIG4.blacklist}}parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h|d)$/);if(!match||!match[1]||!match[2])return 60000;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*24*60*60*1000;default:return 60000}}buildKey(params){let parts=[this.config.keyPrefix,params.category];if(params.authType&¶ms.authType!=="other")parts.push(params.authType);if(this.config.byIp&¶ms.ip)parts.push(`ip:${params.ip}`);if(this.config.byUserId&¶ms.userId)parts.push(`user:${params.userId}`);if(this.config.byEndpoint&¶ms.endpoint)parts.push(`ep:${params.endpoint.replace(/\//g,"_")}`);return parts.join(":")}getLimits(category,authType){if(category==="auth"){if(authType&&authType!=="other"){let authConfig=this.config.authRoutes[authType];if(authConfig)return authConfig}return{window:this.config.authRoutes.window,max:this.config.authRoutes.max}}if(category==="public")return this.config.publicRoutes;return this.config.privateRoutes}isWhitelisted(ip){return this.config.whitelist.some((pattern)=>{if(pattern.includes("*"))return new RegExp(`^${pattern.replace(/\*/g,".*")}$`).test(ip);return pattern===ip})}isBlacklisted(ip){return this.config.blacklist.some((pattern)=>{if(pattern.includes("*"))return new RegExp(`^${pattern.replace(/\*/g,".*")}$`).test(ip);return pattern===ip})}async readRedis(key){let result=await this.redis.read(key);if(result.success)return result.data;return null}async check(params){if(!this.config.enabled)return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isWhitelisted(params.ip))return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isBlacklisted(params.ip))return this.logger.warn(`[RateLimit] Blacklisted IP: ${params.ip}`),{allowed:!1,remaining:0,resetAt:Date.now()+86400000,limit:0,retryAfter:86400};let key=this.buildKey(params),limits=this.getLimits(params.category,params.authType),windowMs=this.parseTimeToMs(limits.window),blockKey=`${key}:blocked`,isBlocked=await this.readRedis(blockKey);if(isBlocked&&isBlocked.until>Date.now()){let retryAfter=Math.ceil((isBlocked.until-Date.now())/1000);return this.logger.warn(`[RateLimit] Blocked: ${key}, retry after ${retryAfter}s`),{allowed:!1,remaining:0,resetAt:isBlocked.until,limit:limits.max,retryAfter}}if(this.config.strategy==="sliding-window")return this.slidingWindowCheck(key,limits.max,windowMs,limits.blockDuration);if(this.config.strategy==="fixed-window")return this.fixedWindowCheck(key,limits.max,windowMs,limits.blockDuration);return this.tokenBucketCheck(key,limits.max,windowMs)}async slidingWindowCheck(key,max,windowMs,blockDuration){let now=Date.now(),windowStart=now-windowMs,dataKey=`${key}:sw`,timestamps=(await this.readRedis(dataKey))?.timestamps||[];timestamps=timestamps.filter((ts)=>ts>windowStart);let count=timestamps.length,firstTimestamp=timestamps[0],resetAt=firstTimestamp!==void 0?firstTimestamp+windowMs:now+windowMs;if(count>=max){if(blockDuration){let blockMs=this.parseTimeToMs(blockDuration);await this.redis.create(`${key}:blocked`,{until:now+blockMs},Math.ceil(blockMs/1000))}return{allowed:!1,remaining:0,resetAt,limit:max,retryAfter:Math.ceil((resetAt-now)/1000)}}return timestamps.push(now),await this.redis.create(dataKey,{timestamps},Math.ceil(windowMs/1000)+1),{allowed:!0,remaining:max-timestamps.length,resetAt,limit:max}}async fixedWindowCheck(key,max,windowMs,blockDuration){let now=Date.now(),windowId=Math.floor(now/windowMs),dataKey=`${key}:fw:${windowId}`,resetAt=(windowId+1)*windowMs,count=(await this.readRedis(dataKey))?.count||0;if(count>=max){if(blockDuration){let blockMs=this.parseTimeToMs(blockDuration);await this.redis.create(`${key}:blocked`,{until:now+blockMs},Math.ceil(blockMs/1000))}return{allowed:!1,remaining:0,resetAt,limit:max,retryAfter:Math.ceil((resetAt-now)/1000)}}return await this.redis.create(dataKey,{count:count+1},Math.ceil(windowMs/1000)+1),{allowed:!0,remaining:max-(count+1),resetAt,limit:max}}async tokenBucketCheck(key,max,windowMs){let now=Date.now(),refillRate=max/windowMs,dataKey=`${key}:tb`,data=await this.readRedis(dataKey),tokens=data?.tokens??max,lastRefill=data?.lastRefill??now,refill=(now-lastRefill)*refillRate;if(tokens=Math.min(max,tokens+refill),tokens<1){let waitTime=Math.ceil((1-tokens)/refillRate);return{allowed:!1,remaining:0,resetAt:now+waitTime,limit:max,retryAfter:Math.ceil(waitTime/1000)}}return tokens-=1,await this.redis.create(dataKey,{tokens,lastRefill:now},Math.ceil(windowMs/1000)*2),{allowed:!0,remaining:Math.floor(tokens),resetAt:now+windowMs,limit:max}}async decrement(params){if(!this.config.skipSuccessfulRequests)return;let key=this.buildKey(params);if(this.config.strategy==="sliding-window"){let dataKey=`${key}:sw`,data=await this.readRedis(dataKey);if(data?.timestamps?.length){data.timestamps.pop();let windowMs=this.parseTimeToMs(this.getLimits(params.category,params.authType).window);await this.redis.create(dataKey,data,Math.ceil(windowMs/1000)+1)}}else if(this.config.strategy==="fixed-window"){let windowMs=this.parseTimeToMs(this.getLimits(params.category,params.authType).window),windowId=Math.floor(Date.now()/windowMs),dataKey=`${key}:fw:${windowId}`,data=await this.readRedis(dataKey);if(data?.count)await this.redis.create(dataKey,{count:data.count-1},Math.ceil(windowMs/1000)+1)}}getHeaders(result){let headers={};return headers[this.config.headers.remaining]=String(result.remaining),headers[this.config.headers.reset]=String(Math.ceil(result.resetAt/1000)),headers[this.config.headers.limit]=String(result.limit),headers}isEnabled(){return this.config.enabled}}var DEFAULT_AUTH_LOGIN,DEFAULT_AUTH_REGISTER,DEFAULT_AUTH_PASSWORD_RESET,DEFAULT_AUTH_MAGIC_LINK,DEFAULT_CONFIG4;var init_RateLimiter=__esm(()=>{DEFAULT_AUTH_LOGIN={window:"15m",max:5,blockDuration:"30m"},DEFAULT_AUTH_REGISTER={window:"1h",max:3,blockDuration:"1h"},DEFAULT_AUTH_PASSWORD_RESET={window:"1h",max:3,blockDuration:"1h"},DEFAULT_AUTH_MAGIC_LINK={window:"1h",max:5,blockDuration:"1h"},DEFAULT_CONFIG4={enabled:!0,strategy:"sliding-window",keyPrefix:"rl:",authRoutes:{window:"1m",max:10,login:DEFAULT_AUTH_LOGIN,register:DEFAULT_AUTH_REGISTER,passwordReset:DEFAULT_AUTH_PASSWORD_RESET,magicLink:DEFAULT_AUTH_MAGIC_LINK},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 exports_schema={};__export(exports_schema,{ensureSchemaExists:()=>ensureSchemaExists});import{sql as sql2}from"drizzle-orm";var validateIdentifier=(name)=>{if(!name||name.length>63)throw Error(`Invalid identifier: must be 1-63 characters, got ${name.length}`);if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name))throw Error(`Invalid identifier: "${name}" contains unsafe characters`);return name},ensureSchemaExists=async(db,schemaName)=>{let safeName=validateIdentifier(schemaName);await db.execute(sql2.raw(`CREATE SCHEMA IF NOT EXISTS "${safeName}"`))};var init_schema=()=>{};var rowToTenantRecord=(row)=>({id:String(row.id||""),subdomain:String(row.subdomain||""),schemaName:String(row.schemaName||row.schema_name||""),companyId:String(row.companyId||row.company_id||""),companyName:row.companyName!=null?String(row.companyName):row.company_name!=null?String(row.company_name):null,godAdminEmail:String(row.godAdminEmail||row.god_admin_email||""),status:parseStatus(row.status),plan:row.plan!=null?String(row.plan):null,domain:row.domain!=null?String(row.domain):null,settings:parseJsonbToConfig(row.settings),trustedSources:parseTrustedSources(row.trustedSources||row.trusted_sources),maxUsers:row.maxUsers!=null?Number(row.maxUsers):row.max_users!=null?Number(row.max_users):null,provisionedAt:row.provisionedAt!=null?String(row.provisionedAt):row.provisioned_at!=null?String(row.provisioned_at):null,suspendedAt:row.suspendedAt!=null?String(row.suspendedAt):row.suspended_at!=null?String(row.suspended_at):null,suspendedReason:row.suspendedReason!=null?String(row.suspendedReason):row.suspended_reason!=null?String(row.suspended_reason):null}),rowToFeatureRecord=(row,parseConfig)=>({id:String(row.id||""),tenantId:String(row.tenantId||row.tenant_id||""),featureName:String(row.featureName||row.feature_name||""),enabled:Boolean(row.enabled),featureConfig:parseConfig(row.config)}),parseStatus=(value)=>{let valid=["provisioning","active","suspended","archived"],str=String(value||"provisioning");return valid.includes(str)?str:"provisioning"},parseJsonbToConfig=(value)=>{if(!value||typeof value!=="object")return{};let result={};for(let[k,v]of Object.entries(value))if(typeof v==="string"||typeof v==="number"||typeof v==="boolean")result[k]=v;return result},parseTrustedSources=(value)=>{if(!Array.isArray(value))return[];return value.map((item)=>{let entry=item;return{allowHeaderAuth:entry.allowHeaderAuth===!0||entry.allow_header_auth===!0,allowedIps:Array.isArray(entry.allowedIps||entry.allowed_ips)?entry.allowedIps||entry.allowed_ips:void 0,allowedServices:Array.isArray(entry.allowedServices||entry.allowed_services)?entry.allowedServices||entry.allowed_services:void 0}})},extractSubdomain=(host)=>{let hostWithoutPort=host.split(":")[0]||"";if(hostWithoutPort==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(hostWithoutPort))return null;let parts=hostWithoutPort.split(".");if(parts.length<3)return null;let subdomain=parts[0]||"";if(!subdomain||subdomain==="www")return null;return subdomain},isIpInCidr=(ip,cidr)=>{let[cidrIp,prefixStr]=cidr.split("/");if(!cidrIp||!prefixStr)return!1;let prefix=Number.parseInt(prefixStr,10);if(Number.isNaN(prefix))return!1;let ipParts=ip.split(".").map(Number),cidrParts=cidrIp.split(".").map(Number);if(ipParts.length!==4||cidrParts.length!==4)return!1;let ipNum=(ipParts[0]||0)<<24|(ipParts[1]||0)<<16|(ipParts[2]||0)<<8|(ipParts[3]||0),cidrNum=(cidrParts[0]||0)<<24|(cidrParts[1]||0)<<16|(cidrParts[2]||0)<<8|(cidrParts[3]||0),mask=~((1<<32-prefix)-1);return(ipNum&mask)===(cidrNum&mask)},isTrustedSource=(tenant,request,authMode)=>{let trustedSources=tenant.trustedSources;if(!trustedSources||!Array.isArray(trustedSources)||trustedSources.length===0)return authMode==="consumer";let clientIp=request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||request.headers.get("x-real-ip")?.trim()||"",serviceId=request.headers.get("x-service-id")||"";for(let source of trustedSources){if(!source.allowHeaderAuth)continue;if(source.allowedIps&&source.allowedIps.length>0){if(source.allowedIps.some((allowedIp)=>{if(allowedIp.includes("/"))return isIpInCidr(clientIp,allowedIp);return clientIp===allowedIp}))return!0}if(source.allowedServices&&source.allowedServices.length>0){if(source.allowedServices.includes(serviceId))return!0}if((!source.allowedIps||source.allowedIps.length===0)&&(!source.allowedServices||source.allowedServices.length===0))return!0}return!1};function getDatabaseAuthMode(){return process.env.DATABASE_AUTH_MODE||"password"}function getRedisAuthMode(){return process.env.REDIS_AUTH_MODE||"password"}async function acquireToken(scope,label){let{DefaultAzureCredential,ManagedIdentityCredential,ClientSecretCredential}=await import("@azure/identity"),authMode=scope==="https://ossrdbms-aad.database.windows.net/.default"?getDatabaseAuthMode():getRedisAuthMode(),clientId=process.env.AZURE_CLIENT_ID||"",tenantId=process.env.AZURE_TENANT_ID||"",clientSecret=process.env.AZURE_CLIENT_SECRET||"",credential;if(authMode==="managed_identity")credential=clientId?new ManagedIdentityCredential(clientId):new DefaultAzureCredential;else if(authMode==="service_principal"){if(!tenantId||!clientId||!clientSecret)throw Error("[azure-auth] service_principal auth requires AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET");credential=new ClientSecretCredential(tenantId,clientId,clientSecret)}else throw Error(`[azure-auth] Unsupported auth mode: ${authMode}`);let result=await credential.getToken(scope);if(!result)throw Error(`[azure-auth] Failed to acquire token for ${label}`);return console.log(`[azure-auth] ${label} token acquired, expires at ${new Date(result.expiresOnTimestamp).toISOString()}`),{token:result.token,expiresAt:result.expiresOnTimestamp}}async function getPostgresToken(){let now=Date.now();if(pgCachedToken&&now<pgTokenExpiresAt-300000)return pgCachedToken;let{token,expiresAt}=await acquireToken("https://ossrdbms-aad.database.windows.net/.default","PostgreSQL");return pgCachedToken=token,pgTokenExpiresAt=expiresAt,pgCachedToken}async function getRedisToken(){let now=Date.now();if(redisCachedToken&&now<redisTokenExpiresAt-300000)return redisCachedToken;let{token,expiresAt}=await acquireToken("https://redis.azure.com/.default","Redis");return redisCachedToken=token,redisTokenExpiresAt=expiresAt,redisCachedToken}function getRedisTokenExpiresAt(){return redisTokenExpiresAt}var pgCachedToken=null,pgTokenExpiresAt=0,redisCachedToken=null,redisTokenExpiresAt=0;var exports_Azure={};__export(exports_Azure,{getRedisTokenExpiresAt:()=>getRedisTokenExpiresAt,getRedisToken:()=>getRedisToken,getRedisAuthMode:()=>getRedisAuthMode,getPostgresToken:()=>getPostgresToken,getDatabaseAuthMode:()=>getDatabaseAuthMode});var init_Azure=()=>{};import{access,mkdir as mkdir2}from"fs/promises";import{dirname,resolve}from"path";var DEFAULT_CONFIG5,FILE_SIZE_UNITS,resolvePath=(path2)=>{if(!path2||typeof path2!=="string")throw createFileManagerError("INVALID_PATH","Path must be a non-empty string",path2,"resolvePath");return resolve(path2)},extractDirectoryPath=(filePath)=>{let resolvedPath=resolvePath(filePath);return dirname(resolvedPath)},ensureDirectoryExists=async(dirPath)=>{let resolvedPath=resolve(dirPath);try{await mkdir2(resolvedPath,{recursive:!0})}catch(error){if(error.code!=="EEXIST")throw createFileManagerError("DIRECTORY_CREATE_FAILED",`Failed to create directory: ${resolvedPath}`,resolvedPath,"ensureDirectory")}},formatFileSize=(bytes)=>{let size=bytes,unitIndex=0;while(size>=1024&&unitIndex<FILE_SIZE_UNITS.length-1)size/=1024,unitIndex++;return`${size.toFixed(2)} ${FILE_SIZE_UNITS[unitIndex]}`},validateFileExtension=(fileName,expectedExtension)=>{return fileName.toLowerCase().endsWith(expectedExtension.toLowerCase())},ensureFileExtension=(fileName,extension)=>{let normalizedExtension=extension.startsWith(".")?extension:`.${extension}`;if(validateFileExtension(fileName,normalizedExtension))return fileName;return`${fileName}${normalizedExtension}`},createFileManagerError=(code,message,path2,operation)=>{return{code,message,path:path2,operation:operation||"unknown"}},safeJsonStringify=(data)=>{try{return JSON.stringify(data,null,2)}catch{return"{}"}},executeBulkOperation=async(items,operation,concurrency=DEFAULT_CONFIG5.maxConcurrency)=>{let results=[];for(let i=0;i<items.length;i+=concurrency){let batch3=items.slice(i,i+concurrency),batchPromises=[];for(let item of batch3)batchPromises.push(operation(item));let batchResults=await Promise.allSettled(batchPromises);results.push(...batchResults)}return results},validateConfig=(config,options={})=>{let errors=[],warnings=[],strict=options.strict??!0;if(config.defaultEncoding!==void 0){if(!["utf-8","utf8","ascii","base64","hex"].includes(config.defaultEncoding))errors.push(`Invalid defaultEncoding: ${config.defaultEncoding}`)}if(config.maxConcurrency!==void 0){if(!Number.isInteger(config.maxConcurrency)||config.maxConcurrency<1)errors.push("maxConcurrency must be a positive integer");if(config.maxConcurrency>50)warnings.push("maxConcurrency > 50 may cause performance issues")}if(config.defaultCreateDir!==void 0&&typeof config.defaultCreateDir!=="boolean")errors.push("defaultCreateDir must be a boolean");if(config.defaultRecursive!==void 0&&typeof config.defaultRecursive!=="boolean")errors.push("defaultRecursive must be a boolean");if(strict&&!options.allowUnknownKeys){let validKeys=["defaultEncoding","defaultCreateDir","defaultRecursive","maxConcurrency"],configKeys=Object.keys(config);for(let key of configKeys)if(!validKeys.includes(key))errors.push(`Unknown configuration key: ${key}`)}return{isValid:errors.length===0,errors,warnings}},mergeConfig=(partial,base=DEFAULT_CONFIG5)=>{let validation=validateConfig(partial);if(!validation.isValid)throw createFileManagerError("CONFIG_VALIDATION_FAILED",`Configuration validation failed: ${validation.errors.join(", ")}`,void 0,"mergeConfig");return{...base,...partial}},parsePermissions=(mode)=>{let parseOctal=(octal)=>({read:Boolean(octal&4),write:Boolean(octal&2),execute:Boolean(octal&1)}),ownerMode=mode>>6&7,groupMode=mode>>3&7,othersMode=mode&7;return{owner:parseOctal(ownerMode),group:parseOctal(groupMode),others:parseOctal(othersMode)}},validatePermissionMode=(mode)=>{return Number.isInteger(mode)&&mode>=0&&mode<=511};var init_utils4=__esm(()=>{DEFAULT_CONFIG5={defaultEncoding:"utf-8",defaultCreateDir:!0,defaultRecursive:!0,maxConcurrency:5},FILE_SIZE_UNITS=["B","KB","MB","GB","TB"]});import{copyFile,rename,unlink as unlink2}from"fs/promises";import{basename,dirname as dirname2,extname,join as join2}from"path";var DEFAULT_ATOMIC_CONFIG,generateTempPath=(originalPath,suffix=".tmp")=>{let resolvedPath=resolvePath(originalPath),timestamp=Date.now(),random=Math.random().toString(36).substring(2,8);return`${resolvedPath}${suffix}.${timestamp}.${random}`},generateBackupPath=(originalPath,backupDir,useTimestamp=!0)=>{let resolvedPath=resolvePath(originalPath),dir=backupDir?resolvePath(backupDir):dirname2(resolvedPath),name=basename(resolvedPath),ext=extname(name),nameWithoutExt=basename(name,ext),timestamp=useTimestamp?`.${new Date().toISOString().replace(/[:.]/g,"-")}`:"",backupName=`${nameWithoutExt}.backup${timestamp}${ext}`;return join2(dir,backupName)},atomicWrite=async({path:path2,data,tempSuffix=DEFAULT_ATOMIC_CONFIG.tempSuffix,backup=DEFAULT_ATOMIC_CONFIG.backup,sync=DEFAULT_ATOMIC_CONFIG.sync})=>{let resolvedPath=resolvePath(path2),tempPath=generateTempPath(resolvedPath,tempSuffix),backupPath;try{if(await ensureDirectoryExists(extractDirectoryPath(resolvedPath)),backup){if(await Bun.file(resolvedPath).exists())backupPath=generateBackupPath(resolvedPath),await copyFile(resolvedPath,backupPath)}let bytesWritten=await Bun.write(tempPath,data);return await rename(tempPath,resolvedPath),{success:!0,bytesWritten,tempPath,backupPath}}catch(error){try{await unlink2(tempPath)}catch{}throw createFileManagerError("ATOMIC_WRITE_FAILED",`Atomic write failed: ${error}`,resolvedPath,"atomicWrite")}},atomicJsonWrite=async(path2,data,options={})=>{let jsonString=JSON.stringify(data,null,2);return atomicWrite({path:path2,data:jsonString,...options})},createBackup=async({sourcePath,backupDir,keepOriginal=!0,timestamp=DEFAULT_ATOMIC_CONFIG.timestamp})=>{let resolvedSource=resolvePath(sourcePath);if(!await Bun.file(resolvedSource).exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"createBackup");let backupPath=generateBackupPath(resolvedSource,backupDir,timestamp);if(await ensureDirectoryExists(dirname2(backupPath)),keepOriginal)await copyFile(resolvedSource,backupPath);else await rename(resolvedSource,backupPath);return backupPath},restoreFromBackup=async(backupPath,targetPath,deleteBackup=!1)=>{let resolvedBackup=resolvePath(backupPath),resolvedTarget=resolvePath(targetPath);if(!await Bun.file(resolvedBackup).exists())throw createFileManagerError("BACKUP_NOT_FOUND",`Backup file not found: ${backupPath}`,resolvedBackup,"restoreFromBackup");try{if(await ensureDirectoryExists(extractDirectoryPath(resolvedTarget)),deleteBackup)await rename(resolvedBackup,resolvedTarget);else await copyFile(resolvedBackup,resolvedTarget);return!0}catch(error){return console.error(`Error restoring from backup ${backupPath}:`,error),!1}},safeUpdate=async(path2,updateFunction,options={})=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),backupPath;try{if(await file.exists())backupPath=await createBackup({sourcePath:resolvedPath,keepOriginal:!0,timestamp:!0});let currentData=await file.exists()?await file.text():"",newData=await updateFunction(currentData),result=await atomicWrite({path:resolvedPath,data:newData,backup:!1,...options});return{success:result.success,bytesWritten:result.bytesWritten,tempPath:result.tempPath,backupPath}}catch(error){if(backupPath)try{await restoreFromBackup(backupPath,resolvedPath,!1)}catch(rollbackError){console.error("Rollback failed:",rollbackError)}throw error}},batchAtomicWrite=async(operations)=>{let successful=[],failed=[];for(let operation of operations)try{let result=await atomicWrite(operation);successful.push(result)}catch(error){failed.push({operation,error})}return{successful,failed}};var init_atomic=__esm(()=>{init_utils4();DEFAULT_ATOMIC_CONFIG={tempSuffix:".tmp",backup:!1,sync:!0,timestamp:!0}});import{chmod,stat as stat2}from"fs/promises";var PERMISSION_MODES,setFilePermissions=async(path2,mode)=>{let resolvedPath=resolvePath(path2);if(!validatePermissionMode(mode))throw createFileManagerError("INVALID_PERMISSION_MODE",`Invalid permission mode: ${mode.toString(8)}`,resolvedPath,"setFilePermissions");try{return await chmod(resolvedPath,mode),!0}catch(error){return console.error(`Error setting permissions for ${path2}:`,error),!1}},getFilePermissions=async(path2)=>{let resolvedPath=resolvePath(path2);try{let mode=(await stat2(resolvedPath)).mode&511,permissions=parsePermissions(mode);return{path:resolvedPath,mode,owner:permissions.owner,group:permissions.group,others:permissions.others}}catch(error){throw createFileManagerError("PERMISSION_READ_FAILED",`Failed to read permissions: ${error}`,resolvedPath,"getFilePermissions")}},hasPermissions=async(path2,requiredMode)=>{try{return((await getFilePermissions(path2)).mode&requiredMode)===requiredMode}catch{return!1}},makeReadable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|256;return setFilePermissions(path2,newMode)},makeWritable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|128;return setFilePermissions(path2,newMode)},makeExecutable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|64;return setFilePermissions(path2,newMode)},makeReadOnly=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode&-147;return setFilePermissions(path2,newMode)},setCommonPermissions=async(path2,pattern)=>{let mode=PERMISSION_MODES[pattern];return setFilePermissions(path2,mode)};var init_permissions=__esm(()=>{init_utils4();PERMISSION_MODES={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 DEFAULT_STREAM_CONFIG,createFileWriter=async(path2,options={})=>{let resolvedPath=resolvePath(path2),config={...DEFAULT_STREAM_CONFIG,...options};await ensureDirectoryExists(extractDirectoryPath(resolvedPath));let writer=Bun.file(resolvedPath).writer({highWaterMark:config.highWaterMark}),isClosed=!1;return{write:(chunk)=>{if(isClosed)throw createFileManagerError("WRITER_CLOSED","Cannot write to closed writer",resolvedPath,"streamWrite");try{let result=writer.write(chunk);if(config.autoFlush)writer.flush();return result}catch(error){throw createFileManagerError("WRITE_FAILED",`Failed to write chunk: ${error}`,resolvedPath,"streamWrite")}},flush:()=>{if(isClosed)return 0;try{return writer.flush()}catch(error){throw createFileManagerError("FLUSH_FAILED",`Failed to flush writer: ${error}`,resolvedPath,"streamFlush")}},end:async(error)=>{if(isClosed)return 0;try{let result=await writer.end(error);return isClosed=!0,result}catch(err){throw isClosed=!0,createFileManagerError("END_FAILED",`Failed to end writer: ${err}`,resolvedPath,"streamEnd")}},ref:()=>{if(!isClosed)writer.ref()},unref:()=>{if(!isClosed)writer.unref()}}},writeStream=async(path2,chunks,options={})=>{let writer=await createFileWriter(path2,options),totalBytes=0;try{for(let chunk of chunks){let bytesWritten=writer.write(chunk);totalBytes+=bytesWritten}return await writer.flush(),await writer.end(),totalBytes}catch(error){try{await writer.end(error)}catch{}throw error}},appendStream=async(path2,chunks,options={})=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),existingContent=await file.exists()?await file.arrayBuffer():new ArrayBuffer(0),allChunks=[];if(existingContent.byteLength>0)allChunks.push(existingContent);return allChunks.push(...chunks),writeStream(resolvedPath,allChunks,options)},copyFileStream=async(sourcePath,destinationPath,options={})=>{let resolvedSource=resolvePath(sourcePath),sourceFile=Bun.file(resolvedSource);if(!await sourceFile.exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"copyFileStream");let sourceStream=sourceFile.stream(),writer=await createFileWriter(destinationPath,options),totalBytes=0;try{let reader=sourceStream.getReader();while(!0){let{done,value}=await reader.read();if(done)break;let bytesWritten=writer.write(value);totalBytes+=bytesWritten}return await writer.flush(),await writer.end(),totalBytes}catch(error){try{await writer.end(error)}catch{}throw error}},readFileStream=async(path2,chunkProcessor)=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath);if(!await file.exists())throw createFileManagerError("FILE_NOT_FOUND",`File not found: ${path2}`,resolvedPath,"readFileStream");let reader=file.stream().getReader();try{while(!0){let{done,value}=await reader.read();if(done)break;await chunkProcessor(value)}}finally{reader.releaseLock()}};var init_streaming=__esm(()=>{init_utils4();DEFAULT_STREAM_CONFIG={highWaterMark:1048576,autoFlush:!0,closeOnEnd:!0}});import{readdir,rm,rmdir,stat as stat3}from"fs/promises";import{extname as extname2,join as join3}from"path";class BunFileManager{static instance;config;constructor(){this.config={...DEFAULT_CONFIG5}}static getInstance(){if(!BunFileManager.instance)BunFileManager.instance=new BunFileManager;return BunFileManager.instance}async createFile({dir,name,data,options={}}){let filePath=resolvePath(join3(dir,name));if(options.createDir!==!1)await ensureDirectoryExists(extractDirectoryPath(filePath));let fileData=options.type?new Blob([data],{type:options.type}):data;return await Bun.write(filePath,fileData)}async createJsonFile(dir,name,data){let fileName=ensureFileExtension(name,".json"),jsonString=safeJsonStringify(data);return this.createFile({dir,name:fileName,data:jsonString,options:{type:"application/json"}})}async createDirectory({path:path2}){await ensureDirectoryExists(path2)}async readFile({path:path2,format="text"}){let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath);if(!await file.exists())throw createFileManagerError("FILE_NOT_FOUND",`File not found: ${path2}`,resolvedPath,"readFile");switch(format){case"text":return await file.text();case"json":return await file.json();case"buffer":return await file.arrayBuffer();case"bytes":return await file.bytes();case"stream":return file.stream();default:return await file.text()}}async readJsonFile(path2){return this.readFile({path:path2,format:"json"})}async getFileInfo(path2){let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),fileName=path2.split("/").pop()||path2,stats=null;try{stats=await stat3(resolvedPath)}catch{}return{name:fileName,path:resolvedPath,size:file.size,type:file.type,exists:await file.exists(),extension:extname2(fileName),createdAt:stats?.birthtime,modifiedAt:stats?.mtime}}async readDirectory({path:path2,recursive=!1}){let resolvedPath=resolvePath(path2);return await readdir(resolvedPath,{recursive,encoding:"utf8"})}async getFilesByExtension(dir,extension){let files=await this.readDirectory({path:dir}),normalizedExt=extension.startsWith(".")?extension:`.${extension}`;return files.filter((file)=>file.endsWith(normalizedExt))}async updateFile({path:path2,data,mode="overwrite"}){let resolvedPath=resolvePath(path2);if(mode==="append"){let combinedData=await this.readFile({path:path2,format:"text"})+data;return await Bun.write(resolvedPath,combinedData)}return await Bun.write(resolvedPath,data)}async updateJsonFile(path2,data,merge=!1){let finalData=data;if(merge)try{let existingData=await this.readJsonFile(path2);if(typeof existingData==="object"&&existingData!==null&&!Array.isArray(existingData)&&typeof data==="object"&&data!==null&&!Array.isArray(data))finalData={...existingData,...data}}catch{}return this.updateFile({path:path2,data:safeJsonStringify(finalData),mode:"overwrite"})}async appendToFile(path2,data){return this.updateFile({path:path2,data,mode:"append"})}async deleteFile(path2){try{let resolvedPath=resolvePath(path2);return await Bun.file(resolvedPath).delete(),!0}catch(error){return console.error(`Error deleting file ${path2}:`,error),!1}}async deleteDirectory({path:path2,recursive=!1}){try{let resolvedPath=resolvePath(path2);if(recursive)await rm(resolvedPath,{recursive:!0,force:!0});else await rmdir(resolvedPath);return!0}catch(error){return console.error(`Error deleting directory ${path2}:`,error),!1}}async deleteFiles(paths){let results=await executeBulkOperation(paths,async(path2)=>{if(!await this.deleteFile(path2))throw Error(`Failed to delete: ${path2}`);return path2}),success=[],failed=[];for(let i=0;i<results.length;i++){let result=results[i],originalPath=paths[i];if(result?.status==="fulfilled")success.push(originalPath||"");else failed.push(originalPath||"")}return{success,failed}}async exists(path2){let resolvedPath=resolvePath(path2);return await Bun.file(resolvedPath).exists()}async copyFile(sourcePath,destinationPath){let resolvedSource=resolvePath(sourcePath),resolvedDestination=resolvePath(destinationPath),sourceFile=Bun.file(resolvedSource);if(!await sourceFile.exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"copyFile");return await ensureDirectoryExists(extractDirectoryPath(resolvedDestination)),await Bun.write(resolvedDestination,sourceFile)}async moveFile(sourcePath,destinationPath){try{return await this.copyFile(sourcePath,destinationPath),await this.deleteFile(sourcePath),!0}catch(error){return console.error(`Error moving file from ${sourcePath} to ${destinationPath}:`,error),!1}}getFormattedFileSize(bytes){return formatFileSize(bytes)}getConfig(){return{...this.config}}updateConfig(newConfig){let validation=validateConfig(newConfig);if(validation.isValid){let mergedConfig=mergeConfig(newConfig,this.config);Object.assign(this.config,mergedConfig)}return validation}validateConfiguration(config){return validateConfig(config)}async createStreamWriter(path2,options={}){return createFileWriter(path2,options)}async writeStream(path2,chunks,options={}){return writeStream(path2,chunks,options)}async appendStream(path2,chunks,options={}){return appendStream(path2,chunks,options)}async copyFileStream(sourcePath,destinationPath,options={}){return copyFileStream(sourcePath,destinationPath,options)}async readFileStream(path2,chunkProcessor){return readFileStream(path2,chunkProcessor)}async setPermissions(path2,mode){return setFilePermissions(path2,mode)}async setPermissionsAdvanced(options){return setFilePermissions(options.path,options.mode)}async getPermissions(path2){return getFilePermissions(path2)}async checkPermissions(path2,requiredMode){return hasPermissions(path2,requiredMode)}async makeFileReadable(path2){return makeReadable(path2)}async makeFileWritable(path2){return makeWritable(path2)}async makeFileExecutable(path2){return makeExecutable(path2)}async makeFileReadOnly(path2){return makeReadOnly(path2)}async setCommonPermission(path2,pattern){return setCommonPermissions(path2,pattern)}async atomicWrite(options){return atomicWrite(options)}async atomicJsonWrite(path2,data,options={}){return atomicJsonWrite(path2,data,options)}async createFileBackup(options){return createBackup(options)}async restoreFileFromBackup(backupPath,targetPath,deleteBackup=!1){return restoreFromBackup(backupPath,targetPath,deleteBackup)}async safeFileUpdate(path2,updateFunction,options={}){return safeUpdate(path2,updateFunction,options)}async batchAtomicOperations(operations){return batchAtomicWrite(operations)}}var init_core=__esm(()=>{init_atomic();init_permissions();init_streaming();init_utils4()});var fileManager;var init_File=__esm(()=>{init_core();init_utils4();init_core();fileManager=BunFileManager.getInstance()});import{Pool}from"pg";var init_Postgre=()=>{};var init_Managers=__esm(()=>{init_Azure();init_Dapr();init_File();init_Postgre();init_Redis()});var exports_utils={};__export(exports_utils,{validatePayload:()=>validatePayload,validateEnvVariables:()=>validateEnvVariables,toAudit:()=>toAudit,signNewAccessToken:()=>signNewAccessToken,sanitizePayload:()=>sanitizePayload,refreshAccessTokenWithLock:()=>refreshAccessTokenWithLock,parseTokenValuesFromHeaders:()=>parseTokenValuesFromHeaders,parseTimeToSeconds:()=>parseTimeToSeconds2,parseQueryParams:()=>parseQueryParams,initiateRedisManager:()=>initiateRedisManager,getRedisManager:()=>getRedisManager,ensureDatabaseExists:()=>ensureDatabaseExists,createAuditLog:()=>createAuditLog,buildPaginationMeta:()=>buildPaginationMeta});function parseTokenValuesFromHeaders(headers,tokenNames){let cookies=(headers.get("cookie")?.split(";")||[]).reduce((acc,cookie)=>{let trimmed=cookie.trim(),eqIndex=trimmed.indexOf("=");if(eqIndex>0)acc[trimmed.slice(0,eqIndex)]=trimmed.slice(eqIndex+1);return acc},{});return{access_token:cookies[tokenNames.access_token]||headers.get("authorization")?.split(" ")[1],refresh_token:cookies[tokenNames.refresh_token],session_token:cookies[tokenNames.session_token]}}async function initiateRedisManager(config){if(!config.redis){console.log("Redis not configured, skipping");return}let rawWithDapr=config.redis.withDapr;if(typeof rawWithDapr==="string"?process.env[rawWithDapr]?.toLowerCase()!=="false":rawWithDapr??!1){redisManagerInstance=new RedisManager({withDapr:!0,stateStoreName:config.redis.stateStoreName});return}let resolvedUrl=config.redis.url?process.env[config.redis.url]:void 0,resolvedHost=config.redis.host?process.env[config.redis.host]:void 0,resolvedPort=config.redis.port?parseInt(process.env[config.redis.port]||"",10):void 0;if((process.env.REDIS_AUTH_MODE||"password")!=="password"){let{getRedisToken:getRedisToken2,getRedisTokenExpiresAt:getRedisTokenExpiresAt2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure)),clientId=process.env.AZURE_CLIENT_ID||"",initialToken=await getRedisToken2();redisManagerInstance=new RedisManager({host:resolvedHost,port:Number.isNaN(resolvedPort)?void 0:resolvedPort,password:initialToken,username:clientId,tls:!0});let scheduleRedisTokenRefresh=()=>{let expiresAt=getRedisTokenExpiresAt2(),refreshIn=Math.max(expiresAt-Date.now()-300000,30000);setTimeout(async()=>{try{let newToken=await getRedisToken2();if(redisManagerInstance)await redisManagerInstance.reauthenticate(clientId,newToken),console.log("[Redis] Entra ID token refreshed successfully");scheduleRedisTokenRefresh()}catch(err){console.error("[Redis] Token refresh failed:",err.message),setTimeout(scheduleRedisTokenRefresh,30000)}},refreshIn)};scheduleRedisTokenRefresh()}else{let resolvedPassword=process.env.REDIS_PASSWORD||void 0;redisManagerInstance=new RedisManager({url:resolvedUrl,host:resolvedHost,port:Number.isNaN(resolvedPort)?void 0:resolvedPort,...resolvedPassword?{password:resolvedPassword}:{}})}}function getRedisManager(){return redisManagerInstance}function parseTimeToSeconds2(timeString){if(typeof timeString==="number")return timeString;if(!timeString||timeString.trim()==="")throw Error("Time string cannot be empty");let match=timeString.trim().match(/^(\d+(?:\.\d+)?)\s*([smhdwMy])$/);if(!match||!match[1]||!match[2])throw Error(`Invalid time format: "${timeString}". Expected format: "75s", "10m", "2h", "1d", "1w", "2M", "1y"`);let value=parseFloat(match[1]),unit=match[2],multiplier={s:1,m:60,h:3600,d:86400,w:604800,M:2592000,y:31536000}[unit];if(multiplier===void 0)throw Error(`Unknown time unit: "${unit}"`);let seconds=Math.floor(value*multiplier);if(seconds<=0)throw Error(`Time value must be positive: "${timeString}"`);return seconds}function signNewAccessToken({sessionData,options,refreshTokenId,roles,claims}){let secretEnvName=options.authentication?.accessToken?.secret;if(!secretEnvName)throw Error("Access token secret env name is not configured");let secret=process.env[secretEnvName];if(!secret)throw Error(`Access token secret env "${secretEnvName}" is not set`);return signJWT({subject:sessionData.userId,issuer:options.authentication?.accessToken?.issuer,audience:options.authentication?.accessToken?.audience,algorithm:options.authentication?.accessToken?.algorithm,expiresInSeconds:parseTimeToSeconds2(options.authentication?.accessToken?.expiresIn??"15m"),sessionId:sessionData.id,customClaims:{refreshTokenId,...roles&&roles.length>0?{roles}:{},...claims&&claims.length>0?{claims}:{}}},secret)}function toAudit(payload,summary){return payload?{entityName:payload.entity_name,entityId:payload.entity_id===" - "?null:payload.entity_id,operation:payload.operation_type,userId:payload.user_id==="unknown"?null:payload.user_id,summary,ipAddress:payload.ip_address,userAgent:payload.user_agent,path:payload.path,query:payload.query}:void 0}function reconstructBracketParams(query){let result={},arrayGroups={};for(let[key,value]of Object.entries(query)){let match=key.match(/^(\w+)\[\d*\]\[(\w+)\]$/),arrayName=match?.[1],prop=match?.[2];if(arrayName&&prop){if(!arrayGroups[arrayName])arrayGroups[arrayName]={};let group=arrayGroups[arrayName];if(!group[prop])group[prop]=[];let arr=group[prop];if(Array.isArray(value))for(let v of value)arr.push(v);else arr.push(value)}else result[key]=value}for(let[arrayName,props]of Object.entries(arrayGroups)){let propNames=Object.keys(props);if(propNames.length===0)continue;let maxLen=Math.max(...propNames.map((p)=>(props[p]||[]).length)),items=[];for(let i=0;i<maxLen;i++){let item={};for(let p of propNames)item[p]=(props[p]||[])[i];items.push(item)}result[arrayName]=items}return result}function parseQueryParams(query){let q=reconstructBracketParams(query),parseJSONOrPassthrough=(value)=>{if(value===void 0||value===null)return;if(typeof value==="object")return value;if(typeof value==="string")try{return JSON.parse(value)}catch{return}return},page=q.page?parseInt(q.page,10):1,limit=q.limit?parseInt(q.limit,10):20,offset=q.offset?parseInt(q.offset,10):(page-1)*limit;return{page,limit,offset,search:q.search,searchFields:q.searchFields?q.searchFields.split(","):void 0,filters:parseJSONOrPassthrough(q.filters),sort:parseJSONOrPassthrough(q.sort),select:q.select?q.select.split(","):void 0,with:parseJSONOrPassthrough(q.with),distinct:q.distinct==="true",distinctOn:q.distinctOn?q.distinctOn.split(","):void 0}}function buildPaginationMeta(page,limit,offset,totalItems){let totalPages=Math.ceil(totalItems/limit),hasNextPage=page<totalPages,hasPrevPage=page>1;return{page,limit,offset,totalItems,totalPages,hasNextPage,hasPrevPage,nextPage:hasNextPage?page+1:null,prevPage:hasPrevPage?page-1:null}}function getBaseTypeValidator(type){let stringTypes=["varchar","char","text","uuid","citext","bit","varbit"],numberTypes=["integer","smallint","bigint","serial","smallserial","bigserial","real","doublePrecision","numeric","decimal"],booleanTypes=["boolean"];if(stringTypes.includes(type))return(v)=>({valid:typeof v==="string",expectedType:"string"});if(numberTypes.includes(type))return(v)=>({valid:typeof v==="number",expectedType:"number"});if(booleanTypes.includes(type))return(v)=>({valid:typeof v==="boolean",expectedType:"boolean"});if(type==="json"||type==="jsonb")return(v)=>({valid:typeof v==="object",expectedType:"object"});return()=>({valid:!0,expectedType:"any"})}function validatePayload(payload,columns,isPartial=!1){let errors=[];for(let col2 of columns){let value=payload[col2.name]??payload[col2.name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase())],hasDbDefault=col2.default!==void 0||!!col2.defaultRaw||!!col2.generatedByDefaultAsIdentity||!!col2.generatedAlwaysAsIdentity||!!col2.generatedAlwaysAs,isRequired=col2.notNull&&!col2.nullable&&!hasDbDefault;if(value===void 0||value===null){if(isRequired&&!isPartial)errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} is required`});continue}let typeCheck=getBaseTypeValidator(col2.type)(value);if(!typeCheck.valid){errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} must be of type ${typeCheck.expectedType}`});continue}if(typeof value==="string"){let len=value.length;if(col2.length&&len>col2.length)errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} exceeds max length of ${col2.length}`});if(col2.validation?.minLength&&len<col2.validation.minLength)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at least ${col2.validation.minLength} characters`});if(col2.validation?.maxLength&&len>col2.validation.maxLength)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at most ${col2.validation.maxLength} characters`});if(col2.validation?.pattern){if(!new RegExp(col2.validation.pattern).test(value))errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} does not match required pattern`})}if(col2.validation?.format){let formatRegex=FORMAT_PATTERNS[col2.validation.format];if(formatRegex&&!formatRegex.test(value))errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be a valid ${col2.validation.format}`})}}if(typeof value==="number"){if(col2.validation?.min!==void 0&&value<col2.validation.min)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at least ${col2.validation.min}`});if(col2.validation?.max!==void 0&&value>col2.validation.max)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at most ${col2.validation.max}`})}if(col2.enumValues&&col2.enumValues.length>0){if(!col2.enumValues.includes(value))errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} must be one of: ${col2.enumValues.join(", ")}`})}}return{valid:errors.length===0,errors}}function escapeHtml(str){return str.replace(/[&<>"'`=/]/g,(char)=>HTML_ENTITIES[char]||char)}function stripTags(str){return str.replace(/<[^>]*>/g,"")}function normalizeEmail(email){let parts=email.split("@"),localPart=parts[0],domain=parts[1];if(!localPart||!domain)return email;let beforePlus=localPart.split("+")[0];if(!beforePlus)return email;return`${beforePlus.replace(/\./g,"")}@${domain.toLowerCase()}`}function slugify(str){return str.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}function applySanitizer(value,sanitizer){if(value===null||value===void 0)return value;switch(sanitizer){case"trim":return typeof value==="string"?value.trim():value;case"lowercase":return typeof value==="string"?value.toLowerCase():value;case"uppercase":return typeof value==="string"?value.toUpperCase():value;case"escapeHtml":return typeof value==="string"?escapeHtml(value):value;case"stripTags":return typeof value==="string"?stripTags(value):value;case"normalizeEmail":return typeof value==="string"?normalizeEmail(value):value;case"toNumber":if(typeof value==="number")return value;if(typeof value==="string"){let num=Number(value);return Number.isNaN(num)?value:num}return value;case"toBoolean":if(typeof value==="boolean")return value;if(typeof value==="string"){let lower=value.toLowerCase();if(lower==="true"||lower==="1"||lower==="yes")return!0;if(lower==="false"||lower==="0"||lower==="no")return!1}if(typeof value==="number")return value!==0;return value;case"slugify":return typeof value==="string"?slugify(value):value;default:return value}}function sanitizePayload(payload,columns){let sanitized={},toCamel2=(s)=>s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase());for(let key of Object.keys(payload)){let value=payload[key],snakeKey=key.replace(/[A-Z]/g,(l)=>`_${l.toLowerCase()}`),col2=columns.find((c)=>c.name===key||c.name===snakeKey);if(col2?.sanitize&&col2.sanitize.length>0)for(let sanitizer of col2.sanitize)value=applySanitizer(value,sanitizer);if(col2&&(col2.type==="timestamp"||col2.type==="timestamptz"||col2.type==="date")&&typeof value==="string"){let parsed=new Date(value);if(!Number.isNaN(parsed.getTime()))value=parsed}let normalizedKey=key.includes("_")?toCamel2(key):key;sanitized[normalizedKey]=value}return sanitized}function createAuditLog(db,auditTable,entry){if(!db||!auditTable)return;let logEntry={user_id:entry.user_id,entity_name:entry.entity_name,entity_id:entry.entity_id,operation:entry.operation,old_data:entry.old_data??null,new_data:entry.new_data??null,timestamp:new Date().toISOString()};db.insert(auditTable).values(logEntry).execute().catch((err)=>{console.error("Audit log failed:",err)})}async function refreshAccessTokenWithLock(userId,sessionId,generateToken){let redis=new RedisManager,lockKey=`${REFRESH_LOCK_PREFIX}${userId}`,cacheKey=`${ACCESS_TOKEN_CACHE_PREFIX}${userId}:${sessionId}`,cachedResult=await redis.read(cacheKey);if(cachedResult.success&&cachedResult.data)return{success:!0,accessToken:cachedResult.data,fromCache:!0};let lockResult=await redis.acquireLock(lockKey,LOCK_TTL_SECONDS);if(!lockResult.success)return{success:!1,error:lockResult.error};if(lockResult.data)try{let newToken=generateToken();return await redis.create(cacheKey,newToken,ACCESS_TOKEN_CACHE_TTL_SECONDS),{success:!0,accessToken:newToken,fromCache:!1}}finally{await redis.releaseLock(lockKey)}let waitResult=await redis.waitForLock(lockKey,LOCK_WAIT_TIMEOUT_MS,50);if(!waitResult.success)return{success:!1,error:waitResult.error};if(!waitResult.data)return{success:!1,error:"Lock wait timeout"};let newCachedResult=await redis.read(cacheKey);if(newCachedResult.success&&newCachedResult.data)return{success:!0,accessToken:newCachedResult.data,fromCache:!0};let fallbackToken=generateToken();return await redis.create(cacheKey,fallbackToken,ACCESS_TOKEN_CACHE_TTL_SECONDS),{success:!0,accessToken:fallbackToken,fromCache:!1}}function validateEnvVariables(config){let errors=[],resolved={},databaseAuthMode=process.env.DATABASE_AUTH_MODE||"password",redisAuthMode=process.env.REDIS_AUTH_MODE||"password";resolved.databaseAuthMode=databaseAuthMode,resolved.redisAuthMode=redisAuthMode;let entraIdModes=["managed_identity","service_principal"];if(entraIdModes.includes(databaseAuthMode)||entraIdModes.includes(redisAuthMode)){if(!process.env.AZURE_CLIENT_ID)console.warn("[Nucleus] AZURE_CLIENT_ID is not set. Required for user-assigned managed identity.");if([databaseAuthMode,redisAuthMode].filter((m)=>m==="service_principal").length>0){if(!process.env.AZURE_TENANT_ID)errors.push({field:"azure.tenantId",envName:"AZURE_TENANT_ID",message:"AZURE_TENANT_ID is required for service_principal auth mode."});if(!process.env.AZURE_CLIENT_SECRET)errors.push({field:"azure.clientSecret",envName:"AZURE_CLIENT_SECRET",message:"AZURE_CLIENT_SECRET is required for service_principal auth mode."})}}if(config.database?.url){let envValue=process.env[config.database.url];if(!envValue)errors.push({field:"database.url",envName:config.database.url,message:`Environment variable "${config.database.url}" is not set. Please set it in your .env file.`});else resolved.databaseUrl=envValue}let validationWithDapr=typeof config.redis?.withDapr==="string"?process.env[config.redis.withDapr]?.toLowerCase()!=="false":config.redis?.withDapr??!1;if(config.redis&&!validationWithDapr)if(config.redis.url){let envValue=process.env[config.redis.url];if(!envValue)errors.push({field:"redis.url",envName:config.redis.url,message:`Environment variable "${config.redis.url}" is not set. Please set it in your .env file.`});else resolved.redisUrl=envValue}else{if(config.redis.host){if(!process.env[config.redis.host])errors.push({field:"redis.host",envName:config.redis.host,message:`Environment variable "${config.redis.host}" is not set. Please set it in your .env file.`})}if(config.redis.port){if(!process.env[config.redis.port])errors.push({field:"redis.port",envName:config.redis.port,message:`Environment variable "${config.redis.port}" is not set. Please set it in your .env file.`})}}if(config.authentication?.enabled){if(!config.authentication.mode)errors.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(config.authentication.accessToken?.secret){let envValue=process.env[config.authentication.accessToken.secret];if(!envValue)errors.push({field:"authentication.accessToken.secret",envName:config.authentication.accessToken.secret,message:`Environment variable "${config.authentication.accessToken.secret}" is not set. Please set it in your .env file.`});else resolved.accessTokenSecret=envValue}else errors.push({field:"authentication.accessToken.secret",envName:"",message:"authentication.accessToken.secret is required when authentication is enabled."});let isConsumerMode=config.authentication.mode==="consumer";if(config.authentication.refreshToken?.secret){let envValue=process.env[config.authentication.refreshToken.secret];if(!envValue)errors.push({field:"authentication.refreshToken.secret",envName:config.authentication.refreshToken.secret,message:`Environment variable "${config.authentication.refreshToken.secret}" is not set. Please set it in your .env file.`});else resolved.refreshTokenSecret=envValue}else if(!isConsumerMode)errors.push({field:"authentication.refreshToken.secret",envName:"",message:"authentication.refreshToken.secret is required when authentication is enabled."});if(config.authentication.sessionToken?.secret){let envValue=process.env[config.authentication.sessionToken.secret];if(!envValue)errors.push({field:"authentication.sessionToken.secret",envName:config.authentication.sessionToken.secret,message:`Environment variable "${config.authentication.sessionToken.secret}" is not set. Please set it in your .env file.`});else resolved.sessionTokenSecret=envValue}else if(!isConsumerMode)errors.push({field:"authentication.sessionToken.secret",envName:"",message:"authentication.sessionToken.secret is required when authentication is enabled."})}if(config.authentication?.oauth?.enabled&&config.authentication.oauth.providers){let resolvedProviders={};for(let[providerName,providerConfig]of Object.entries(config.authentication.oauth.providers)){if(!providerConfig)continue;let{clientId:clientIdEnvName,clientSecret:clientSecretEnvName,redirectUri:redirectUriEnvName}=providerConfig,clientId=process.env[clientIdEnvName],clientSecret=process.env[clientSecretEnvName],redirectUri=process.env[redirectUriEnvName]??redirectUriEnvName;if(!clientId)errors.push({field:`authentication.oauth.providers.${providerName}.clientId`,envName:clientIdEnvName,message:`Environment variable "${clientIdEnvName}" is not set (OAuth ${providerName} clientId).`});if(!clientSecret)errors.push({field:`authentication.oauth.providers.${providerName}.clientSecret`,envName:clientSecretEnvName,message:`Environment variable "${clientSecretEnvName}" is not set (OAuth ${providerName} clientSecret).`});if(clientId&&clientSecret)resolvedProviders[providerName]={clientId,clientSecret,redirectUri,scopes:providerConfig.scopes,authorizationUrl:providerConfig.authorizationUrl,tokenUrl:providerConfig.tokenUrl,userInfoUrl:providerConfig.userInfoUrl,extraAuthParams:providerConfig.extraAuthParams}}if(Object.keys(resolvedProviders).length>0)resolved.oauthProviders=resolvedProviders}return{valid:errors.length===0,errors,resolved}}async function ensureDatabaseExists(databaseUrl,logger2,authMode){let{Pool:Pool2}=await import("pg"),targetDb=new URL(databaseUrl).pathname.replace("/","");if(!targetDb)return;let adminUrl=new URL(databaseUrl);adminUrl.pathname="/postgres";let pool;if(authMode&&authMode!=="password"){let{getPostgresToken:getPostgresToken2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure));pool=new Pool2({connectionString:adminUrl.toString(),password:getPostgresToken2,ssl:{rejectUnauthorized:!0}})}else pool=new Pool2({connectionString:adminUrl.toString()});try{if((await pool.query("SELECT 1 FROM pg_database WHERE datname = $1",[targetDb])).rowCount===0)logger2.info(`[Database] Creating database "${targetDb}"...`),await pool.query(`CREATE DATABASE "${targetDb}" TEMPLATE template0`),logger2.info(`[Database] Database "${targetDb}" created successfully`);else logger2.info(`[Database] Database "${targetDb}" exists`)}catch(err){let message=err instanceof Error?err.message:String(err);logger2.warn(`[Database] Could not auto-create database: ${message}`)}finally{await pool.end()}}var redisManagerInstance=null,FORMAT_PATTERNS,HTML_ENTITIES,ACCESS_TOKEN_CACHE_PREFIX="access_token:",REFRESH_LOCK_PREFIX="refresh_lock:",LOCK_TTL_SECONDS=5,LOCK_WAIT_TIMEOUT_MS=3000,ACCESS_TOKEN_CACHE_TTL_SECONDS=60;var init_utils5=__esm(()=>{init_Managers();init_Services();FORMAT_PATTERNS={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};HTML_ENTITIES={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}});import{eq as eq8}from"drizzle-orm";import{pgSchema}from"drizzle-orm/pg-core";class TenantRegistry{db;logger;mainSchemaName;mainSchemaTables;mainSchemaRelations;createAllTablesForSchema;createAllRelationsForSchema;appId;authMode;tenantResolution;tenantHeader;redisCacheTtlSeconds;idpUrl;tenantsBySubdomain=new Map;tenantsBySchemaName=new Map;tenantsById=new Map;schemaContexts=new Map;tenantFeatures=new Map;constructor(config){this.db=config.db,this.logger=config.logger,this.mainSchemaName=config.mainSchemaName,this.mainSchemaTables=config.mainSchemaTables,this.mainSchemaRelations=config.mainSchemaRelations,this.createAllTablesForSchema=config.createAllTablesForSchema,this.createAllRelationsForSchema=config.createAllRelationsForSchema,this.appId=config.appId,this.authMode=config.authMode,this.tenantResolution=config.tenantResolution,this.tenantHeader=config.tenantHeader,this.redisCacheTtlSeconds=config.redisCacheTtlSeconds,this.idpUrl=config.idpUrl}async initialize(){this.logger.info("[TenantRegistry] Initializing..."),this.schemaContexts.set(this.mainSchemaName,{schemaName:this.mainSchemaName,schemaTables:this.mainSchemaTables,schemaRelations:this.mainSchemaRelations,tenant:null});let tenants=await this.loadTenantsFromDb();this.logger.info(`[TenantRegistry] Loaded ${tenants.length} tenants from database`);let features=await this.loadTenantFeaturesFromDb();this.logger.info(`[TenantRegistry] Loaded ${features.length} tenant feature mappings`);for(let tenant of tenants)this.indexTenant(tenant);for(let feature of features){let existing=this.tenantFeatures.get(feature.tenantId)||[];existing.push(feature),this.tenantFeatures.set(feature.tenantId,existing)}let activeTenants=tenants.filter((t)=>t.status==="active");for(let tenant of activeTenants)await this.buildSchemaContext(tenant);this.logger.info(`[TenantRegistry] Initialized with ${activeTenants.length} active tenant schemas + main schema`)}resolveFromRequest(request){let url=new URL(request.url),host=request.headers.get("host")||url.host||"";if(this.tenantResolution==="subdomain"||this.tenantResolution==="both"){let subdomain=extractSubdomain(host);if(subdomain){let tenant=this.tenantsBySubdomain.get(subdomain);if(tenant)return this.validateAndReturnTenant(tenant);return{resolved:!1,error:`Tenant not found for subdomain: ${subdomain}`,statusCode:404}}}if(this.tenantResolution==="header"||this.tenantResolution==="both"){let tenantIdOrSubdomain=request.headers.get(this.tenantHeader);if(tenantIdOrSubdomain){let result=this.resolveFromHeader(tenantIdOrSubdomain,request);if(result)return result}}let mainContext=this.schemaContexts.get(this.mainSchemaName);if(mainContext)return{resolved:!0,context:mainContext};return{resolved:!1,error:"No tenant could be resolved and main schema is unavailable",statusCode:500}}getSchemaContext(schemaName){return this.schemaContexts.get(schemaName)}getMainContext(){let ctx=this.schemaContexts.get(this.mainSchemaName);if(!ctx)throw Error("[TenantRegistry] Main schema context not initialized");return ctx}getActiveTenants(){return Array.from(this.tenantsById.values()).filter((t)=>t.status==="active")}getTenantById(id){return this.tenantsById.get(id)}getTenantFeatures(tenantId){return this.tenantFeatures.get(tenantId)||[]}isTenantFeatureEnabled(tenantId,featureName){return(this.tenantFeatures.get(tenantId)||[]).find((f)=>f.featureName===featureName)?.enabled??!1}getTenantIdsWithFeature(featureName){let result=[];for(let[tenantId,features]of this.tenantFeatures)if(features.find((f)=>f.featureName===featureName&&f.enabled))result.push(tenantId);return result}getSchemaNamesWithFeature(featureName){let tenantIds=this.getTenantIdsWithFeature(featureName),schemaNames=[];for(let tenantId of tenantIds){let tenant=this.tenantsById.get(tenantId);if(tenant&&tenant.status==="active")schemaNames.push(tenant.schemaName)}return schemaNames}getAllSchemaNames(){return Array.from(this.schemaContexts.keys())}async provisionTenant(tenant){this.logger.info(`[TenantRegistry] Provisioning tenant: ${tenant.subdomain} \u2192 ${tenant.schemaName}`),await ensureSchemaExists(this.db,tenant.schemaName);let context=await this.buildSchemaContext(tenant);return this.indexTenant(tenant),await this.syncSchemaToDb(context),this.logger.info(`[TenantRegistry] Tenant provisioned: ${tenant.subdomain}`),context}async syncSchemaToDb(context){let{pushSchema}=await import("drizzle-kit/api"),targetSchema=pgSchema(context.schemaName);try{await(await pushSchema({schema:targetSchema,...context.schemaTables},this.db,[context.schemaName])).apply(),this.logger.info(`[TenantRegistry] Schema sync completed for: ${context.schemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);this.logger.warn(`[TenantRegistry] Schema sync warning for ${context.schemaName}: ${msg}`)}}async syncAllSchemas(){for(let[schemaName,context]of this.schemaContexts)this.logger.info(`[TenantRegistry] Syncing schema: ${schemaName}`),await ensureSchemaExists(this.db,schemaName),await this.syncSchemaToDb(context)}async invalidateCache(subdomain){try{let{getRedisManager:getRedisManager2}=await Promise.resolve().then(() => (init_utils5(),exports_utils)),redis=getRedisManager2();if(redis)await redis.remove(`tenant:${subdomain}`),this.logger.info(`[TenantRegistry] Cache invalidated for: ${subdomain}`)}catch{}}async refreshTenant(tenantId){let tenantsTable=this.mainSchemaTables.tenants;if(!tenantsTable)return;let row=(await this.db.select().from(tenantsTable).where(eq8(tenantsTable.id,tenantId)).limit(1))[0];if(!row)return;let tenant=rowToTenantRecord(row),oldTenant=this.tenantsById.get(tenantId);if(oldTenant)this.tenantsBySubdomain.delete(oldTenant.subdomain),this.tenantsBySchemaName.delete(oldTenant.schemaName);if(this.indexTenant(tenant),tenant.status==="active")await this.buildSchemaContext(tenant);else this.schemaContexts.delete(tenant.schemaName);if(oldTenant)await this.invalidateCache(oldTenant.subdomain);await this.invalidateCache(tenant.subdomain)}async initializeFromIdp(){if(!this.idpUrl){this.logger.error("[TenantRegistry] Consumer multi-tenant requires idpUrl (IDP_URL)");return}this.logger.info(`[TenantRegistry] Initializing from IDP: ${this.idpUrl}`),this.schemaContexts.set(this.mainSchemaName,{schemaName:this.mainSchemaName,schemaTables:this.mainSchemaTables,schemaRelations:this.mainSchemaRelations,tenant:null});let tenants=await this.loadTenantsFromIdp();this.logger.info(`[TenantRegistry] Fetched ${tenants.length} tenants from IDP`);for(let tenant of tenants)this.indexTenant(tenant);let activeTenants=tenants.filter((t)=>t.status==="active");for(let tenant of activeTenants)await this.buildSchemaContext(tenant);this.logger.info(`[TenantRegistry] Consumer initialized with ${activeTenants.length} active tenant schemas + main schema`)}isConsumerMode(){return this.authMode==="consumer"&&!!this.idpUrl}async loadTenantsFromIdp(){if(!this.idpUrl)return[];try{let response=await fetch(`${this.idpUrl}/tenants`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!response.ok)return this.logger.warn(`[TenantRegistry] IDP tenant fetch failed: ${response.status} ${response.statusText}`),[];return((await response.json())?.data?.items||[]).map((item)=>rowToTenantRecord(item))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to fetch tenants from IDP: ${msg}`),[]}}async loadTenantsFromDb(){let tenantsTable=this.mainSchemaTables.tenants;if(!tenantsTable)return this.logger.warn("[TenantRegistry] No tenants table found in main schema"),[];try{return(await this.db.select().from(tenantsTable)).map((row)=>rowToTenantRecord(row))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to load tenants: ${msg}`),[]}}async loadTenantFeaturesFromDb(){let featuresTable=this.mainSchemaTables.tenantFeatures;if(!featuresTable)return this.logger.warn("[TenantRegistry] No tenant_features table found in main schema"),[];try{return(await this.db.select().from(featuresTable)).map((row)=>rowToFeatureRecord(row,parseJsonbToConfig))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to load tenant features: ${msg}`),[]}}indexTenant(tenant){if(this.tenantsById.set(tenant.id,tenant),this.tenantsBySubdomain.set(tenant.subdomain,tenant),this.tenantsBySchemaName.set(tenant.schemaName,tenant),tenant.domain)this.tenantsBySubdomain.set(tenant.domain,tenant)}async buildSchemaContext(tenant){let schema=pgSchema(tenant.schemaName),schemaTables=this.createAllTablesForSchema(schema),schemaRelations=this.createAllRelationsForSchema?this.createAllRelationsForSchema(schema):{},context={schemaName:tenant.schemaName,schemaTables,schemaRelations,tenant};return this.schemaContexts.set(tenant.schemaName,context),context}resolveFromHeader(tenantIdOrSubdomain,request){let tenant=this.tenantsBySubdomain.get(tenantIdOrSubdomain);if(!tenant)tenant=this.tenantsById.get(tenantIdOrSubdomain);if(!tenant)tenant=this.tenantsBySchemaName.get(tenantIdOrSubdomain);if(!tenant)return{resolved:!1,error:`Tenant not found for header value: ${tenantIdOrSubdomain}`,statusCode:404};if(!isTrustedSource(tenant,request,this.authMode))return{resolved:!1,error:`Untrusted source for tenant: ${tenant.subdomain}`,statusCode:403};return this.validateAndReturnTenant(tenant)}validateAndReturnTenant(tenant){if(tenant.status==="suspended")return{resolved:!1,error:`Tenant ${tenant.subdomain} is suspended: ${tenant.suspendedReason||"No reason provided"}`,statusCode:403};if(tenant.status==="provisioning")return{resolved:!1,error:`Tenant ${tenant.subdomain} is still being provisioned`,statusCode:503};if(tenant.status==="archived")return{resolved:!1,error:`Tenant ${tenant.subdomain} has been archived`,statusCode:410};let context=this.schemaContexts.get(tenant.schemaName);if(!context)return{resolved:!1,error:`Schema context not found for tenant: ${tenant.subdomain}`,statusCode:500};return{resolved:!0,context}}}var init_TenantRegistry=__esm(()=>{init_schema()});var init_Tenant=__esm(()=>{init_schema();init_TenantRegistry()});var init_types5=()=>{};import{and as and4,desc as desc2,eq as eq9,inArray as inArray2}from"drizzle-orm";function toCamel2(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());result[camelKey]=value}return result}function fromCamel2(obj){let result={};for(let[key,value]of Object.entries(obj)){let snakeKey=key.replace(/[A-Z]/g,(c)=>`_${c.toLowerCase()}`);result[snakeKey]=value}return result}class VerificationService{db;schemaTables;config;logger;onNotificationTrigger;constructor(serviceConfig){this.db=serviceConfig.db,this.schemaTables=serviceConfig.schemaTables,this.config=serviceConfig.config,this.logger=serviceConfig.logger}setNotificationHandler(handler){this.onNotificationTrigger=handler}getConnectedNotificationNodeIds(stepNodeId,steps,edges){let result=new Set,getNeighbors=(nid)=>{let neighbors=[];for(let edge of edges){let{sourceNodeId:src,targetNodeId:tgt}=edge;if(src===nid)neighbors.push(tgt);else if(tgt===nid)neighbors.push(src)}return neighbors},directNeighbors=getNeighbors(stepNodeId);for(let neighborId of directNeighbors)if(steps.find((s)=>s.nodeId===neighborId)?.nodeType==="notification")result.add(neighborId);for(let neighborId of directNeighbors)if(steps.find((s)=>s.nodeId===neighborId)?.nodeType==="verifier"){let verifierNeighbors=getNeighbors(neighborId);for(let vNeighborId of verifierNeighbors){if(vNeighborId===stepNodeId)continue;if(steps.find((s)=>s.nodeId===vNeighborId)?.nodeType==="notification")result.add(vNeighborId)}}let ids=[...result];return this.logger.info(`[Verification] Connected notification nodes for step ${stepNodeId}: [${ids.join(", ")}]`),ids}getTable(name){return this.schemaTables[name]}getCol(table,col2){return table[col2]}async listFlows(entityName){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return[];return(await(entityName?this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"entityName"),entityName)):this.db.select().from(flowsTable))).map((r)=>fromCamel2(r))}async getFlow(flowId){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),notifRulesTable=this.getTable("verificationNotificationRules"),notifRecipientsTable=this.getTable("verificationNotificationRecipients"),notifChannelsTable=this.getTable("verificationNotificationChannels");if(!flowsTable)return null;let flowRow=(await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)).limit(1))[0];if(!flowRow)return null;let flow=fromCamel2(flowRow),steps=(stepsTable?await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),edges=(edgesTable?await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),verifierConfigs=(verifierConfigsTable?await this.db.select().from(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),notifRules=(notifRulesTable?await this.db.select().from(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),ruleIds=notifRules.map((r)=>r.id),notifRecipients=(notifRecipientsTable&&ruleIds.length>0?await this.db.select().from(notifRecipientsTable).where(inArray2(this.getCol(notifRecipientsTable,"ruleId"),ruleIds)):[]).map((r)=>fromCamel2(r)),notifChannels=(notifChannelsTable&&ruleIds.length>0?await this.db.select().from(notifChannelsTable).where(inArray2(this.getCol(notifChannelsTable,"ruleId"),ruleIds)):[]).map((r)=>fromCamel2(r));return{flow,graph:{steps,edges,verifier_configs:verifierConfigs,notification_rules:notifRules,notification_recipients:notifRecipients,notification_channels:notifChannels}}}async saveFlow(params){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),notifRulesTable=this.getTable("verificationNotificationRules"),notifRecipientsTable=this.getTable("verificationNotificationRecipients"),notifChannelsTable=this.getTable("verificationNotificationChannels");if(!flowsTable||!stepsTable||!edgesTable)throw Error("Verification tables not configured");let existingFlows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),params.flow_id)).limit(1),flowId=params.flow_id;if(existingFlows.length>0)await this.db.update(flowsTable).set(toCamel2({entity_name:params.entity_name,name:params.name,description:params.description||null,trigger_on:params.trigger_on,trigger_fields:params.trigger_fields||null,is_draft:params.is_draft,viewport:params.viewport||null})).where(eq9(this.getCol(flowsTable,"id"),flowId));else{let[newFlow]=await this.db.insert(flowsTable).values(toCamel2({id:flowId,entity_name:params.entity_name,name:params.name,description:params.description||null,trigger_on:params.trigger_on,trigger_fields:params.trigger_fields||null,is_draft:params.is_draft,viewport:params.viewport||null})).returning();flowId=newFlow.id}if(await this.db.delete(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),flowId)),edgesTable)await this.db.delete(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),flowId));if(verifierConfigsTable)await this.db.delete(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId));if(notifRulesTable){let oldRuleIds=(await this.db.select().from(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId))).map((r)=>r.id);if(oldRuleIds.length>0){if(notifRecipientsTable)for(let rid of oldRuleIds)await this.db.delete(notifRecipientsTable).where(eq9(this.getCol(notifRecipientsTable,"ruleId"),rid));if(notifChannelsTable)for(let rid of oldRuleIds)await this.db.delete(notifChannelsTable).where(eq9(this.getCol(notifChannelsTable,"ruleId"),rid))}await this.db.delete(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId))}let{graph}=params;if(graph.steps.length>0)await this.db.insert(stepsTable).values(graph.steps.map((s)=>toCamel2({flow_id:flowId,entity_name:params.entity_name,node_id:s.node_id,node_type:s.node_type,step_order:s.step_order,name:s.name||null,description:s.description||null,position_x:s.position_x,position_y:s.position_y,width:s.width||null,height:s.height||null,style:s.style||null,data:s.data||null})));if(graph.edges.length>0&&edgesTable)await this.db.insert(edgesTable).values(graph.edges.map((e)=>toCamel2({flow_id:flowId,edge_id:e.edge_id,source_node_id:e.source_node_id,target_node_id:e.target_node_id,source_handle:e.source_handle||null,target_handle:e.target_handle||null,edge_type:e.edge_type,label:e.label||null,condition:e.condition||null,style:e.style||null,animated:e.animated})));if(graph.verifier_configs.length>0&&verifierConfigsTable)await this.db.insert(verifierConfigsTable).values(graph.verifier_configs.map((vc)=>toCamel2({flow_id:flowId,node_id:vc.node_id,verifier_type:vc.verifier_type,verifier_user_id:vc.verifier_user_id||null,verifier_role:vc.verifier_role||null,require_signature:vc.require_signature,all_must_approve:vc.all_must_approve})));if(this.logger.info(`[Verification] Save: ${graph.notification_rules.length} rules, ${graph.notification_recipients.length} recipients, ${graph.notification_channels.length} channels`),graph.notification_rules.length>0&¬ifRulesTable)for(let rule of graph.notification_rules){this.logger.info(`[Verification] Saving notification rule: node_id=${rule.node_id}, trigger=${rule.trigger}, title_template=${JSON.stringify(rule.title_template)}, body_template=${JSON.stringify(rule.body_template)}`);let[insertedRule]=await this.db.insert(notifRulesTable).values(toCamel2({flow_id:flowId,node_id:rule.node_id,trigger:rule.trigger,title_template:rule.title_template||null,body_template:rule.body_template||null,starts_at:rule.starts_at||null,expires_at:rule.expires_at||null})).returning(),ruleId=insertedRule.id,ruleRecipients=graph.notification_recipients.filter((r)=>r.rule_id===rule.node_id);if(ruleRecipients.length>0&¬ifRecipientsTable)await this.db.insert(notifRecipientsTable).values(ruleRecipients.map((r)=>toCamel2({rule_id:ruleId,recipient_type:r.recipient_type,recipient_user_id:r.recipient_user_id||null,recipient_role:r.recipient_role||null})));let ruleChannels=graph.notification_channels.filter((c)=>c.rule_id===rule.node_id);if(ruleChannels.length>0&¬ifChannelsTable)await this.db.insert(notifChannelsTable).values(ruleChannels.map((c)=>toCamel2({rule_id:ruleId,channel:c.channel})))}return this.logger.info(`[Verification] Flow saved: ${flowId} for ${params.entity_name}`),{success:!0,flow_id:flowId}}async publishFlow(flowId){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};return await this.db.update(flowsTable).set(toCamel2({is_draft:!1,published_at:new Date})).where(eq9(this.getCol(flowsTable,"id"),flowId)),this.logger.info(`[Verification] Flow published: ${flowId}`),{success:!0,message:"Flow published"}}async deleteFlow(flowId){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};return await this.db.delete(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)),this.logger.info(`[Verification] Flow deleted: ${flowId}`),{success:!0,message:"Flow deleted"}}async startFlow(params){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),instancesTable=this.getTable("verificationInstances"),requirementsTable=this.getTable("verificationRequirements"),userRolesTable=this.getTable("user_roles");if(!flowsTable||!stepsTable||!edgesTable||!instancesTable||!requirementsTable)return{success:!1,message:"Verification tables not configured"};let flow=(await this.db.select().from(flowsTable).where(and4(eq9(this.getCol(flowsTable,"id"),params.flow_id),eq9(this.getCol(flowsTable,"isDraft"),!1))).limit(1))[0];if(!flow)return{success:!1,message:"Published flow not found"};if((await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"entityName"),params.entity_name),eq9(this.getCol(instancesTable,"entityId"),params.entity_id),eq9(this.getCol(instancesTable,"status"),"active"))).limit(1)).length>0)return{success:!1,message:"An active verification instance already exists for this entity"};let steps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),params.flow_id)),edges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),params.flow_id)),stepNodes=steps.filter((s)=>s.nodeType==="step");if(stepNodes.sort((a,b)=>a.stepOrder-b.stepOrder),stepNodes.length===0)return{success:!1,message:"Flow has no step nodes"};let[instance]=await this.db.insert(instancesTable).values(toCamel2({flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,started_by:params.started_by||null,status:"active",current_step_order:1,started_at:new Date})).returning(),instanceId=instance.id;if(await this.materializeRequirementsForStep(instanceId,params.flow_id,params.entity_name,params.entity_id,1,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable),this.onNotificationTrigger){let firstStep=stepNodes[0],firstStepNodeId=firstStep?.nodeId,connectedNotifIds=firstStepNodeId?this.getConnectedNotificationNodeIds(firstStepNodeId,steps,edges):[],ctx={flow_name:flow.name,step_name:firstStep?.name||"Step 1",step_order:1,total_steps:stepNodes.length};if(connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,node_id:notifNodeId,context:ctx});else await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,context:ctx})}return this.logger.info(`[Verification] Flow started: instance ${instanceId} for ${params.entity_name}:${params.entity_id}`),{success:!0,instance_id:instanceId,message:"Flow started"}}async materializeRequirementsForStep(instanceId,flowId,entityName,entityId,stepOrder,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable){if(!requirementsTable)return;let stepNode=steps.find((s)=>s.nodeType==="step"&&s.stepOrder===stepOrder);if(!stepNode)return;let stepNodeId=stepNode.nodeId,verifierNodeIds=edges.filter((e)=>e.targetNodeId===stepNodeId).map((e)=>e.sourceNodeId),verifierNodes=steps.filter((s)=>s.nodeType==="verifier"&&verifierNodeIds.includes(s.nodeId));if(verifierNodes.length===0)return;let verifierConfigs=[];if(verifierConfigsTable)verifierConfigs=await this.db.select().from(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId));for(let verifierNode of verifierNodes){let nodeId=verifierNode.nodeId,config=verifierConfigs.find((vc)=>vc.nodeId===nodeId);if(!config)continue;let{verifierType,allMustApprove}=config;if(verifierType==="role"&&allMustApprove&&userRolesTable){let rolesTable=this.getTable("roles");if(rolesTable){let rolesCols=rolesTable,userRolesCols=userRolesTable,role=(await this.db.select().from(rolesTable).where(eq9(rolesCols.name,config.verifierRole)).limit(1))[0];if(role){let usersWithRole=await this.db.select({user_id:userRolesCols.userId}).from(userRolesTable).where(eq9(userRolesCols.roleId,role.id));for(let userRole of usersWithRole)await this.db.insert(requirementsTable).values(toCamel2({instance_id:instanceId,step_node_id:stepNodeId,verifier_node_id:nodeId,entity_name:entityName,entity_id:entityId,verifier_type:"user",verifier_user_id:userRole.user_id,verifier_role:config.verifierRole||null,require_signature:config.requireSignature,all_must_approve:!0,step_order:stepOrder,status:"pending"}))}}}else await this.db.insert(requirementsTable).values(toCamel2({instance_id:instanceId,step_node_id:stepNodeId,verifier_node_id:nodeId,entity_name:entityName,entity_id:entityId,verifier_type:verifierType,verifier_user_id:config.verifierUserId||null,verifier_role:config.verifierRole||null,require_signature:config.requireSignature,all_must_approve:allMustApprove,step_order:stepOrder,status:"pending"}))}if(this.onNotificationTrigger){let connectedNotifIds=this.getConnectedNotificationNodeIds(stepNodeId,steps,edges);if(this.logger.info(`[Verification] on_step_reached: stepNodeId=${stepNodeId}, connectedNotifIds=[${connectedNotifIds.join(", ")}]`),connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)this.logger.info(`[Verification] Triggering on_step_reached for notifNodeId=${notifNodeId}`),await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:flowId,entity_name:entityName,entity_id:entityId,node_id:notifNodeId,context:{step_name:stepNode.name||`Step ${stepOrder}`,step_order:stepOrder}});else await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:flowId,entity_name:entityName,entity_id:entityId,context:{step_name:stepNode.name||`Step ${stepOrder}`,step_order:stepOrder}})}}async getStatus(entityName,entityId){let instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),verificationsTable=this.getTable("verifications"),requirementsTable=this.getTable("verificationRequirements"),emptyStatus={entity_name:entityName,entity_id:entityId,instance:null,flow:null,current_step:0,total_steps:0,is_completed:!1,is_rejected:!1,verifications:[],pending_requirements:[]};if(!instancesTable||!flowsTable||!verificationsTable||!requirementsTable)return this.logger.error("[Verification] Required tables not found"),emptyStatus;let instanceRow=(await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"entityName"),entityName),eq9(this.getCol(instancesTable,"entityId"),entityId))).orderBy(desc2(this.getCol(instancesTable,"createdAt"))).limit(1))[0];if(!instanceRow)return emptyStatus;let instance=fromCamel2(instanceRow),flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),instance.flow_id)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0,totalSteps=(stepsTable?await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),instance.flow_id),eq9(this.getCol(stepsTable,"nodeType"),"step"))):[]).length,verifications=(await this.db.select().from(verificationsTable).where(eq9(this.getCol(verificationsTable,"instanceId"),instance.id)).orderBy(desc2(this.getCol(verificationsTable,"createdAt")))).map((r)=>fromCamel2(r)),pendingRequirements=(await this.db.select().from(requirementsTable).where(and4(eq9(this.getCol(requirementsTable,"instanceId"),instance.id),eq9(this.getCol(requirementsTable,"status"),"pending")))).map((r)=>fromCamel2(r));return{entity_name:entityName,entity_id:entityId,instance,flow:flow||null,current_step:instance.current_step_order,total_steps:totalSteps,is_completed:instance.status==="completed",is_rejected:instance.status==="rejected",verifications,pending_requirements:pendingRequirements}}async decide(params){let{entity_name,entity_id,user_id,decision,reason,signature_id,diff}=params,verificationsTable=this.getTable("verifications"),requirementsTable=this.getTable("verificationRequirements"),instancesTable=this.getTable("verificationInstances"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");if(!verificationsTable||!requirementsTable||!instancesTable)return{success:!1,message:"Verification tables not configured"};let status=await this.getStatus(entity_name,entity_id);if(!status.instance||status.instance.status!=="active")return{success:!1,message:"No active verification instance"};let currentPending=status.pending_requirements.filter((r)=>r.step_order===status.current_step);if(currentPending.length===0)return{success:!1,message:"No pending requirements for current step"};let matchedReq=null;for(let req of currentPending){if(req.verifier_type==="user"&&req.verifier_user_id===user_id){matchedReq=req;break}if(req.verifier_type==="role"&&req.verifier_role&&userRolesTable&&rolesTable){let userRolesCols=userRolesTable,rolesCols=rolesTable;if((await this.db.select({role_name:rolesCols.name}).from(userRolesTable).innerJoin(rolesTable,eq9(userRolesCols.roleId,rolesCols.id)).where(eq9(userRolesCols.userId,user_id))).some((ur)=>ur.role_name===req.verifier_role)){matchedReq=req;break}}}if(!matchedReq)return{success:!1,message:"User is not authorized to verify at this step"};if(matchedReq.require_signature&&!signature_id)return{success:!1,message:"Signature is required for this verification step"};let[newVerification]=await this.db.insert(verificationsTable).values(toCamel2({instance_id:status.instance.id,requirement_id:matchedReq.id,verifier_id:user_id,signature_id:signature_id||null,entity_name,entity_id,step_order:status.current_step,decision,reason:reason||null,diff:diff||null})).returning();if(await this.db.update(requirementsTable).set({status:decision}).where(eq9(this.getCol(requirementsTable,"id"),matchedReq.id)),this.onNotificationTrigger&&status.instance){let stepName=`Step ${status.current_step}`,allSteps=[],allEdges=[];if(stepsTable){allSteps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id));let stepRow=allSteps.find((s)=>s.nodeId===matchedReq.step_node_id);if(stepRow?.name)stepName=stepRow.name}if(edgesTable)allEdges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));let triggerName=decision==="approved"?"on_approved":"on_rejected",ctx={flow_name:status.flow?.name||"",step_name:stepName,step_order:status.current_step,total_steps:status.total_steps,decision},connectedNotifIds=this.getConnectedNotificationNodeIds(matchedReq.step_node_id,allSteps,allEdges);if(connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)await this.onNotificationTrigger({trigger:triggerName,flow_id:status.instance.flow_id,entity_name,entity_id,node_id:notifNodeId,verifier_id:user_id,decision,context:ctx});else await this.onNotificationTrigger({trigger:triggerName,flow_id:status.instance.flow_id,entity_name,entity_id,verifier_id:user_id,decision,context:ctx})}if(decision==="rejected"){await this.db.update(instancesTable).set(toCamel2({status:"rejected",completed_at:new Date})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id));let newInstanceId;if(this.config.autoResetOnRejection){this.logger.info(`[Verification] Flow rejected for ${entity_name}:${entity_id}, auto-restarting from step 1`);let restartResult=await this.startFlow({flow_id:status.instance.flow_id,entity_name,entity_id,started_by:status.instance.started_by});if(restartResult.success)newInstanceId=restartResult.instance_id}return{success:!0,message:this.config.autoResetOnRejection?"Verification rejected \u2014 flow restarted from step 1":"Verification rejected",verification:newVerification,flow_completed:!1,new_instance_id:newInstanceId}}let matchedReqId=matchedReq.id,remainingPending=currentPending.filter((r)=>r.id!==matchedReqId);if(remainingPending.length>0)return{success:!0,message:`Step ${status.current_step} partially approved, ${remainingPending.length} verifier(s) remaining`,verification:newVerification,flow_completed:!1};let nextStep=status.current_step+1;if(nextStep>status.total_steps){if(await this.db.update(instancesTable).set(toCamel2({status:"completed",completed_at:new Date})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id)),this.onNotificationTrigger){let completedSteps=[],completedEdges=[];if(stepsTable)completedSteps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id));if(edgesTable)completedEdges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));let lastStepNodeId=matchedReq.step_node_id,completedNotifIds=this.getConnectedNotificationNodeIds(lastStepNodeId,completedSteps,completedEdges),completedCtx={flow_name:status.flow?.name||"",step_order:status.current_step,total_steps:status.total_steps};if(completedNotifIds.length>0)for(let notifNodeId of completedNotifIds)await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:status.instance.flow_id,entity_name,entity_id,node_id:notifNodeId,context:completedCtx});else await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:status.instance.flow_id,entity_name,entity_id,context:completedCtx})}return{success:!0,message:"Verification flow completed",verification:newVerification,flow_completed:!0}}if(await this.db.update(instancesTable).set(toCamel2({current_step_order:nextStep})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id)),stepsTable&&edgesTable){let steps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id)),edges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));await this.materializeRequirementsForStep(status.instance.id,status.instance.flow_id,entity_name,entity_id,nextStep,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable)}return{success:!0,message:`Step ${status.current_step} approved, moving to step ${nextStep}`,verification:newVerification,flow_completed:!1,next_step:nextStep}}async startFlowForEntity(params){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};let flow=(await this.db.select().from(flowsTable).where(and4(eq9(this.getCol(flowsTable,"entityName"),params.entity_name),eq9(this.getCol(flowsTable,"isDraft"),!1))).limit(1))[0];if(!flow)return{success:!1,message:`No published flow found for entity '${params.entity_name}'`};return this.startFlow({flow_id:flow.id,entity_name:params.entity_name,entity_id:params.entity_id,started_by:params.started_by})}async listEntityStatuses(params){let instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),emptyResult={items:[],total:0,page:1,limit:20};if(!instancesTable||!flowsTable)return emptyResult;let page=params.page||1,limit=params.limit||20,offset=(page-1)*limit,conditions=[eq9(this.getCol(instancesTable,"entityName"),params.entity_name)];if(params.status)conditions.push(eq9(this.getCol(instancesTable,"status"),params.status));let whereClause=conditions.length===1?conditions[0]:and4(...conditions),allInstances=(await this.db.select().from(instancesTable).where(whereClause).orderBy(desc2(this.getCol(instancesTable,"createdAt")))).map((r)=>fromCamel2(r)),total=allInstances.length,paged=allInstances.slice(offset,offset+limit),items=[];for(let inst of paged){let flowId=inst.flow_id,flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0,totalSteps=0;if(stepsTable)totalSteps=(await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),flowId),eq9(this.getCol(stepsTable,"nodeType"),"step")))).length;items.push({instance_id:inst.id,entity_name:inst.entity_name,entity_id:inst.entity_id,flow_id:flowId,flow_name:flow?.name||"Unknown",status:inst.status,current_step_order:inst.current_step_order,total_steps:totalSteps,started_by:inst.started_by,started_at:inst.started_at,completed_at:inst.completed_at})}return{items,total,page,limit}}async getPending(userId){let requirementsTable=this.getTable("verificationRequirements"),instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");if(this.logger.info(`[Verification.getPending] userId=${userId}, tables: req=${!!requirementsTable} inst=${!!instancesTable} flow=${!!flowsTable} steps=${!!stepsTable} roles=${!!rolesTable} userRoles=${!!userRolesTable}`),!requirementsTable||!instancesTable||!flowsTable)return this.logger.warn("[Verification.getPending] Missing required tables, returning empty"),[];let userRolesCols=userRolesTable,rolesCols=rolesTable,userRoleNames=(userRolesTable&&rolesTable?await this.db.select({role_name:rolesCols.name}).from(userRolesTable).innerJoin(rolesTable,eq9(userRolesCols.roleId,rolesCols.id)).where(eq9(userRolesCols.userId,userId)):[]).map((ur)=>ur.role_name),pendingReqs=(await this.db.select().from(requirementsTable).where(eq9(this.getCol(requirementsTable,"status"),"pending"))).map((r)=>fromCamel2(r));this.logger.info(`[Verification.getPending] Found ${pendingReqs.length} pending requirements, userRoles=${JSON.stringify(userRoleNames)}`);for(let req of pendingReqs)this.logger.info(`[Verification.getPending] Req: verifier_type=${req.verifier_type} verifier_user_id=${req.verifier_user_id} verifier_role=${req.verifier_role} step_order=${req.step_order} entity=${req.entity_name}/${req.entity_id}`);let pendingItems=[];for(let req of pendingReqs){if(!(req.verifier_type==="user"&&req.verifier_user_id===userId||req.verifier_type==="role"&&userRoleNames.includes(req.verifier_role))){this.logger.info(`[Verification.getPending] Skipping req: canVerify=false (type=${req.verifier_type}, reqUserId=${req.verifier_user_id}, loggedInUserId=${userId})`);continue}let instances=await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"id"),req.instance_id),eq9(this.getCol(instancesTable,"status"),"active"))).limit(1),instance=instances[0]?fromCamel2(instances[0]):void 0;if(!instance)continue;if(instance.current_step_order!==req.step_order)continue;let flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),instance.flow_id)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0;if(!flow)continue;let stepName;if(stepsTable&&req.step_node_id){let stepRow=(await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),instance.flow_id),eq9(this.getCol(stepsTable,"nodeId"),req.step_node_id))).limit(1))[0];if(stepRow?.name)stepName=stepRow.name}pendingItems.push({instance_id:instance.id,entity_name:req.entity_name,entity_id:req.entity_id,flow_name:flow.name,step_order:req.step_order,step_name:stepName,require_signature:req.require_signature,created_at:req.created_at})}return pendingItems}}var init_Verification=__esm(()=>{init_types5()});import*as crypto5 from"crypto";var IYZICO_PATHS,generateAuthString=(apiKey,secretKey,path2,payload,randomKey)=>{let compound=payload?randomKey+path2+payload:randomKey+path2,encryptedData=crypto5.createHmac("sha256",secretKey).update(compound).digest("hex"),authorizationString=`apiKey:${apiKey}&randomKey:${randomKey}&signature:${encryptedData}`;return`IYZWSv2 ${Buffer.from(authorizationString).toString("base64")}`},buildRequest=(config,path2,payload)=>{let body=JSON.stringify(payload),randomKey=Date.now().toString(32),headers=new Headers;return headers.set("Content-Type","application/json"),headers.set("x-iyzi-rnd",randomKey),headers.set("Authorization",generateAuthString(config.apiKey,config.secretKey,path2,body,randomKey)),{url:new URL(`${config.apiUrl}${path2}`).toString(),headers,body}},iyzicoFetch=async(config,path2,payload)=>{let{url,headers,body}=buildRequest(config,path2,payload);try{let json=await(await fetch(url,{method:"POST",headers,body})).json(),isSuccess=json.status==="success";return{success:isSuccess,data:isSuccess?json:null,errorCode:json.errorCode??void 0,errorMessage:json.errorMessage??void 0,rawResponse:json}}catch(error){let message=error instanceof Error?error.message:"Unknown fetch error";return{success:!1,data:null,errorCode:"NETWORK_ERROR",errorMessage:message,rawResponse:{error:message}}}},createIyzicoProvider=(config)=>{let generateConversationId=()=>`nk-${Date.now().toString(16)}`;return{get name(){return"iyzico"},async initialize3DS(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId,price:request.price,paidPrice:request.paidPrice,currency:request.currency,installment:request.installment??1,paymentChannel:request.paymentChannel??"WEB",basketId:request.basketId??Date.now().toString(16),paymentGroup:request.paymentGroup??"PRODUCT",paymentCard:request.paymentCard,buyer:request.buyer,shippingAddress:request.shippingAddress,billingAddress:request.billingAddress,basketItems:request.basketItems,callbackUrl:request.callbackUrl},result=await iyzicoFetch(config,IYZICO_PATHS.INITIALIZE_3DS,payload);return{success:result.success,threeDSHtmlContent:result.data?.threeDSHtmlContent,paymentId:result.data?.paymentId,signature:result.data?.signature,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async complete3DS(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId,paymentId:request.paymentId},result=await iyzicoFetch(config,IYZICO_PATHS.COMPLETE_3DS,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,paidPrice:result.data?.paidPrice,currency:result.data?.currency,installment:result.data?.installment,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,binNumber:result.data?.binNumber,lastFourDigits:result.data?.lastFourDigits,basketId:result.data?.basketId,authCode:result.data?.authCode,signature:result.data?.signature,fraudStatus:result.data?.fraudStatus,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async getPaymentDetail(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),paymentId:request.paymentId,paymentConversationId:request.paymentConversationId},result=await iyzicoFetch(config,IYZICO_PATHS.PAYMENT_DETAIL,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,paidPrice:result.data?.paidPrice,currency:result.data?.currency,basketId:result.data?.basketId,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,lastFourDigits:result.data?.lastFourDigits,binNumber:result.data?.binNumber,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async queryBin(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),binNumber:request.binNumber.slice(0,6)};if(request.price!==void 0)payload.price=request.price;let result=await iyzicoFetch(config,IYZICO_PATHS.BIN_CHECK,payload);return{success:result.success,binNumber:result.data?.binNumber,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,bankName:result.data?.bankName,bankCode:result.data?.bankCode,commercial:result.data?.commercial,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async saveCard(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),card:request.card,email:request.email,externalId:request.externalId},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_SAVE,payload);return{success:result.success,cardUserKey:result.data?.cardUserKey,cardToken:result.data?.cardToken,cardAlias:result.data?.cardAlias,binNumber:result.data?.binNumber,lastFourDigits:result.data?.lastFourDigits,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,cardBankName:result.data?.cardBankName,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async listCards(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),cardUserKey:request.cardUserKey},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_LIST,payload),cards=(result.data?.cardDetails??[]).map((cd)=>({cardToken:cd.cardToken,cardAlias:cd.cardAlias,binNumber:cd.binNumber,lastFourDigits:cd.lastFourDigits,cardType:cd.cardType,cardAssociation:cd.cardAssociation,cardFamily:cd.cardFamily,cardBankName:cd.cardBankName,cardBankCode:cd.cardBankCode}));return{success:result.success,cardUserKey:result.data?.cardUserKey,cards,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async deleteCard(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),cardUserKey:request.cardUserKey,cardToken:request.cardToken},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_DELETE,payload);return{success:result.success,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async refund(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),paymentTransactionId:request.paymentTransactionId,price:request.price,currency:request.currency??"TRY"};if(request.ip)payload.ip=request.ip;let result=await iyzicoFetch(config,IYZICO_PATHS.REFUND,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,currency:result.data?.currency,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},parseCallback(formData){return{success:formData.mdStatus==="1",paymentId:formData.paymentId??"",conversationId:formData.conversationId??"",mdStatus:formData.mdStatus??"",rawData:formData}},async registerSubMerchant(request){let typeMap={personal:"PERSONAL",private_company:"PRIVATE_COMPANY",limited_or_joint_stock_company:"LIMITED_OR_JOINT_STOCK_COMPANY"},payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantExternalId:request.subMerchantExternalId,subMerchantType:typeMap[request.subMerchantType]??"PERSONAL",name:request.name,email:request.email,gsmNumber:request.gsmNumber,address:request.address,iban:request.iban,contactName:request.contactName,contactSurname:request.contactSurname,identityNumber:request.identityNumber,currency:request.currency??"TRY"};if(request.subMerchantType==="private_company")payload.taxOffice=request.taxOffice,payload.legalCompanyTitle=request.legalCompanyTitle;if(request.subMerchantType==="limited_or_joint_stock_company")payload.taxOffice=request.taxOffice,payload.taxNumber=request.taxNumber,payload.legalCompanyTitle=request.legalCompanyTitle;let result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_CREATE,payload);return{success:result.success,subMerchantKey:result.data?.subMerchantKey,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async updateSubMerchant(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantKey:request.subMerchantKey};if(request.name)payload.name=request.name;if(request.email)payload.email=request.email;if(request.gsmNumber)payload.gsmNumber=request.gsmNumber;if(request.address)payload.address=request.address;if(request.iban)payload.iban=request.iban;if(request.contactName)payload.contactName=request.contactName;if(request.contactSurname)payload.contactSurname=request.contactSurname;if(request.identityNumber)payload.identityNumber=request.identityNumber;if(request.taxOffice)payload.taxOffice=request.taxOffice;if(request.taxNumber)payload.taxNumber=request.taxNumber;if(request.legalCompanyTitle)payload.legalCompanyTitle=request.legalCompanyTitle;if(request.currency)payload.currency=request.currency;let result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_UPDATE,payload);return{success:result.success,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async getSubMerchant(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantExternalId:request.subMerchantExternalId},result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_DETAIL,payload);return{success:result.success,subMerchantKey:result.data?.subMerchantKey,name:result.data?.name,email:result.data?.email,gsmNumber:result.data?.gsmNumber,address:result.data?.address,iban:result.data?.iban,subMerchantType:result.data?.subMerchantType,currency:result.data?.currency,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async approveSplit(request){let payload={locale:request.locale??"tr",paymentTransactionId:request.paymentTransactionId},result=await iyzicoFetch(config,IYZICO_PATHS.APPROVAL,payload);return{success:result.success,paymentTransactionId:result.data?.paymentTransactionId,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async disapproveSplit(request){let payload={locale:request.locale??"tr",paymentTransactionId:request.paymentTransactionId},result=await iyzicoFetch(config,IYZICO_PATHS.DISAPPROVAL,payload);return{success:result.success,paymentTransactionId:result.data?.paymentTransactionId,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async createProduct(request){let localId=`iyzico-prod-${Date.now().toString(36)}`;return{success:!0,providerProductId:localId,name:request.name,rawResponse:{local:!0,id:localId}}},async updateProduct(request){return{success:!0,providerProductId:request.providerProductId,rawResponse:{local:!0,updated:request.providerProductId}}},async getProduct(request){return{success:!0,providerProductId:request.providerProductId,rawResponse:{local:!0,message:"Product data is stored locally for iyzico"}}},async listProducts(_request){return{success:!0,products:[],hasMore:!1,rawResponse:{local:!0,message:"Products are stored locally for iyzico"}}},async archiveProduct(request){return{success:!0,rawResponse:{local:!0,archived:request.providerProductId}}},async createPrice(request){let localId=`iyzico-price-${Date.now().toString(36)}`;return{success:!0,providerPriceId:localId,rawResponse:{local:!0,id:localId,product:request.providerProductId}}},async updatePrice(request){return{success:!0,providerPriceId:request.providerPriceId,rawResponse:{local:!0,updated:request.providerPriceId}}},async getPrice(request){return{success:!0,providerPriceId:request.providerPriceId,rawResponse:{local:!0,message:"Price data is stored locally for iyzico"}}},async listPrices(_request){return{success:!0,prices:[],hasMore:!1,rawResponse:{local:!0,message:"Prices are stored locally for iyzico"}}},async archivePrice(request){return{success:!0,rawResponse:{local:!0,archived:request.providerPriceId}}},async createCustomer(request){return{success:!0,providerCustomerId:`local_cus_${Date.now()}`,email:request.email,rawResponse:{local:!0,message:"Customer stored locally for iyzico"}}},async updateCustomer(request){return{success:!0,providerCustomerId:request.providerCustomerId,rawResponse:{local:!0,message:"Customer updated locally for iyzico"}}},async getCustomer(request){return{success:!0,providerCustomerId:request.providerCustomerId,rawResponse:{local:!0,message:"Customer data is stored locally for iyzico"}}},async listCustomers(_request){return{success:!0,customers:[],hasMore:!1,rawResponse:{local:!0,message:"Customers are stored locally for iyzico"}}},async deleteCustomer(_request){return{success:!0,rawResponse:{local:!0,message:"Customer deleted locally for iyzico"}}},async createSubscription(_request){return{success:!0,providerSubscriptionId:`local_sub_${Date.now()}`,status:"active",rawResponse:{local:!0,message:"Subscription stored locally for iyzico"}}},async updateSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,status:"active",rawResponse:{local:!0,message:"Subscription updated locally for iyzico"}}},async cancelSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,status:"canceled",rawResponse:{local:!0,message:"Subscription canceled locally for iyzico"}}},async getSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,rawResponse:{local:!0,message:"Subscription data is stored locally for iyzico"}}},async listSubscriptions(_request){return{success:!0,subscriptions:[],hasMore:!1,rawResponse:{local:!0,message:"Subscriptions are stored locally for iyzico"}}},async reportUsage(request){return{success:!0,usageRecordId:`local_ur_${Date.now()}`,quantity:request.quantity,timestamp:request.timestamp??Math.floor(Date.now()/1000),rawResponse:{local:!0,message:"Usage recorded locally for iyzico"}}},async listUsageRecordSummaries(_request){return{success:!0,summaries:[],hasMore:!1,rawResponse:{local:!0,message:"Usage summaries are stored locally for iyzico"}}},async createInvoice(_request){return{success:!0,providerInvoiceId:`local_inv_${Date.now()}`,status:"draft",rawResponse:{local:!0,message:"Invoice stored locally for iyzico"}}},async finalizeInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,status:"open",rawResponse:{local:!0,message:"Invoice finalized locally for iyzico"}}},async sendInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice send is a no-op for iyzico"}}},async voidInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice voided locally for iyzico"}}},async payInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,status:"paid",rawResponse:{local:!0,message:"Invoice payment is a no-op for iyzico"}}},async getInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice data is stored locally for iyzico"}}},async listInvoices(_request){return{success:!0,invoices:[],hasMore:!1,rawResponse:{local:!0,message:"Invoices are stored locally for iyzico"}}},async getBalance(){return{success:!0,available:[],pending:[],rawResponse:{local:!0,message:"Balance is not tracked by iyzico provider"}}},async createPayout(_request){return{success:!0,providerPayoutId:`local_po_${Date.now()}`,status:"pending",rawResponse:{local:!0,message:"Payout created locally for iyzico"}}},async getPayout(request){return{success:!0,providerPayoutId:request.providerPayoutId,rawResponse:{local:!0,message:"Payout data is stored locally for iyzico"}}},async cancelPayout(request){return{success:!0,providerPayoutId:request.providerPayoutId,status:"canceled",rawResponse:{local:!0,message:"Payout cancelled locally for iyzico"}}},async listPayouts(_request){return{success:!0,payouts:[],hasMore:!1,rawResponse:{local:!0,message:"Payouts are stored locally for iyzico"}}},async createTransfer(_request){return{success:!0,providerTransferId:`local_tr_${Date.now()}`,rawResponse:{local:!0,message:"Transfer created locally for iyzico"}}},async listTransfers(_request){return{success:!0,transfers:[],hasMore:!1,rawResponse:{local:!0,message:"Transfers are stored locally for iyzico"}}}}};var init_IyzicoProvider=__esm(()=>{IYZICO_PATHS={INITIALIZE_3DS:"/payment/3dsecure/initialize",COMPLETE_3DS:"/payment/3dsecure/auth",PAYMENT_AUTH:"/payment/auth",PAYMENT_DETAIL:"/payment/detail",BIN_CHECK:"/payment/bin/check",CARD_SAVE:"/cardstorage/card",CARD_LIST:"/cardstorage/cards",CARD_DELETE:"/cardstorage/card/delete",REFUND:"/payment/refund",SUB_MERCHANT_CREATE:"/onboarding/submerchant",SUB_MERCHANT_UPDATE:"/onboarding/submerchant",SUB_MERCHANT_DETAIL:"/onboarding/submerchant/detail",APPROVAL:"/payment/iyzipos/item/approve",DISAPPROVAL:"/payment/iyzipos/item/disapprove"}});var loadStripe=(config)=>{try{let StripeModule=__require("stripe");return new(StripeModule.default??StripeModule)(config.secretKey,{maxNetworkRetries:config.maxNetworkRetries??2,timeout:config.timeout??30000,...config.apiVersion?{apiVersion:config.apiVersion}:{}})}catch(error){return console.error("[Payment:Stripe] Failed to load stripe package. Install it: bun add stripe",error instanceof Error?error.message:error),null}},createStripeProvider=(config)=>{let stripe=loadStripe(config);if(!stripe)return null;let providerName="stripe";return{get name(){return providerName},async initialize3DS(request){try{let params={amount:Math.round(Number(request.paidPrice)*100),currency:request.currency.toLowerCase(),payment_method_types:["card"],description:`Order ${request.conversationId}`,metadata:{conversationId:request.conversationId,basketId:request.basketId??"",buyerEmail:request.buyer.email,buyerId:request.buyer.id}};if("cardToken"in request.paymentCard&&request.paymentCard.cardToken)params.payment_method=request.paymentCard.cardToken,params.confirm=!0,params.return_url=request.callbackUrl;let paymentIntent=await stripe.paymentIntents.create(params),clientSecret=paymentIntent.client_secret,piId=paymentIntent.id,status=paymentIntent.status;return{success:!0,paymentId:piId,threeDSHtmlContent:clientSecret,signature:status,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment initialization failed",rawResponse:{error:err.message}}}},async complete3DS(request){try{let paymentIntent=await stripe.paymentIntents.retrieve(request.paymentId,{expand:["payment_method"]}),status=paymentIntent.status,isSuccess=status==="succeeded",amountReceived=paymentIntent.amount_received??0,card=paymentIntent.payment_method?.card;return{success:isSuccess,paymentId:paymentIntent.id,price:amountReceived/100,paidPrice:amountReceived/100,currency:paymentIntent.currency?.toUpperCase(),cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,cardFamily:card?.funding??void 0,lastFourDigits:card?.last4??void 0,authCode:status,errorCode:isSuccess?void 0:"PAYMENT_NOT_SUCCEEDED",errorMessage:isSuccess?void 0:`Payment status: ${status}`,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment completion failed",rawResponse:{error:err.message}}}},async getPaymentDetail(request){try{let paymentIntent=await stripe.paymentIntents.retrieve(request.paymentId,{expand:["payment_method"]}),amountReceived=paymentIntent.amount_received??paymentIntent.amount??0,card=paymentIntent.payment_method?.card;return{success:!0,paymentId:paymentIntent.id,price:amountReceived/100,paidPrice:amountReceived/100,currency:paymentIntent.currency?.toUpperCase(),cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,lastFourDigits:card?.last4??void 0,binNumber:void 0,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment detail query failed",rawResponse:{error:err.message}}}},async queryBin(_request){return{success:!1,errorCode:"NOT_SUPPORTED",errorMessage:"BIN query is not supported by Stripe. Card info is available after payment method creation.",rawResponse:{}}},async saveCard(request){try{let customer=await stripe.customers.create({email:request.email,metadata:{externalId:request.externalId??""}}),paymentMethod=await stripe.paymentMethods.create({type:"card",card:{number:request.card.cardNumber,exp_month:Number(request.card.expireMonth),exp_year:Number(request.card.expireYear)}});await stripe.paymentMethods.attach(paymentMethod.id,{customer:customer.id});let card=paymentMethod.card;return{success:!0,cardUserKey:customer.id,cardToken:paymentMethod.id,cardAlias:request.card.cardAlias,binNumber:void 0,lastFourDigits:card?.last4??void 0,cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,cardFamily:card?.funding??void 0,cardBankName:void 0,rawResponse:{customer,paymentMethod}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to save card",rawResponse:{error:err.message}}}},async listCards(request){try{let response=await stripe.paymentMethods.list({customer:request.cardUserKey,type:"card"}),cards=response.data.map((pm)=>{let card=pm.card;return{cardToken:pm.id,cardAlias:pm.metadata?.alias??"",binNumber:"",lastFourDigits:card?.last4??"",cardType:card?.brand??"",cardAssociation:card?.brand??"",cardFamily:card?.funding??"",cardBankName:"",cardBankCode:0}});return{success:!0,cardUserKey:request.cardUserKey,cards,rawResponse:response}}catch(error){let err=error;return{success:!1,cards:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list cards",rawResponse:{error:err.message}}}},async deleteCard(request){try{return await stripe.paymentMethods.detach(request.cardToken),{success:!0,rawResponse:{detached:request.cardToken}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to delete card",rawResponse:{error:err.message}}}},async refund(request){try{let amountInCents=Math.round(Number(request.price)*100),refund=await stripe.refunds.create({payment_intent:request.paymentTransactionId,amount:amountInCents});return{success:refund.status==="succeeded",paymentId:refund.payment_intent,price:amountInCents/100,currency:refund.currency?.toUpperCase(),errorCode:refund.status!=="succeeded"?"REFUND_FAILED":void 0,errorMessage:refund.status!=="succeeded"?`Refund status: ${refund.status}`:void 0,rawResponse:refund}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Refund failed",rawResponse:{error:err.message}}}},parseCallback(formData){let paymentIntent=formData.payment_intent??formData.paymentId??"",redirectStatus=formData.redirect_status??"";return{success:redirectStatus==="succeeded",paymentId:paymentIntent,conversationId:formData.conversationId??"",mdStatus:redirectStatus,rawData:formData}},async registerSubMerchant(request){try{let account=await stripe.accounts.create({type:"express",country:request.currency==="TRY"?"TR":void 0,email:request.email,business_type:request.subMerchantType==="personal"?"individual":"company",metadata:{externalId:request.subMerchantExternalId,name:request.name,contactName:request.contactName??"",contactSurname:request.contactSurname??""},capabilities:{transfers:{requested:!0}}});return{success:!0,subMerchantKey:account.id,rawResponse:account}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create connected account",rawResponse:{error:err.message}}}},async updateSubMerchant(request){try{let params={metadata:{}},meta=params.metadata;if(request.name)meta.name=request.name;if(request.email)params.email=request.email;if(request.contactName)meta.contactName=request.contactName;if(request.contactSurname)meta.contactSurname=request.contactSurname;return await stripe.accounts.update(request.subMerchantKey,params),{success:!0,rawResponse:{updated:request.subMerchantKey}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update connected account",rawResponse:{error:err.message}}}},async getSubMerchant(request){try{let account=await stripe.accounts.retrieve(request.subMerchantExternalId),meta=account.metadata??{};return{success:!0,subMerchantKey:account.id,name:meta.name,email:account.email,subMerchantType:account.business_type==="individual"?"personal":"company",currency:account.default_currency?.toUpperCase(),rawResponse:account}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to retrieve connected account",rawResponse:{error:err.message}}}},async approveSplit(request){return{success:!0,paymentTransactionId:request.paymentTransactionId,rawResponse:{message:"Stripe transfers are automatic; no manual approval needed."}}},async disapproveSplit(request){try{let reversal=await stripe.transfers.createReversal(request.paymentTransactionId);return{success:!0,paymentTransactionId:reversal.id,rawResponse:reversal}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to reverse transfer",rawResponse:{error:err.message}}}},async createProduct(request){try{let params={name:request.name};if(request.description)params.description=request.description;if(request.type)params.type=request.type;if(request.images)params.images=request.images;if(request.unitLabel)params.unit_label=request.unitLabel;if(request.url)params.url=request.url;if(request.metadata)params.metadata=request.metadata;let product=await stripe.products.create(params);return{success:!0,providerProductId:product.id,name:product.name,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create product",rawResponse:{error:err.message}}}},async updateProduct(request){try{let params={};if(request.name)params.name=request.name;if(request.description!==void 0)params.description=request.description;if(request.images)params.images=request.images;if(request.unitLabel!==void 0)params.unit_label=request.unitLabel;if(request.url!==void 0)params.url=request.url;if(request.active!==void 0)params.active=request.active;if(request.metadata)params.metadata=request.metadata;let product=await stripe.products.update(request.providerProductId,params);return{success:!0,providerProductId:product.id,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update product",rawResponse:{error:err.message}}}},async getProduct(request){try{let product=await stripe.products.retrieve(request.providerProductId);return{success:!0,providerProductId:product.id,name:product.name,description:product.description,type:product.type,active:product.active,images:product.images,unitLabel:product.unit_label,url:product.url,metadata:product.metadata,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get product",rawResponse:{error:err.message}}}},async listProducts(request){try{let params={};if(request.active!==void 0)params.active=request.active;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.products.list(params);return{success:!0,products:response.data.map((p)=>({providerProductId:p.id,name:p.name,description:p.description,type:p.type,active:p.active,images:p.images,unitLabel:p.unit_label,metadata:p.metadata})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,products:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list products",rawResponse:{error:err.message}}}},async archiveProduct(request){try{return await stripe.products.update(request.providerProductId,{active:!1}),{success:!0,rawResponse:{archived:request.providerProductId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to archive product",rawResponse:{error:err.message}}}},async createPrice(request){try{let params={product:request.providerProductId,currency:request.currency.toLowerCase(),unit_amount:request.unitAmount};if(request.nickname)params.nickname=request.nickname;if(request.billingScheme)params.billing_scheme=request.billingScheme;if(request.unitAmountDecimal)params.unit_amount_decimal=request.unitAmountDecimal;if(request.metadata)params.metadata=request.metadata;if(request.recurring)params.recurring={interval:request.recurring.interval,...request.recurring.intervalCount?{interval_count:request.recurring.intervalCount}:{},...request.recurring.usageType?{usage_type:request.recurring.usageType}:{},...request.recurring.aggregateUsage?{aggregate_usage:request.recurring.aggregateUsage}:{}};if(request.transformQuantity)params.transform_quantity={divide_by:request.transformQuantity.divideBy,round:request.transformQuantity.round};let price=await stripe.prices.create(params);return{success:!0,providerPriceId:price.id,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create price",rawResponse:{error:err.message}}}},async updatePrice(request){try{let params={};if(request.nickname!==void 0)params.nickname=request.nickname;if(request.active!==void 0)params.active=request.active;if(request.metadata)params.metadata=request.metadata;let price=await stripe.prices.update(request.providerPriceId,params);return{success:!0,providerPriceId:price.id,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update price",rawResponse:{error:err.message}}}},async getPrice(request){try{let price=await stripe.prices.retrieve(request.providerPriceId),rec=price.recurring;return{success:!0,providerPriceId:price.id,providerProductId:price.product,currency:price.currency?.toUpperCase(),unitAmount:price.unit_amount,type:price.type,billingScheme:price.billing_scheme,nickname:price.nickname,active:price.active,recurring:rec?{interval:rec.interval,intervalCount:rec.interval_count??1,usageType:rec.usage_type}:void 0,metadata:price.metadata,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get price",rawResponse:{error:err.message}}}},async listPrices(request){try{let params={};if(request.providerProductId)params.product=request.providerProductId;if(request.active!==void 0)params.active=request.active;if(request.type)params.type=request.type;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.prices.list(params);return{success:!0,prices:response.data.map((p)=>{let rec=p.recurring;return{providerPriceId:p.id,providerProductId:p.product,currency:p.currency?.toUpperCase(),unitAmount:p.unit_amount,type:p.type,billingScheme:p.billing_scheme,nickname:p.nickname,active:p.active,recurring:rec?{interval:rec.interval,intervalCount:rec.interval_count??1,usageType:rec.usage_type}:void 0,metadata:p.metadata}}),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,prices:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list prices",rawResponse:{error:err.message}}}},async archivePrice(request){try{return await stripe.prices.update(request.providerPriceId,{active:!1}),{success:!0,rawResponse:{archived:request.providerPriceId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to archive price",rawResponse:{error:err.message}}}},async createCustomer(request){try{let params={email:request.email};if(request.name)params.name=request.name;if(request.phone)params.phone=request.phone;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.address)params.address={line1:request.address.line1,line2:request.address.line2,city:request.address.city,state:request.address.state,postal_code:request.address.postalCode,country:request.address.country};let customer=await stripe.customers.create(params);if(request.taxId)try{await stripe.taxIds?.create({customer:customer.id,type:request.taxId.type,value:request.taxId.value})}catch(_){}return{success:!0,providerCustomerId:customer.id,email:customer.email,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create customer",rawResponse:{error:err.message}}}},async updateCustomer(request){try{let params={};if(request.email)params.email=request.email;if(request.name!==void 0)params.name=request.name;if(request.phone!==void 0)params.phone=request.phone;if(request.description!==void 0)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.address)params.address={line1:request.address.line1,line2:request.address.line2,city:request.address.city,state:request.address.state,postal_code:request.address.postalCode,country:request.address.country};let customer=await stripe.customers.update(request.providerCustomerId,params);return{success:!0,providerCustomerId:customer.id,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update customer",rawResponse:{error:err.message}}}},async getCustomer(request){try{let customer=await stripe.customers.retrieve(request.providerCustomerId);return{success:!0,providerCustomerId:customer.id,email:customer.email,name:customer.name,phone:customer.phone,description:customer.description,metadata:customer.metadata,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get customer",rawResponse:{error:err.message}}}},async listCustomers(request){try{let params={};if(request.email)params.email=request.email;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.customers.list(params);return{success:!0,customers:response.data.map((c)=>({providerCustomerId:c.id,email:c.email,name:c.name,phone:c.phone})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,customers:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list customers",rawResponse:{error:err.message}}}},async deleteCustomer(request){try{return await stripe.customers.del(request.providerCustomerId),{success:!0,rawResponse:{deleted:request.providerCustomerId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to delete customer",rawResponse:{error:err.message}}}},async createSubscription(request){try{let params={customer:request.providerCustomerId,items:request.items.map((i)=>({price:i.providerPriceId,...i.quantity!==void 0?{quantity:i.quantity}:{}}))};if(request.trialPeriodDays)params.trial_period_days=request.trialPeriodDays;if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.cancelAtPeriodEnd!==void 0)params.cancel_at_period_end=request.cancelAtPeriodEnd;if(request.metadata)params.metadata=request.metadata;if(request.defaultPaymentMethod)params.default_payment_method=request.defaultPaymentMethod;params.payment_behavior="default_incomplete",params.payment_settings={save_default_payment_method:"on_subscription"},params.expand=["latest_invoice.payment_intent"];let sub=await stripe.subscriptions.create(params),pi=sub.latest_invoice?.payment_intent;return{success:!0,providerSubscriptionId:sub.id,status:sub.status,currentPeriodStart:sub.current_period_start?new Date(sub.current_period_start*1000).toISOString():void 0,currentPeriodEnd:sub.current_period_end?new Date(sub.current_period_end*1000).toISOString():void 0,clientSecret:pi?.client_secret,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create subscription",rawResponse:{error:err.message}}}},async updateSubscription(request){try{let params={};if(request.items)params.items=request.items.map((i)=>({...i.id?{id:i.id}:{},price:i.providerPriceId,...i.quantity!==void 0?{quantity:i.quantity}:{}}));if(request.cancelAtPeriodEnd!==void 0)params.cancel_at_period_end=request.cancelAtPeriodEnd;if(request.trialEnd!==void 0)params.trial_end=request.trialEnd;if(request.metadata)params.metadata=request.metadata;if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.defaultPaymentMethod)params.default_payment_method=request.defaultPaymentMethod;if(request.prorationBehavior)params.proration_behavior=request.prorationBehavior;let sub=await stripe.subscriptions.update(request.providerSubscriptionId,params);return{success:!0,providerSubscriptionId:sub.id,status:sub.status,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update subscription",rawResponse:{error:err.message}}}},async cancelSubscription(request){try{if(request.cancelAtPeriodEnd){let sub2=await stripe.subscriptions.update(request.providerSubscriptionId,{cancel_at_period_end:!0});return{success:!0,providerSubscriptionId:sub2.id,status:sub2.status,rawResponse:sub2}}let params={};if(request.invoiceNow)params.invoice_now=request.invoiceNow;if(request.prorate)params.prorate=request.prorate;let sub=await stripe.subscriptions.cancel(request.providerSubscriptionId,params);return{success:!0,providerSubscriptionId:sub.id,status:sub.status,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to cancel subscription",rawResponse:{error:err.message}}}},async getSubscription(request){try{let sub=await stripe.subscriptions.retrieve(request.providerSubscriptionId),itemsData=sub.items?.data??[];return{success:!0,providerSubscriptionId:sub.id,providerCustomerId:sub.customer,status:sub.status,currentPeriodStart:sub.current_period_start?new Date(sub.current_period_start*1000).toISOString():void 0,currentPeriodEnd:sub.current_period_end?new Date(sub.current_period_end*1000).toISOString():void 0,cancelAtPeriodEnd:sub.cancel_at_period_end,canceledAt:sub.canceled_at?new Date(sub.canceled_at*1000).toISOString():void 0,trialStart:sub.trial_start?new Date(sub.trial_start*1000).toISOString():void 0,trialEnd:sub.trial_end?new Date(sub.trial_end*1000).toISOString():void 0,items:itemsData.map((i)=>({id:i.id,providerPriceId:i.price?.id??i.price,quantity:i.quantity??1})),metadata:sub.metadata,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get subscription",rawResponse:{error:err.message}}}},async listSubscriptions(request){try{let params={};if(request.providerCustomerId)params.customer=request.providerCustomerId;if(request.status)params.status=request.status;if(request.providerPriceId)params.price=request.providerPriceId;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.subscriptions.list(params);return{success:!0,subscriptions:response.data.map((s)=>({providerSubscriptionId:s.id,providerCustomerId:s.customer,status:s.status,currentPeriodStart:s.current_period_start?new Date(s.current_period_start*1000).toISOString():void 0,currentPeriodEnd:s.current_period_end?new Date(s.current_period_end*1000).toISOString():void 0,cancelAtPeriodEnd:s.cancel_at_period_end})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,subscriptions:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list subscriptions",rawResponse:{error:err.message}}}},async reportUsage(request){try{let params={quantity:request.quantity,action:request.action??"increment"};if(request.timestamp)params.timestamp=request.timestamp;let record=await stripe.subscriptionItems.usageRecords.create(request.subscriptionItemId,params);return{success:!0,usageRecordId:record.id,quantity:record.quantity,timestamp:record.timestamp,rawResponse:record}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to report usage",rawResponse:{error:err.message}}}},async listUsageRecordSummaries(request){try{let params={};if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.subscriptionItems.usageRecordSummaries.list(request.subscriptionItemId,params);return{success:!0,summaries:response.data.map((s)=>({id:s.id,totalUsage:s.total_usage,period:s.period,subscriptionItem:s.subscription_item})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,summaries:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list usage summaries",rawResponse:{error:err.message}}}},async createInvoice(request){try{let params={customer:request.providerCustomerId};if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.autoAdvance!==void 0)params.auto_advance=request.autoAdvance;let invoice=await stripe.invoices.create(params);if(request.items?.length)for(let item of request.items){let lineParams={customer:request.providerCustomerId,invoice:invoice.id};if(item.providerPriceId)lineParams.price=item.providerPriceId;if(item.quantity)lineParams.quantity=item.quantity;if(item.unitAmount!==void 0)lineParams.unit_amount=item.unitAmount;if(item.currency)lineParams.currency=item.currency;if(item.description)lineParams.description=item.description;await stripe.invoiceItems.create(lineParams)}return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create invoice",rawResponse:{error:err.message}}}},async finalizeInvoice(request){try{let params={};if(request.autoAdvance!==void 0)params.auto_advance=request.autoAdvance;let invoice=await stripe.invoices.finalizeInvoice(request.providerInvoiceId,params);return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to finalize invoice",rawResponse:{error:err.message}}}},async sendInvoice(request){try{let invoice=await stripe.invoices.sendInvoice(request.providerInvoiceId);return{success:!0,providerInvoiceId:invoice.id,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to send invoice",rawResponse:{error:err.message}}}},async voidInvoice(request){try{let invoice=await stripe.invoices.voidInvoice(request.providerInvoiceId);return{success:!0,providerInvoiceId:invoice.id,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to void invoice",rawResponse:{error:err.message}}}},async payInvoice(request){try{let params={};if(request.paymentMethod)params.payment_method=request.paymentMethod;let invoice=await stripe.invoices.pay(request.providerInvoiceId,params);return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,amountPaid:invoice.amount_paid,amountDue:invoice.amount_due,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to pay invoice",rawResponse:{error:err.message}}}},async getInvoice(request){try{let invoice=await stripe.invoices.retrieve(request.providerInvoiceId),linesData=invoice.lines?.data??[];return{success:!0,providerInvoiceId:invoice.id,providerCustomerId:invoice.customer,providerSubscriptionId:invoice.subscription,status:invoice.status,amountDue:invoice.amount_due,amountPaid:invoice.amount_paid,amountRemaining:invoice.amount_remaining,currency:invoice.currency?.toUpperCase(),description:invoice.description,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,dueDate:invoice.due_date?new Date(invoice.due_date*1000).toISOString():void 0,periodStart:invoice.period_start?new Date(invoice.period_start*1000).toISOString():void 0,periodEnd:invoice.period_end?new Date(invoice.period_end*1000).toISOString():void 0,metadata:invoice.metadata,lines:linesData.map((l)=>({id:l.id,description:l.description,amount:l.amount,currency:l.currency?.toUpperCase(),quantity:l.quantity,providerPriceId:l.price?.id})),rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get invoice",rawResponse:{error:err.message}}}},async listInvoices(request){try{let params={};if(request.providerCustomerId)params.customer=request.providerCustomerId;if(request.providerSubscriptionId)params.subscription=request.providerSubscriptionId;if(request.status)params.status=request.status;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.invoices.list(params);return{success:!0,invoices:response.data.map((inv)=>({providerInvoiceId:inv.id,providerCustomerId:inv.customer,status:inv.status,amountDue:inv.amount_due,amountPaid:inv.amount_paid,currency:inv.currency?.toUpperCase(),dueDate:inv.due_date?new Date(inv.due_date*1000).toISOString():void 0,hostedInvoiceUrl:inv.hosted_invoice_url})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,invoices:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list invoices",rawResponse:{error:err.message}}}},async getBalance(){try{let bal=await stripe.balance.retrieve(),mapAmounts=(arr)=>(arr??[]).map((a)=>({amount:a.amount,currency:a.currency?.toUpperCase()}));return{success:!0,available:mapAmounts(bal.available),pending:mapAmounts(bal.pending),connectReserved:mapAmounts(bal.connect_reserved),rawResponse:bal}}catch(error){let err=error;return{success:!1,available:[],pending:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get balance",rawResponse:{error:err.message}}}},async createPayout(request){try{let params={amount:request.amount,currency:request.currency.toLowerCase()};if(request.destination)params.destination=request.destination;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.method)params.method=request.method;if(request.sourceType)params.source_type=request.sourceType;if(request.statementDescriptor)params.statement_descriptor=request.statementDescriptor;let payout=await stripe.payouts.create(params);return{success:!0,providerPayoutId:payout.id,amount:payout.amount,currency:payout.currency?.toUpperCase(),status:payout.status,arrivalDate:payout.arrival_date?new Date(payout.arrival_date*1000).toISOString():void 0,method:payout.method,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create payout",rawResponse:{error:err.message}}}},async getPayout(request){try{let payout=await stripe.payouts.retrieve(request.providerPayoutId);return{success:!0,providerPayoutId:payout.id,amount:payout.amount,currency:payout.currency?.toUpperCase(),status:payout.status,arrivalDate:payout.arrival_date?new Date(payout.arrival_date*1000).toISOString():void 0,method:payout.method,description:payout.description,destination:payout.destination,metadata:payout.metadata,failureCode:payout.failure_code,failureMessage:payout.failure_message,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get payout",rawResponse:{error:err.message}}}},async cancelPayout(request){try{let payout=await stripe.payouts.cancel(request.providerPayoutId);return{success:!0,providerPayoutId:payout.id,status:payout.status,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to cancel payout",rawResponse:{error:err.message}}}},async listPayouts(request){try{let params={};if(request.status)params.status=request.status;if(request.destination)params.destination=request.destination;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;if(request.arrivalDateGte||request.arrivalDateLte){let arrival={};if(request.arrivalDateGte)arrival.gte=request.arrivalDateGte;if(request.arrivalDateLte)arrival.lte=request.arrivalDateLte;params.arrival_date=arrival}let response=await stripe.payouts.list(params);return{success:!0,payouts:response.data.map((p)=>({providerPayoutId:p.id,amount:p.amount,currency:p.currency?.toUpperCase(),status:p.status,arrivalDate:p.arrival_date?new Date(p.arrival_date*1000).toISOString():void 0,method:p.method,description:p.description})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,payouts:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list payouts",rawResponse:{error:err.message}}}},async createTransfer(request){try{let params={amount:request.amount,currency:request.currency.toLowerCase(),destination:request.destination};if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.sourceTransaction)params.source_transaction=request.sourceTransaction;if(request.transferGroup)params.transfer_group=request.transferGroup;let transfer=await stripe.transfers.create(params);return{success:!0,providerTransferId:transfer.id,amount:transfer.amount,currency:transfer.currency?.toUpperCase(),destination:transfer.destination,rawResponse:transfer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create transfer",rawResponse:{error:err.message}}}},async listTransfers(request){try{let params={};if(request.destination)params.destination=request.destination;if(request.transferGroup)params.transfer_group=request.transferGroup;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.transfers.list(params);return{success:!0,transfers:response.data.map((t)=>({providerTransferId:t.id,amount:t.amount,currency:t.currency?.toUpperCase(),destination:t.destination,description:t.description,created:t.created?new Date(t.created*1000).toISOString():void 0})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,transfers:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list transfers",rawResponse:{error:err.message}}}}}},verifyStripeWebhook=(rawBody,signature,webhookSecret)=>{try{let StripeModule=__require("stripe");return{success:!0,event:new(StripeModule.default??StripeModule)("sk_dummy_for_webhook_verification").webhooks.constructEvent(rawBody,signature,webhookSecret)}}catch(error){return{success:!1,event:null,error:error instanceof Error?error.message:"Webhook verification failed"}}};var resolveEnvValue=(value)=>{let envValue=process.env[value];if(envValue)return envValue;return value},createPaymentService=(config)=>{let paymentConfig=config.payment;if(!paymentConfig?.enabled)return null;let providerName=paymentConfig.provider;if(!providerName)return console.warn("[Payment] payment.enabled=true but no provider specified"),null;let providerConfig=null,provider=null,webhookSecret;switch(providerName){case"iyzico":{let iyzicoConf=paymentConfig.iyzico;if(!iyzicoConf)return console.warn("[Payment] payment.provider=iyzico but no iyzico config block"),null;let apiUrl=resolveEnvValue(iyzicoConf.apiUrl),apiKey=resolveEnvValue(iyzicoConf.apiKey),secretKey=resolveEnvValue(iyzicoConf.secretKey);if(!apiUrl||!apiKey||!secretKey)return console.warn("[Payment] iyzico credentials missing. Ensure env vars are set:",{apiUrl:iyzicoConf.apiUrl,apiKey:iyzicoConf.apiKey,secretKey:iyzicoConf.secretKey}),null;providerConfig={name:"iyzico",apiUrl,apiKey,secretKey},provider=createIyzicoProvider(providerConfig);break}case"stripe":{let stripeConf=paymentConfig.stripe;if(!stripeConf)return console.warn("[Payment] payment.provider=stripe but no stripe config block"),null;let secretKey=resolveEnvValue(stripeConf.secretKey),whSecret=resolveEnvValue(stripeConf.webhookSecret);if(!secretKey)return console.warn("[Payment] Stripe secret key missing. Ensure env var is set:",{secretKey:stripeConf.secretKey}),null;if(!whSecret)console.warn("[Payment] Stripe webhook secret missing. Webhook verification will fail.",{webhookSecret:stripeConf.webhookSecret});webhookSecret=whSecret,provider=createStripeProvider({secretKey,webhookSecret:whSecret,apiVersion:stripeConf.apiVersion,maxNetworkRetries:stripeConf.maxNetworkRetries,timeout:stripeConf.timeout});break}default:return console.warn(`[Payment] Unknown provider: ${providerName}`),null}if(!provider)return null;return console.log(`[Payment] Initialized provider: ${providerName}`),{provider:providerName,providerInstance:provider,webhookSecret}};var init_PaymentService=__esm(()=>{init_IyzicoProvider()});var exports_Payment={};__export(exports_Payment,{verifyStripeWebhook:()=>verifyStripeWebhook,createStripeProvider:()=>createStripeProvider,createPaymentService:()=>createPaymentService,createIyzicoProvider:()=>createIyzicoProvider});var init_Payment=__esm(()=>{init_IyzicoProvider();init_PaymentService()});var init_Services=__esm(()=>{init_ApiKey();init_Auth();init_Authorization();init_Backup();init_Captcha();init_Email();init_Gmail();init_Logger2();init_Monitoring();init_Notification();init_OAuth();init_RateLimiter();init_Tenant();init_Verification();init_Payment()});import path2 from"path";import Elysia2,{t}from"elysia";function mergeCdnConfig(config){if(!config)return DEFAULT_CDN_CONFIG;return{enabled:config.enabled??DEFAULT_CDN_CONFIG.enabled,basePath:config.basePath??DEFAULT_CDN_CONFIG.basePath,cacheMaxAge:config.cacheMaxAge??DEFAULT_CDN_CONFIG.cacheMaxAge,enableRangeRequests:config.enableRangeRequests??DEFAULT_CDN_CONFIG.enableRangeRequests,enableEtag:config.enableEtag??DEFAULT_CDN_CONFIG.enableEtag,corsOrigins:config.corsOrigins??DEFAULT_CDN_CONFIG.corsOrigins}}function getMimeTypeDisposition(mimeType){let inlineTypes=["image/","video/","audio/","text/","application/pdf"];for(let type of inlineTypes)if(mimeType.startsWith(type)||mimeType===type)return"inline";return"attachment"}function sanitizeFilename(filename){return filename.replace(/[^A-Za-z0-9._-]+/g,"_").replace(/_{2,}/g,"_").slice(0,200)}function createCdnRoutes(config){let{cdn,storagePath,logger:logger2,getFileRecord}=config,plugin=new Elysia2({prefix:cdn.basePath});if(!cdn.enabled)return plugin;return plugin.get("/:id",async({params,request,set})=>{let{id}=params,schemaName=request.headers.get("x-schema-name")||void 0,filePath,fileName,mimeType;if(getFileRecord){let fileRecord=await getFileRecord(id,schemaName);if(!fileRecord)return set.status=404,{success:!1,message:"File not found"};filePath=path2.join(fileRecord.path,fileRecord.name),fileName=fileRecord.name,mimeType=fileRecord.mimeType||fileRecord.mime_type||"application/octet-stream"}else filePath=path2.join(storagePath,id),fileName=id,mimeType="application/octet-stream";if(!await fileManager.exists(filePath))return set.status=404,{success:!1,message:"Physical file not found"};let fileInfo=await fileManager.getFileInfo(filePath),lastModified=new Date(fileInfo.modifiedAt||Date.now()).toUTCString(),etag=cdn.enableEtag?`"${fileInfo.size}-${fileInfo.modifiedAt?.getTime()||Date.now()}"`:void 0,cacheHeaders={"Cache-Control":`public, max-age=${cdn.cacheMaxAge}`,"Last-Modified":lastModified};if(etag)cacheHeaders.ETag=etag;if(cdn.corsOrigins.length>0)cacheHeaders["Access-Control-Allow-Origin"]=cdn.corsOrigins[0]==="*"?"*":cdn.corsOrigins.join(", "),cacheHeaders["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";let ifNoneMatch=request.headers.get("if-none-match");if(etag&&ifNoneMatch===etag)return new Response(null,{status:304,headers:cacheHeaders});let bunFile=Bun.file(filePath),range=request.headers.get("range");if(cdn.enableRangeRequests&&range){let rangeMatch=range.match(/bytes=(\d*)-(\d*)/);if(!rangeMatch)return set.status=416,new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${fileInfo.size}`,"Content-Type":mimeType,...cacheHeaders}});let startStr=rangeMatch[1]||"0",endStr=rangeMatch[2]||"",start=parseInt(startStr,10),end=endStr?parseInt(endStr,10):fileInfo.size-1;if(start>=fileInfo.size||end>=fileInfo.size||start>end)return new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${fileInfo.size}`,"Content-Type":mimeType,...cacheHeaders}});let chunkSize=end-start+1,chunkBlob=bunFile.slice(start,end+1);return new Response(chunkBlob,{status:206,headers:{"Content-Range":`bytes ${start}-${end}/${fileInfo.size}`,"Accept-Ranges":"bytes","Content-Length":chunkSize.toString(),"Content-Type":mimeType,...cacheHeaders}})}let dispositionType=getMimeTypeDisposition(mimeType),asciiFallbackName=sanitizeFilename(fileName),encodedUtf8Name=encodeURIComponent(fileName),contentDisposition=`${dispositionType}; filename="${asciiFallbackName}"; filename*=UTF-8''${encodedUtf8Name}`;return new Response(bunFile,{status:200,headers:{"Content-Length":fileInfo.size.toString(),"Content-Type":mimeType,"Accept-Ranges":cdn.enableRangeRequests?"bytes":"none","Content-Disposition":contentDisposition,...cacheHeaders}})},{params:t.Object({id:t.String()}),detail:{tags:["CDN"],summary:"Get file by ID",description:"Serve file with streaming, range requests, and caching support"}}),plugin.head("/:id",async({params,request,set})=>{let{id}=params,schemaName=request.headers.get("x-schema-name")||void 0,filePath,mimeType;if(getFileRecord){let fileRecord=await getFileRecord(id,schemaName);if(!fileRecord)return set.status=404,new Response(null,{status:404});filePath=path2.join(fileRecord.path,fileRecord.name),mimeType=fileRecord.mime_type||"application/octet-stream"}else filePath=path2.join(storagePath,id),mimeType="application/octet-stream";if(!await fileManager.exists(filePath))return set.status=404,new Response(null,{status:404});let fileInfo=await fileManager.getFileInfo(filePath),lastModified=new Date(fileInfo.modifiedAt||Date.now()).toUTCString(),etag=cdn.enableEtag?`"${fileInfo.size}-${fileInfo.modifiedAt?.getTime()||Date.now()}"`:void 0,headers={"Content-Length":fileInfo.size.toString(),"Content-Type":mimeType,"Accept-Ranges":cdn.enableRangeRequests?"bytes":"none","Cache-Control":`public, max-age=${cdn.cacheMaxAge}`,"Last-Modified":lastModified};if(etag)headers.ETag=etag;if(cdn.corsOrigins.length>0)headers["Access-Control-Allow-Origin"]=cdn.corsOrigins[0]==="*"?"*":cdn.corsOrigins.join(", "),headers["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";return new Response(null,{status:200,headers})},{params:t.Object({id:t.String()}),detail:{tags:["CDN"],summary:"Get file metadata",description:"Get file headers without body for preflight checks"}}),logger2.info(`[CDN] Routes enabled at ${cdn.basePath}`),plugin}var DEFAULT_CDN_CONFIG;var init_cdn=__esm(()=>{init_File();DEFAULT_CDN_CONFIG={enabled:!0,basePath:"/cdn",cacheMaxAge:86400,enableRangeRequests:!0,enableEtag:!0,corsOrigins:["*"]}});import{randomUUID as randomUUID4}from"crypto";import path3 from"path";function mergeStorageConfig(config){if(!config)return DEFAULT_STORAGE_CONFIG;return{enabled:config.enabled??DEFAULT_STORAGE_CONFIG.enabled,basePath:config.basePath??DEFAULT_STORAGE_CONFIG.basePath,maxFileSizeBytes:config.maxFileSizeBytes??DEFAULT_STORAGE_CONFIG.maxFileSizeBytes,allowedMimeTypes:config.allowedMimeTypes??DEFAULT_STORAGE_CONFIG.allowedMimeTypes,blockedMimeTypes:config.blockedMimeTypes??DEFAULT_STORAGE_CONFIG.blockedMimeTypes,formData:{filesField:config.formData?.filesField??DEFAULT_STORAGE_CONFIG.formData.filesField,dataField:config.formData?.dataField??DEFAULT_STORAGE_CONFIG.formData.dataField,maxFiles:config.formData?.maxFiles??DEFAULT_STORAGE_CONFIG.formData.maxFiles}}}function parseFormDataBody(body,config){let result={data:{},files:[]};if(!body||typeof body!=="object")return result;let bodyObj=body,dataField=bodyObj[config.formData.dataField];if(dataField){if(typeof dataField==="string")try{result.data=JSON.parse(dataField)}catch{result.data={}}else if(typeof dataField==="object")result.data=dataField}let filesField=bodyObj[config.formData.filesField];if(filesField){if(filesField instanceof File)result.files=[filesField];else if(Array.isArray(filesField))result.files=filesField.filter((f)=>f instanceof File)}return result}function validateFile(file,config){if(file.size>config.maxFileSizeBytes)return{valid:!1,error:`File ${file.name} exceeds maximum size of ${config.maxFileSizeBytes} bytes`};if(config.blockedMimeTypes.length>0&&config.blockedMimeTypes.includes(file.type))return{valid:!1,error:`File type ${file.type} is not allowed`};if(config.allowedMimeTypes.length>0&&!config.allowedMimeTypes.includes(file.type))return{valid:!1,error:`File type ${file.type} is not in allowed list`};return{valid:!0}}async function uploadFile(file,config,subFolder){let id=randomUUID4(),ext=path3.extname(file.name),uniqueName=`${id}${ext}`,folderPath=subFolder?path3.join(config.basePath,subFolder):config.basePath,arrayBuffer=await file.arrayBuffer(),buffer=new Uint8Array(arrayBuffer);return await fileManager.createFile({dir:folderPath,name:uniqueName,data:buffer,options:{type:file.type,createDir:!0}}),{id,name:uniqueName,originalName:file.name,path:folderPath,mimeType:file.type,size:file.size,createdAt:new Date}}async function uploadFiles(files,config,subFolder){let success=[],failed=[];for(let file of files.slice(0,config.formData.maxFiles)){let validation=validateFile(file,config);if(!validation.valid){failed.push({file:file.name,error:validation.error||"Unknown error"});continue}try{let result=await uploadFile(file,config,subFolder);success.push(result)}catch(error){failed.push({file:file.name,error:error instanceof Error?error.message:"Upload failed"})}}return{success,failed}}async function deleteFile(filePath,fileName){try{let fullPath=path3.join(filePath,fileName);return await fileManager.deleteFile(fullPath)}catch{return!1}}var DEFAULT_STORAGE_CONFIG;var init_helpers=__esm(()=>{init_File();DEFAULT_STORAGE_CONFIG={enabled:!1,basePath:"./uploads",maxFileSizeBytes:104857600,allowedMimeTypes:[],blockedMimeTypes:["application/x-executable","application/x-msdos-program"],formData:{filesField:"files",dataField:"data",maxFiles:10}}});var exports_storage={};__export(exports_storage,{validateFile:()=>validateFile,uploadFiles:()=>uploadFiles,uploadFile:()=>uploadFile,parseFormDataBody:()=>parseFormDataBody,mergeStorageConfig:()=>mergeStorageConfig,mergeCdnConfig:()=>mergeCdnConfig,deleteFile:()=>deleteFile,createCdnRoutes:()=>createCdnRoutes});var init_storage=__esm(()=>{init_cdn();init_helpers()});import crypto6 from"crypto";var{password:password2}=globalThis.Bun;async function hashPassword(plainPassword){return await password2.hash(plainPassword,{algorithm:"bcrypt",cost:10})}function generateVerificationToken(){return crypto6.randomBytes(32).toString("hex")}function parseTimeToMs2(time){let match=time.match(/^(\d+)(s|m|h|d)$/);if(!match||!match[1]||!match[2])return 86400000;let value=Number.parseInt(match[1],10);switch(match[2]){case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*24*60*60*1000;default:return 86400000}}function validatePasswordStrength(pwd){let errors=[];if(pwd.length<8)errors.push("Password must be at least 8 characters");if(!/[A-Z]/.test(pwd))errors.push("Password must contain uppercase letter");if(!/[a-z]/.test(pwd))errors.push("Password must contain lowercase letter");if(!/[0-9]/.test(pwd))errors.push("Password must contain a number");return{valid:errors.length===0,errors}}var init_utils6=()=>{};var resolveAuthTablesForRequest=(request,authConfig)=>{let defaults={usersTable:authConfig.usersTable,sessionsTable:authConfig.sessionsTable??null,userRolesTable:authConfig.userRolesTable??void 0,rolesTable:authConfig.rolesTable??void 0,roleClaimsTable:authConfig.roleClaimsTable??void 0,claimsTable:authConfig.claimsTable??void 0,oauthAccountsTable:authConfig.oauthAccountsTable??void 0,apiKeysTable:authConfig.apiKeysTable??void 0,schemaTables:authConfig.schemaTables||{}},registry=authConfig.tenantRegistry;if(!registry)return defaults;let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return defaults;let ctx=registry.getSchemaContext(schemaName);if(!ctx)return defaults;let tables=ctx.schemaTables;return{usersTable:tables.users??defaults.usersTable,sessionsTable:tables.userSessions??tables.user_sessions??tables.sessions??defaults.sessionsTable,userRolesTable:tables.userRoles??defaults.userRolesTable,rolesTable:tables.roles??defaults.rolesTable,roleClaimsTable:tables.roleClaims??defaults.roleClaimsTable,claimsTable:tables.claims??defaults.claimsTable,oauthAccountsTable:tables.oauthAccounts??defaults.oauthAccountsTable,apiKeysTable:tables.apiKeys??defaults.apiKeysTable,schemaTables:tables}};import{eq as eq15,sql as sql3}from"drizzle-orm";import{Elysia as Elysia13,t as t12}from"elysia";function createChangeUserIdRoute(config,schemaName="public"){let{db,logger:logger2}=config,routes=new Elysia13;return routes.post("/auth/admin/change-user-id",async(ctx)=>{let{usersTable}=resolveAuthTablesForRequest(ctx.request,config);if(!db||!usersTable)return{success:!1,message:"Database not configured"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Unauthorized"};let requestingUser=(await db.select().from(usersTable).where(eq15(usersTable.id,requestingUserId)).limit(1))[0];if(!requestingUser||!requestingUser.isGod)return ctx.set.status=403,{success:!1,message:"Forbidden: godmin privileges required"};let{currentId,newId}=ctx.body;if(!currentId||!newId)return ctx.set.status=400,{success:!1,message:"currentId and newId are required"};if(currentId===newId)return ctx.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(newId))return ctx.set.status=400,{success:!1,message:"newId must be a valid UUID"};let targetUser=(await db.select().from(usersTable).where(eq15(usersTable.id,currentId)).limit(1))[0];if(!targetUser)return ctx.set.status=404,{success:!1,message:"User not found"};if((await db.select().from(usersTable).where(eq15(usersTable.id,newId)).limit(1)).length>0)return ctx.set.status=409,{success:!1,message:"A user with this ID already exists"};try{let fkResult=await db.execute(sql3`
|
|
60
|
+
`}getActiveAlerts(){return Array.from(this.state.activeAlerts.values())}acknowledgeAlert(alertId){for(let[_type,alert]of this.state.activeAlerts)if(alert.id===alertId)return alert.acknowledged=!0,!0;return!1}clearAlert(type){this.state.activeAlerts.delete(type)}}class ApplicationCollector{config;requestCount=0;responseTimes=[];errorCount=0;rateLimitBlocks=0;byEndpoint={};byMethod={};byStatus={};byErrorType={};lastCollectTime=Date.now();constructor(config){this.config=config}recordRequest(params){if(!this.config?.enabled)return;if(this.requestCount++,this.config.metrics?.responseTime!==!1){if(this.responseTimes.push(params.responseTimeMs),this.responseTimes.length>1e4)this.responseTimes=this.responseTimes.slice(-5000)}if(this.config.metrics?.requests!==!1)this.byEndpoint[params.endpoint]=(this.byEndpoint[params.endpoint]||0)+1,this.byMethod[params.method]=(this.byMethod[params.method]||0)+1,this.byStatus[String(params.status)]=(this.byStatus[String(params.status)]||0)+1;if(this.config.metrics?.errors!==!1&¶ms.isError){if(this.errorCount++,params.errorType)this.byErrorType[params.errorType]=(this.byErrorType[params.errorType]||0)+1}}recordRateLimitBlock(){if(!this.config?.enabled||this.config.metrics?.rateLimits===!1)return;this.rateLimitBlocks++}collect(){if(!this.config?.enabled)return null;let elapsed=(Date.now()-this.lastCollectTime)/1000/60,perMinute=elapsed>0?Math.round(this.requestCount/elapsed):0,blockedPerMinute=elapsed>0?Math.round(this.rateLimitBlocks/elapsed):0,sortedTimes=[...this.responseTimes].sort((a,b)=>a-b),len=sortedTimes.length;return{requests:{total:this.requestCount,perMinute,byEndpoint:{...this.byEndpoint},byMethod:{...this.byMethod},byStatus:{...this.byStatus}},responseTime:{avg:len>0?Math.round(sortedTimes.reduce((a,b)=>a+b,0)/len*100)/100:0,min:len>0?sortedTimes[0]??0:0,max:len>0?sortedTimes[len-1]??0:0,p50:len>0?sortedTimes[Math.floor(len*0.5)]??0:0,p95:len>0?sortedTimes[Math.floor(len*0.95)]??0:0,p99:len>0?sortedTimes[Math.floor(len*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}}}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 elapsed=(Date.now()-this.lastCollectTime)/1000/60;return elapsed>0?Math.round(this.requestCount/elapsed):0}getErrorRate(){return this.requestCount>0?this.errorCount/this.requestCount*100:0}getRateLimitBlocksPerMinute(){let elapsed=(Date.now()-this.lastCollectTime)/1000/60;return elapsed>0?Math.round(this.rateLimitBlocks/elapsed):0}getAvgResponseTime(){if(this.responseTimes.length===0)return 0;return this.responseTimes.reduce((a,b)=>a+b,0)/this.responseTimes.length}}import*as fs3 from"fs";import*as os from"os";class SystemCollector{config;lastCpuInfo=null;constructor(config){this.config=config}async collect(){if(!this.config?.enabled)return null;let metrics={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)metrics.cpu=this.collectCpu();if(this.config.metrics?.memory!==!1)metrics.memory=this.collectMemory();if(this.config.metrics?.disk!==!1)metrics.disk=await this.collectDisk();if(this.config.metrics?.network)metrics.network=this.collectNetwork();if(this.config.metrics?.process!==!1)metrics.process=await this.collectProcess();return metrics}collectCpu(){let cpus2=os.cpus(),cores=cpus2.length,idle=0,total=0;for(let cpu of cpus2)idle+=cpu.times.idle,total+=cpu.times.user+cpu.times.nice+cpu.times.sys+cpu.times.idle+cpu.times.irq;let usage=0;if(this.lastCpuInfo){let idleDiff=idle-this.lastCpuInfo.idle,totalDiff=total-this.lastCpuInfo.total;usage=totalDiff>0?Math.round((1-idleDiff/totalDiff)*100*100)/100:0}return this.lastCpuInfo={idle,total},{usage,cores}}collectMemory(){let total=os.totalmem(),free=os.freemem(),used=total-free,usagePercent=Math.round(used/total*100*100)/100,memUsage=process.memoryUsage();return{total,used,free,usagePercent,heapUsed:memUsage.heapUsed,heapTotal:memUsage.heapTotal}}async collectDisk(){try{let stats=fs3.statfsSync("/"),total=stats.blocks*stats.bsize,free=stats.bfree*stats.bsize,used=total-free,usagePercent=Math.round(used/total*100*100)/100;return{total,used,free,usagePercent}}catch{return{total:0,used:0,free:0,usagePercent:0}}}collectNetwork(){let interfaces=os.networkInterfaces(),bytesIn=0,bytesOut=0;for(let name in interfaces){let iface=interfaces[name];if(iface){for(let info of iface)if(!info.internal)bytesIn+=0,bytesOut+=0}}return{bytesIn,bytesOut}}async collectProcess(){let uptime=process.uptime(),pid=process.pid,lagStart=Date.now(),eventLoopLag=await new Promise((resolve)=>{setImmediate(()=>{resolve(Date.now()-lagStart)})});return{uptime,pid,eventLoopLag}}}var init_SystemCollector=()=>{};import{randomUUID as randomUUID3}from"crypto";import*as os2 from"os";class LiveMonitoringService{store;memoryInterval=null;cpuInterval=null;lastCpuInfo=null;isRunning=!1;constructor(config){let merged={...DEFAULT_LIVE_CONFIG,...config};this.store={requests:[],configs:{logMemory:merged.logMemory,logCpu:merged.logCpu,logDapr:merged.logDapr,logWebSocket:merged.logWebSocket,cpuLogInterval:merged.cpuLogInterval,memoryLogInterval:merged.memoryLogInterval},logs:{memory:[],cpu:[],dapr:[],ws:[]},logLimits:{memory:merged.memoryLogLimit,cpu:merged.cpuLogLimit,dapr:merged.daprLogLimit,ws:merged.wsLogLimit,request:merged.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 collect=()=>{if(!this.store.configs.logMemory)return;let mem=process.memoryUsage(),entry={timestamp:Date.now(),rss:mem.rss,heapUsed:mem.heapUsed,heapTotal:mem.heapTotal};if(this.store.logs.memory.push(entry),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=entry,this.store.worker.updatedAt=Date.now()};collect(),this.memoryInterval=setInterval(collect,this.store.configs.memoryLogInterval)}startCpuCollector(){if(this.cpuInterval)clearInterval(this.cpuInterval);let collect=()=>{if(!this.store.configs.logCpu)return;let cpus3=os2.cpus(),userTime=0,sysTime=0,idle=0,total=0;for(let cpu of cpus3)userTime+=cpu.times.user,sysTime+=cpu.times.sys,idle+=cpu.times.idle,total+=cpu.times.user+cpu.times.nice+cpu.times.sys+cpu.times.idle+cpu.times.irq;let userPercent=0,sysPercent=0;if(this.lastCpuInfo){let totalDiff=total-this.lastCpuInfo.total,idleDiff=idle-this.lastCpuInfo.idle;if(totalDiff>0){let activeDiff=totalDiff-idleDiff;userPercent=Math.round((userTime-0)/(activeDiff||1)*100*100)/100,sysPercent=Math.round((sysTime-0)/(activeDiff||1)*100*100)/100;let totalActive=Math.round((1-idleDiff/totalDiff)*100*100)/100;userPercent=Math.round(totalActive*0.7*100)/100,sysPercent=Math.round(totalActive*0.3*100)/100}}this.lastCpuInfo={idle,total};let entry={timestamp:Date.now(),user:userPercent,system:sysPercent};if(this.store.logs.cpu.push(entry),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=entry,this.store.worker.updatedAt=Date.now()};collect(),this.cpuInterval=setInterval(collect,this.store.configs.cpuLogInterval)}recordRequest(request){if(this.store.requests.push(request),this.store.requests.length>this.store.logLimits.request*2)this.store.requests=this.store.requests.slice(-this.store.logLimits.request)}recordDaprEvent(type,details){if(!this.store.configs.logDapr)return;let event={id:randomUUID3(),type,timestamp:Date.now(),...details};if(this.store.logs.dapr.push(event),this.store.daprEvents.push(event),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(type,details){if(!this.store.configs.logWebSocket)return;let event={id:randomUUID3(),type,timestamp:Date.now(),...details};if(this.store.logs.ws.push(event),this.store.wsEvents.push(event),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(timestamps){let memoryUpdates=this.store.logs.memory.filter((m)=>m.timestamp>timestamps.memory),cpuUpdates=this.store.logs.cpu.filter((c)=>c.timestamp>timestamps.cpu),requestUpdates=this.store.requests.filter((r)=>r.timestamp>timestamps.request),daprUpdates=this.store.logs.dapr.filter((d)=>d.timestamp>timestamps.dapr),wsUpdates=this.store.logs.ws.filter((w)=>w.timestamp>timestamps.ws);if(!(memoryUpdates.length>0||cpuUpdates.length>0||requestUpdates.length>0||daprUpdates.length>0||wsUpdates.length>0))return null;return{memory:memoryUpdates,cpu:cpuUpdates,requests:requestUpdates,dapr:daprUpdates,ws:wsUpdates,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(payload){if(payload.logMemory!==void 0)this.store.configs.logMemory=payload.logMemory;if(payload.logCpu!==void 0)this.store.configs.logCpu=payload.logCpu;if(payload.logDapr!==void 0)this.store.configs.logDapr=payload.logDapr;if(payload.logWebSocket!==void 0)this.store.configs.logWebSocket=payload.logWebSocket;if(payload.cpuLogInterval!==void 0){if(this.store.configs.cpuLogInterval=payload.cpuLogInterval,this.isRunning&&this.store.configs.logCpu)this.startCpuCollector()}if(payload.memoryLogInterval!==void 0){if(this.store.configs.memoryLogInterval=payload.memoryLogInterval,this.isRunning&&this.store.configs.logMemory)this.startMemoryCollector()}if(payload.memoryLogLimit!==void 0)this.store.logLimits.memory=payload.memoryLogLimit;if(payload.cpuLogLimit!==void 0)this.store.logLimits.cpu=payload.cpuLogLimit;if(payload.daprLogLimit!==void 0)this.store.logLimits.dapr=payload.daprLogLimit;if(payload.wsLogLimit!==void 0)this.store.logLimits.ws=payload.wsLogLimit;if(payload.requestLogLimit!==void 0)this.store.logLimits.request=payload.requestLogLimit;return{message:"Settings updated successfully",configs:{...this.store.configs},logLimits:{...this.store.logLimits}}}getStore(){return this.store}isEnabled(){return this.isRunning}}var DEFAULT_LIVE_CONFIG;var init_LiveMonitoringService=__esm(()=>{DEFAULT_LIVE_CONFIG={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 MonitoringService{redis;logger;config;appId;flushToDb;systemCollector;applicationCollector;alertService;collectInterval=null;flushInterval=null;pendingMetrics=[];isRunning=!1;constructor(deps){this.redis=deps.redis,this.logger=deps.logger,this.config=this.mergeConfig(deps.config),this.appId=deps.appId,this.flushToDb=deps.flushToDb,this.systemCollector=new SystemCollector(this.config.system),this.applicationCollector=new ApplicationCollector(this.config.application),this.alertService=new AlertService({logger:deps.logger,emailService:deps.emailService,config:this.config,appId:deps.appId})}mergeConfig(config){return{enabled:config.enabled??DEFAULT_CONFIG3.enabled,system:{enabled:config.system?.enabled??DEFAULT_CONFIG3.system.enabled,collectInterval:config.system?.collectInterval??DEFAULT_CONFIG3.system.collectInterval,metrics:{cpu:config.system?.metrics?.cpu??DEFAULT_CONFIG3.system.metrics.cpu,memory:config.system?.metrics?.memory??DEFAULT_CONFIG3.system.metrics.memory,disk:config.system?.metrics?.disk??DEFAULT_CONFIG3.system.metrics.disk,network:config.system?.metrics?.network??DEFAULT_CONFIG3.system.metrics.network,process:config.system?.metrics?.process??DEFAULT_CONFIG3.system.metrics.process}},application:{enabled:config.application?.enabled??DEFAULT_CONFIG3.application.enabled,metrics:{requests:config.application?.metrics?.requests??DEFAULT_CONFIG3.application.metrics.requests,responseTime:config.application?.metrics?.responseTime??DEFAULT_CONFIG3.application.metrics.responseTime,errors:config.application?.metrics?.errors??DEFAULT_CONFIG3.application.metrics.errors,rateLimits:config.application?.metrics?.rateLimits??DEFAULT_CONFIG3.application.metrics.rateLimits}},database:{enabled:config.database?.enabled??DEFAULT_CONFIG3.database.enabled,metrics:{connections:config.database?.metrics?.connections??DEFAULT_CONFIG3.database.metrics.connections,queryTime:config.database?.metrics?.queryTime??DEFAULT_CONFIG3.database.metrics.queryTime,slowQueryThreshold:config.database?.metrics?.slowQueryThreshold??DEFAULT_CONFIG3.database.metrics.slowQueryThreshold}},redis:{enabled:config.redis?.enabled??DEFAULT_CONFIG3.redis.enabled},persistence:{enabled:config.persistence?.enabled??DEFAULT_CONFIG3.persistence.enabled,flushInterval:config.persistence?.flushInterval??DEFAULT_CONFIG3.persistence.flushInterval,retentionDays:config.persistence?.retentionDays??DEFAULT_CONFIG3.persistence.retentionDays},alerts:{enabled:config.alerts?.enabled??DEFAULT_CONFIG3.alerts.enabled,email:{enabled:config.alerts?.email?.enabled??DEFAULT_CONFIG3.alerts.email.enabled,recipients:config.alerts?.email?.recipients??DEFAULT_CONFIG3.alerts.email.recipients},thresholds:{cpuPercent:config.alerts?.thresholds?.cpuPercent??DEFAULT_CONFIG3.alerts.thresholds.cpuPercent,memoryPercent:config.alerts?.thresholds?.memoryPercent??DEFAULT_CONFIG3.alerts.thresholds.memoryPercent,diskPercent:config.alerts?.thresholds?.diskPercent??DEFAULT_CONFIG3.alerts.thresholds.diskPercent,errorRatePercent:config.alerts?.thresholds?.errorRatePercent??DEFAULT_CONFIG3.alerts.thresholds.errorRatePercent,responseTimeMs:config.alerts?.thresholds?.responseTimeMs??DEFAULT_CONFIG3.alerts.thresholds.responseTimeMs,rateLimitBlocksPerMinute:config.alerts?.thresholds?.rateLimitBlocksPerMinute??DEFAULT_CONFIG3.alerts.thresholds.rateLimitBlocksPerMinute},cooldown:config.alerts?.cooldown??DEFAULT_CONFIG3.alerts.cooldown}}}parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h|d)$/);if(!match||!match[1]||!match[2])return 1e4;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*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 collectIntervalMs=this.parseTimeToMs(this.config.system.collectInterval);if(this.collectInterval=setInterval(()=>{this.collect()},collectIntervalMs),this.config.persistence.enabled&&this.flushToDb){let flushIntervalMs=this.parseTimeToMs(this.config.persistence.flushInterval);this.flushInterval=setInterval(()=>{this.flush()},flushIntervalMs)}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 now=Date.now(),snapshot={timestamp:now};if(this.config.system.enabled){let systemMetrics=await this.systemCollector.collect();if(systemMetrics)snapshot.system=systemMetrics,this.addMetricPoints("system",systemMetrics,now)}if(this.config.application.enabled){let appMetrics=this.applicationCollector.collect();if(appMetrics)snapshot.application=appMetrics,this.addMetricPoints("application",appMetrics,now)}if(await this.storeSnapshot(snapshot),this.config.alerts.enabled)await this.alertService.checkAndAlert(snapshot)}addMetricPoints(type,metrics,timestamp){let flatten=(obj,prefix="")=>{for(let key in obj){let value=obj[key],newKey=prefix?`${prefix}.${key}`:key;if(typeof value==="number")this.pendingMetrics.push({timestamp,metricType:type,metricName:newKey,value});else if(typeof value==="object"&&value!==null&&!Array.isArray(value))flatten(value,newKey)}};flatten(metrics)}async storeSnapshot(snapshot){let key=`monitoring:${this.appId}:latest`;await this.redis.create(key,snapshot,3600);let historyKey=`monitoring:${this.appId}:history`,historyResult=await this.redis.read(historyKey),history=historyResult.success&&historyResult.data?historyResult.data:[];history.push(snapshot);let oneHourAgo=Date.now()-3600000,filteredHistory=history.filter((s)=>s.timestamp>oneHourAgo);await this.redis.create(historyKey,filteredHistory,3600)}async flush(){if(this.pendingMetrics.length===0)return;if(!this.flushToDb)return;let metricsToFlush=[...this.pendingMetrics];this.pendingMetrics=[];try{await this.flushToDb(metricsToFlush),this.logger.debug(`[Monitoring] Flushed ${metricsToFlush.length} metrics to database`)}catch(error){this.logger.error(`[Monitoring] Failed to flush metrics: ${error}`),this.pendingMetrics=[...metricsToFlush,...this.pendingMetrics]}}recordRequest(params){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRequest(params)}recordRateLimitBlock(){if(!this.config.enabled||!this.config.application.enabled)return;this.applicationCollector.recordRateLimitBlock()}async getLatestSnapshot(){let key=`monitoring:${this.appId}:latest`,result=await this.redis.read(key);return result.success?result.data:null}async getHistory(minutes=60){let key=`monitoring:${this.appId}:history`,result=await this.redis.read(key);if(!result.success||!result.data)return[];let cutoff=Date.now()-minutes*60000;return result.data.filter((s)=>s.timestamp>cutoff)}getActiveAlerts(){return this.alertService.getActiveAlerts()}acknowledgeAlert(alertId){return this.alertService.acknowledgeAlert(alertId)}isEnabled(){return this.config.enabled}getConfig(){return this.config}}var DEFAULT_CONFIG3;var init_Monitoring=__esm(()=>{init_SystemCollector();init_LiveMonitoringService();DEFAULT_CONFIG3={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 init_types4=()=>{};import{and as and3,desc,eq as eq7}from"drizzle-orm";function toCamel(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());result[camelKey]=value}return result}function fromCamel(obj){let result={};for(let[key,value]of Object.entries(obj)){let snakeKey=key.replace(/[A-Z]/g,(c)=>`_${c.toLowerCase()}`);result[snakeKey]=value}return result}class NotificationService{db;schemaTables;config;logger;emailService;constructor(serviceConfig){this.db=serviceConfig.db,this.schemaTables=serviceConfig.schemaTables,this.config=serviceConfig.config,this.logger=serviceConfig.logger,this.emailService=serviceConfig.emailService}getTable(name){return this.schemaTables[name]}getCol(table,col2){return table[col2]}isChannelEnabled(channel){let channels=this.config.channels;if(!channels)return channel==="portal";switch(channel){case"portal":return channels.portal!==!1;case"email":return channels.email===!0;case"sms":return channels.sms?.enabled===!0;case"telegram":return channels.telegram?.enabled===!0;case"webhook":return channels.webhook?.enabled===!0;default:return!1}}interpolateTemplate(template,context){let result=template;for(let[key,value]of Object.entries(context))result=result.replace(new RegExp(`{{${key}}}`,"g"),String(value??""));for(let[key,value]of Object.entries(this.config.templateVariables||{}))result=result.replace(new RegExp(`{{${key}}}`,"g"),value);return result}async triggerNotifications(params){let{trigger,flow_id,entity_name,entity_id,node_id,context={}}=params,rulesTable=this.getTable("verificationNotificationRules"),recipientsTable=this.getTable("verificationNotificationRecipients"),channelsTable=this.getTable("verificationNotificationChannels");if(!rulesTable||!recipientsTable){this.logger.warn("[Notification] Notification tables not found");return}let now=new Date,rules=await this.db.select().from(rulesTable).where(and3(eq7(this.getCol(rulesTable,"flowId"),flow_id),eq7(this.getCol(rulesTable,"trigger"),trigger)));this.logger.info(`[Notification] Found ${rules.length} rules for trigger=${trigger} flow_id=${flow_id}, filter_node_id=${node_id||"NONE"}`);for(let r of rules)this.logger.info(`[Notification] Rule ${r.id}: nodeId=${r.nodeId}, trigger=${r.trigger}, title=${JSON.stringify(r.titleTemplate)}`);let filteredRules=rules.filter((rule)=>{if(node_id&&rule.nodeId!==node_id)return this.logger.info(`[Notification] EXCLUDED rule ${rule.id}: rule.nodeId=${rule.nodeId} !== filter_node_id=${node_id}`),!1;if(rule.startsAt&&new Date(rule.startsAt)>now)return!1;if(rule.expiresAt&&new Date(rule.expiresAt)<now)return!1;return!0});for(let rule of filteredRules){let recipients=await this.db.select().from(recipientsTable).where(eq7(this.getCol(recipientsTable,"ruleId"),rule.id)),ruleChannels=["portal"];if(channelsTable){let channelEntries=await this.db.select().from(channelsTable).where(eq7(this.getCol(channelsTable,"ruleId"),rule.id));if(channelEntries.length>0)ruleChannels=channelEntries.map((c)=>c.channel)}let enabledChannels=ruleChannels.filter((ch)=>this.isChannelEnabled(ch));if(enabledChannels.length===0)continue;this.logger.info(`[Notification] Rule ${rule.id}: ${recipients.length} recipients, ${enabledChannels.length} channels (${enabledChannels.join(",")})`);let userIds=await this.resolveRecipients(recipients,params.verifier_id,flow_id,entity_name,entity_id);this.logger.info(`[Notification] Rule ${rule.id}: resolved ${userIds.length} user IDs: ${userIds.join(", ")}`);let enrichedContext={...context,entity_name,entity_id,trigger,decision:params.decision};this.logger.info(`[Notification] Rule ${rule.id}: titleTemplate=${JSON.stringify(rule.titleTemplate)}, bodyTemplate=${JSON.stringify(rule.bodyTemplate)}, context=${JSON.stringify(enrichedContext)}`);let title=rule.titleTemplate?this.interpolateTemplate(rule.titleTemplate,enrichedContext):`Verification ${trigger.replace("on_","").replace("_"," ")}`,body=rule.bodyTemplate?this.interpolateTemplate(rule.bodyTemplate,enrichedContext):void 0;this.logger.info(`[Notification] Rule ${rule.id}: final title="${title}", body="${body}"`);for(let userId of userIds)await this.send({user_id:userId,title,body,entity_name,entity_id,type:"verification",source:`flow:${flow_id}`,channels:enabledChannels})}this.logger.debug(`[Notification] Triggered ${filteredRules.length} rules for ${trigger} on ${entity_name}:${entity_id}`)}async resolveRecipients(recipients,currentVerifierId,flowId,entityName,entityId){let userIds=new Set,userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");for(let recipient of recipients)switch(recipient.recipientType){case"user":if(recipient.recipientUserId)userIds.add(recipient.recipientUserId);break;case"role":if(recipient.recipientRole&&userRolesTable&&rolesTable){let rolesCols=rolesTable,userRolesCols=userRolesTable,role=(await this.db.select().from(rolesTable).where(eq7(rolesCols.name,recipient.recipientRole)).limit(1))[0];if(role){let usersInRole=await this.db.select({user_id:userRolesCols.userId}).from(userRolesTable).where(eq7(userRolesCols.roleId,role.id));for(let ur of usersInRole)userIds.add(ur.user_id)}}break;case"step_verifier":if(currentVerifierId)userIds.add(currentVerifierId);break;case"entity_creator":{if(entityName&&entityId){let instancesTable=this.getTable("verificationInstances");if(instancesTable){let inst=(await this.db.select().from(instancesTable).where(and3(eq7(this.getCol(instancesTable,"entityName"),entityName),eq7(this.getCol(instancesTable,"entityId"),entityId))).orderBy(desc(this.getCol(instancesTable,"createdAt"))).limit(1))[0];if(inst?.startedBy)userIds.add(inst.startedBy)}}break}case"all_verifiers":{if(flowId){let verifierConfigsTable=this.getTable("verificationVerifierConfigs");if(verifierConfigsTable){let configs=await this.db.select().from(verifierConfigsTable).where(eq7(this.getCol(verifierConfigsTable,"flowId"),flowId));this.logger.info(`[Notification] all_verifiers: found ${configs.length} verifier configs for flow ${flowId}`);for(let cfg of configs){let row=cfg;if(this.logger.info(`[Notification] all_verifiers: config node_id=${row.nodeId}, type=${row.verifierType}, userId=${row.verifierUserId}, role=${row.verifierRole}`),row.verifierUserId)userIds.add(row.verifierUserId);if(row.verifierType==="role"&&row.verifierRole&&userRolesTable&&rolesTable){let rCols=rolesTable,urCols=userRolesTable,roleRow=(await this.db.select().from(rolesTable).where(eq7(rCols.name,row.verifierRole)).limit(1))[0];if(roleRow){let usersInRole=await this.db.select({user_id:urCols.userId}).from(userRolesTable).where(eq7(urCols.roleId,roleRow.id));for(let ur of usersInRole)userIds.add(ur.user_id)}}}}}break}}return Array.from(userIds)}async send(params){let{user_id,title,body,entity_name,entity_id,type,source,channels}=params;for(let channel of channels)switch(channel){case"portal":await this.sendPortalNotification(user_id,title,body,entity_name,entity_id,type,source);break;case"email":await this.sendEmailNotification(user_id,title,body);break;case"sms":this.logger.debug(`[Notification] SMS channel not yet implemented for user ${user_id}`);break;case"telegram":this.logger.debug(`[Notification] Telegram channel not yet implemented for user ${user_id}`);break;case"webhook":this.logger.debug(`[Notification] Webhook channel not yet implemented for user ${user_id}`);break}}async sendPortalNotification(userId,title,body,entityName,entityId,type,source){let notificationsTable=this.getTable("notifications");if(!notificationsTable){this.logger.warn("[Notification] notifications table not found");return}await this.db.insert(notificationsTable).values(toCamel({user_id:userId,title,body:body||null,entity_name:entityName||null,entity_id:entityId||null,type:type||"system",source:source||null,is_seen:!1})),this.logger.debug(`[Notification] Portal notification sent to ${userId}: ${title}`)}async sendEmailNotification(userId,title,body){if(!this.emailService?.isAvailable()){this.logger.warn("[Notification] Email service not available for email notification");return}let usersTable=this.getTable("users");if(!usersTable){this.logger.warn("[Notification] users table not found");return}let user=(await this.db.select({email:this.getCol(usersTable,"email")}).from(usersTable).where(eq7(this.getCol(usersTable,"id"),userId)).limit(1))[0];if(!user?.email){this.logger.warn(`[Notification] No email found for user ${userId}`);return}await this.emailService.sendEmail({to:user.email,subject:title,html:body||title}),this.logger.debug(`[Notification] Email notification sent to ${user.email}: ${title}`)}async getNotifications(userId,options){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return[];let conditions=[eq7(this.getCol(notificationsTable,"userId"),userId)];if(options?.type)conditions.push(eq7(this.getCol(notificationsTable,"type"),options.type));return(await this.db.select().from(notificationsTable).where(and3(...conditions)).orderBy(desc(this.getCol(notificationsTable,"createdAt"))).limit(options?.limit||50).offset(options?.offset||0)).map((r)=>fromCamel(r))}async getUnseenCount(userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return 0;return(await this.db.select().from(notificationsTable).where(and3(eq7(this.getCol(notificationsTable,"userId"),userId),eq7(this.getCol(notificationsTable,"isSeen"),!1)))).length}async markAsSeen(notificationId,userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return!1;return await this.db.update(notificationsTable).set(toCamel({is_seen:!0,seen_at:new Date})).where(and3(eq7(this.getCol(notificationsTable,"id"),notificationId),eq7(this.getCol(notificationsTable,"userId"),userId))),!0}async markAllAsSeen(userId){let notificationsTable=this.getTable("notifications");if(!notificationsTable)return 0;return(await this.db.update(notificationsTable).set(toCamel({is_seen:!0,seen_at:new Date})).where(and3(eq7(this.getCol(notificationsTable,"userId"),userId),eq7(this.getCol(notificationsTable,"isSeen"),!1))).returning()).length}}var init_Notification=__esm(()=>{init_types4()});function buildGenericAuthUrl(config,state){if(!config.authorizationUrl)throw Error("Generic OAuth provider requires authorizationUrl");let scopes2=config.scopes??[],params=new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",state,...scopes2.length>0?{scope:scopes2.join(" ")}:{},...config.extraAuthParams});return`${config.authorizationUrl}?${params.toString()}`}async function exchangeGenericCode(code,config){if(!config.tokenUrl)throw Error("Generic OAuth provider requires tokenUrl");let tokenRes=await fetch(config.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Generic OAuth token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope};if(!config.userInfoUrl)return{profile:{providerAccountId:tokenData.access_token,rawProfile:tokenData},tokens};let userRes=await fetch(config.userInfoUrl,{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch user info from generic OAuth provider");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.id??rawProfile.sub??rawProfile.user_id??tokenData.access_token,email:rawProfile.email,name:rawProfile.name??rawProfile.display_name??rawProfile.username,avatarUrl:rawProfile.avatar_url??rawProfile.picture??rawProfile.photo,rawProfile},tokens}}function buildGithubAuthUrl(config,state){let scopes2=config.scopes??["read:user","user:email"];return`https://github.com/login/oauth/authorize?${new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,scope:scopes2.join(" "),state,...config.extraAuthParams}).toString()}`}async function exchangeGithubCode(code,config){let tokenRes=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,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`GitHub token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`GitHub OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://api.github.com/user",{headers:{Authorization:`Bearer ${tokenData.access_token}`,Accept:"application/vnd.github+json"}});if(!userRes.ok)throw Error("Failed to fetch GitHub user info");let rawProfile=await userRes.json(),email=rawProfile.email;if(!email)try{let emailsRes=await fetch("https://api.github.com/user/emails",{headers:{Authorization:`Bearer ${tokenData.access_token}`,Accept:"application/vnd.github+json"}});if(emailsRes.ok){let emails=await emailsRes.json();email=emails.find((e)=>e.primary&&e.verified)?.email??emails[0]?.email}}catch{}return{profile:{providerAccountId:String(rawProfile.id),email,name:rawProfile.name??rawProfile.login,avatarUrl:rawProfile.avatar_url,rawProfile},tokens}}function buildGoogleAuthUrl(config,state){let scopes2=config.scopes??["openid","email","profile"];return`https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",scope:scopes2.join(" "),state,access_type:"offline",prompt:"select_account",...config.extraAuthParams}).toString()}`}async function exchangeGoogleCode(code,config){let tokenRes=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Google token exchange failed: ${err}`)}let tokenData=await tokenRes.json(),tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://www.googleapis.com/oauth2/v3/userinfo",{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch Google user info");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.sub,email:rawProfile.email,name:rawProfile.name,avatarUrl:rawProfile.picture,rawProfile},tokens}}function getMicrosoftBaseUrl(config){return`https://login.microsoftonline.com/${config.tenantId??"common"}/oauth2/v2.0`}function buildMicrosoftAuthUrl(config,state){let scopes2=config.scopes??["openid","email","profile","User.Read"],params=new URLSearchParams({client_id:config.clientId,redirect_uri:config.redirectUri,response_type:"code",scope:scopes2.join(" "),state,response_mode:"query",prompt:"select_account",...config.extraAuthParams});return`${getMicrosoftBaseUrl(config)}/authorize?${params.toString()}`}async function exchangeMicrosoftCode(code,config){let tokenRes=await fetch(`${getMicrosoftBaseUrl(config)}/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code,client_id:config.clientId,client_secret:config.clientSecret,redirect_uri:config.redirectUri,grant_type:"authorization_code"}).toString()});if(!tokenRes.ok){let err=await tokenRes.text();throw Error(`Microsoft token exchange failed: ${err}`)}let tokenData=await tokenRes.json();if(tokenData.error)throw Error(`Microsoft OAuth error: ${tokenData.error_description||tokenData.error}`);let tokens={accessToken:tokenData.access_token,refreshToken:tokenData.refresh_token,expiresAt:tokenData.expires_in?new Date(Date.now()+tokenData.expires_in*1000):void 0,scope:tokenData.scope},userRes=await fetch("https://graph.microsoft.com/v1.0/me",{headers:{Authorization:`Bearer ${tokenData.access_token}`}});if(!userRes.ok)throw Error("Failed to fetch Microsoft user info");let rawProfile=await userRes.json();return{profile:{providerAccountId:rawProfile.id,email:rawProfile.mail??rawProfile.userPrincipalName,name:rawProfile.displayName,avatarUrl:void 0,rawProfile},tokens}}import{randomBytes as randomBytes2}from"crypto";class OAuthService{config;stateStore=new Map;cleanupInterval=null;constructor(config){this.config=config;let ttl=(config.stateTtlSeconds??600)*1000;this.cleanupInterval=setInterval(()=>{let now=Date.now();for(let[key,val]of this.stateStore.entries())if(val.expiresAt<now)this.stateStore.delete(key)},ttl)}stop(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isProviderEnabled(provider){return!!(this.config.enabled&&this.config.providers[provider])}getEnabledProviders(){if(!this.config.enabled)return[];return Object.keys(this.config.providers)}buildAuthorizationUrl(provider,linkUserId,redirectUrl){let providerConfig=this.config.providers[provider];if(!providerConfig)throw Error(`OAuth provider "${provider}" is not configured`);let statePayload={provider,linkUserId,redirectUrl,createdAt:Date.now()},state=randomBytes2(32).toString("hex"),ttl=(this.config.stateTtlSeconds??600)*1000;switch(this.stateStore.set(state,{payload:statePayload,expiresAt:Date.now()+ttl}),provider){case"google":return buildGoogleAuthUrl(providerConfig,state);case"github":return buildGithubAuthUrl(providerConfig,state);case"microsoft":return buildMicrosoftAuthUrl(providerConfig,state);default:return buildGenericAuthUrl(providerConfig,state)}}consumeState(state){let entry=this.stateStore.get(state);if(!entry)return null;if(entry.expiresAt<Date.now())return this.stateStore.delete(state),null;return this.stateStore.delete(state),entry.payload}async exchangeCode(provider,code){let providerConfig=this.config.providers[provider];if(!providerConfig)throw Error(`OAuth provider "${provider}" is not configured`);switch(provider){case"google":return exchangeGoogleCode(code,providerConfig);case"github":return exchangeGithubCode(code,providerConfig);case"microsoft":return exchangeMicrosoftCode(code,providerConfig);default:return exchangeGenericCode(code,providerConfig)}}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 init_OAuthService=()=>{};var init_OAuth=__esm(()=>{init_OAuthService()});class RateLimiter{redis;logger;config;constructor(deps){this.redis=deps.redis,this.logger=deps.logger,this.config=this.mergeConfig(deps.config)}mergeConfig(config){return{enabled:config.enabled??DEFAULT_CONFIG4.enabled,strategy:config.strategy??DEFAULT_CONFIG4.strategy,keyPrefix:config.keyPrefix??DEFAULT_CONFIG4.keyPrefix,authRoutes:{window:config.authRoutes?.window??DEFAULT_CONFIG4.authRoutes.window,max:config.authRoutes?.max??DEFAULT_CONFIG4.authRoutes.max,login:{window:config.authRoutes?.login?.window??DEFAULT_AUTH_LOGIN.window,max:config.authRoutes?.login?.max??DEFAULT_AUTH_LOGIN.max,blockDuration:config.authRoutes?.login?.blockDuration??DEFAULT_AUTH_LOGIN.blockDuration},register:{window:config.authRoutes?.register?.window??DEFAULT_AUTH_REGISTER.window,max:config.authRoutes?.register?.max??DEFAULT_AUTH_REGISTER.max,blockDuration:config.authRoutes?.register?.blockDuration??DEFAULT_AUTH_REGISTER.blockDuration},passwordReset:{window:config.authRoutes?.passwordReset?.window??DEFAULT_AUTH_PASSWORD_RESET.window,max:config.authRoutes?.passwordReset?.max??DEFAULT_AUTH_PASSWORD_RESET.max,blockDuration:config.authRoutes?.passwordReset?.blockDuration??DEFAULT_AUTH_PASSWORD_RESET.blockDuration},magicLink:{window:config.authRoutes?.magicLink?.window??DEFAULT_AUTH_MAGIC_LINK.window,max:config.authRoutes?.magicLink?.max??DEFAULT_AUTH_MAGIC_LINK.max,blockDuration:config.authRoutes?.magicLink?.blockDuration??DEFAULT_AUTH_MAGIC_LINK.blockDuration}},publicRoutes:{window:config.publicRoutes?.window??DEFAULT_CONFIG4.publicRoutes.window,max:config.publicRoutes?.max??DEFAULT_CONFIG4.publicRoutes.max},privateRoutes:{window:config.privateRoutes?.window??DEFAULT_CONFIG4.privateRoutes.window,max:config.privateRoutes?.max??DEFAULT_CONFIG4.privateRoutes.max},byIp:config.byIp??DEFAULT_CONFIG4.byIp,byUserId:config.byUserId??DEFAULT_CONFIG4.byUserId,byEndpoint:config.byEndpoint??DEFAULT_CONFIG4.byEndpoint,skipSuccessfulRequests:config.skipSuccessfulRequests??DEFAULT_CONFIG4.skipSuccessfulRequests,headers:{remaining:config.headers?.remaining??DEFAULT_CONFIG4.headers.remaining,reset:config.headers?.reset??DEFAULT_CONFIG4.headers.reset,limit:config.headers?.limit??DEFAULT_CONFIG4.headers.limit},whitelist:config.whitelist??DEFAULT_CONFIG4.whitelist,blacklist:config.blacklist??DEFAULT_CONFIG4.blacklist}}parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h|d)$/);if(!match||!match[1]||!match[2])return 60000;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*24*60*60*1000;default:return 60000}}buildKey(params){let parts=[this.config.keyPrefix,params.category];if(params.authType&¶ms.authType!=="other")parts.push(params.authType);if(this.config.byIp&¶ms.ip)parts.push(`ip:${params.ip}`);if(this.config.byUserId&¶ms.userId)parts.push(`user:${params.userId}`);if(this.config.byEndpoint&¶ms.endpoint)parts.push(`ep:${params.endpoint.replace(/\//g,"_")}`);return parts.join(":")}getLimits(category,authType){if(category==="auth"){if(authType&&authType!=="other"){let authConfig=this.config.authRoutes[authType];if(authConfig)return authConfig}return{window:this.config.authRoutes.window,max:this.config.authRoutes.max}}if(category==="public")return this.config.publicRoutes;return this.config.privateRoutes}isWhitelisted(ip){return this.config.whitelist.some((pattern)=>{if(pattern.includes("*"))return new RegExp(`^${pattern.replace(/\*/g,".*")}$`).test(ip);return pattern===ip})}isBlacklisted(ip){return this.config.blacklist.some((pattern)=>{if(pattern.includes("*"))return new RegExp(`^${pattern.replace(/\*/g,".*")}$`).test(ip);return pattern===ip})}async readRedis(key){let result=await this.redis.read(key);if(result.success)return result.data;return null}async check(params){if(!this.config.enabled)return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isWhitelisted(params.ip))return{allowed:!0,remaining:-1,resetAt:0,limit:-1};if(this.isBlacklisted(params.ip))return this.logger.warn(`[RateLimit] Blacklisted IP: ${params.ip}`),{allowed:!1,remaining:0,resetAt:Date.now()+86400000,limit:0,retryAfter:86400};let key=this.buildKey(params),limits=this.getLimits(params.category,params.authType),windowMs=this.parseTimeToMs(limits.window),blockKey=`${key}:blocked`,isBlocked=await this.readRedis(blockKey);if(isBlocked&&isBlocked.until>Date.now()){let retryAfter=Math.ceil((isBlocked.until-Date.now())/1000);return this.logger.warn(`[RateLimit] Blocked: ${key}, retry after ${retryAfter}s`),{allowed:!1,remaining:0,resetAt:isBlocked.until,limit:limits.max,retryAfter}}if(this.config.strategy==="sliding-window")return this.slidingWindowCheck(key,limits.max,windowMs,limits.blockDuration);if(this.config.strategy==="fixed-window")return this.fixedWindowCheck(key,limits.max,windowMs,limits.blockDuration);return this.tokenBucketCheck(key,limits.max,windowMs)}async slidingWindowCheck(key,max,windowMs,blockDuration){let now=Date.now(),windowStart=now-windowMs,dataKey=`${key}:sw`,timestamps=(await this.readRedis(dataKey))?.timestamps||[];timestamps=timestamps.filter((ts)=>ts>windowStart);let count=timestamps.length,firstTimestamp=timestamps[0],resetAt=firstTimestamp!==void 0?firstTimestamp+windowMs:now+windowMs;if(count>=max){if(blockDuration){let blockMs=this.parseTimeToMs(blockDuration);await this.redis.create(`${key}:blocked`,{until:now+blockMs},Math.ceil(blockMs/1000))}return{allowed:!1,remaining:0,resetAt,limit:max,retryAfter:Math.ceil((resetAt-now)/1000)}}return timestamps.push(now),await this.redis.create(dataKey,{timestamps},Math.ceil(windowMs/1000)+1),{allowed:!0,remaining:max-timestamps.length,resetAt,limit:max}}async fixedWindowCheck(key,max,windowMs,blockDuration){let now=Date.now(),windowId=Math.floor(now/windowMs),dataKey=`${key}:fw:${windowId}`,resetAt=(windowId+1)*windowMs,count=(await this.readRedis(dataKey))?.count||0;if(count>=max){if(blockDuration){let blockMs=this.parseTimeToMs(blockDuration);await this.redis.create(`${key}:blocked`,{until:now+blockMs},Math.ceil(blockMs/1000))}return{allowed:!1,remaining:0,resetAt,limit:max,retryAfter:Math.ceil((resetAt-now)/1000)}}return await this.redis.create(dataKey,{count:count+1},Math.ceil(windowMs/1000)+1),{allowed:!0,remaining:max-(count+1),resetAt,limit:max}}async tokenBucketCheck(key,max,windowMs){let now=Date.now(),refillRate=max/windowMs,dataKey=`${key}:tb`,data=await this.readRedis(dataKey),tokens=data?.tokens??max,lastRefill=data?.lastRefill??now,refill=(now-lastRefill)*refillRate;if(tokens=Math.min(max,tokens+refill),tokens<1){let waitTime=Math.ceil((1-tokens)/refillRate);return{allowed:!1,remaining:0,resetAt:now+waitTime,limit:max,retryAfter:Math.ceil(waitTime/1000)}}return tokens-=1,await this.redis.create(dataKey,{tokens,lastRefill:now},Math.ceil(windowMs/1000)*2),{allowed:!0,remaining:Math.floor(tokens),resetAt:now+windowMs,limit:max}}async decrement(params){if(!this.config.skipSuccessfulRequests)return;let key=this.buildKey(params);if(this.config.strategy==="sliding-window"){let dataKey=`${key}:sw`,data=await this.readRedis(dataKey);if(data?.timestamps?.length){data.timestamps.pop();let windowMs=this.parseTimeToMs(this.getLimits(params.category,params.authType).window);await this.redis.create(dataKey,data,Math.ceil(windowMs/1000)+1)}}else if(this.config.strategy==="fixed-window"){let windowMs=this.parseTimeToMs(this.getLimits(params.category,params.authType).window),windowId=Math.floor(Date.now()/windowMs),dataKey=`${key}:fw:${windowId}`,data=await this.readRedis(dataKey);if(data?.count)await this.redis.create(dataKey,{count:data.count-1},Math.ceil(windowMs/1000)+1)}}getHeaders(result){let headers={};return headers[this.config.headers.remaining]=String(result.remaining),headers[this.config.headers.reset]=String(Math.ceil(result.resetAt/1000)),headers[this.config.headers.limit]=String(result.limit),headers}isEnabled(){return this.config.enabled}}var DEFAULT_AUTH_LOGIN,DEFAULT_AUTH_REGISTER,DEFAULT_AUTH_PASSWORD_RESET,DEFAULT_AUTH_MAGIC_LINK,DEFAULT_CONFIG4;var init_RateLimiter=__esm(()=>{DEFAULT_AUTH_LOGIN={window:"15m",max:5,blockDuration:"30m"},DEFAULT_AUTH_REGISTER={window:"1h",max:3,blockDuration:"1h"},DEFAULT_AUTH_PASSWORD_RESET={window:"1h",max:3,blockDuration:"1h"},DEFAULT_AUTH_MAGIC_LINK={window:"1h",max:5,blockDuration:"1h"},DEFAULT_CONFIG4={enabled:!0,strategy:"sliding-window",keyPrefix:"rl:",authRoutes:{window:"1m",max:10,login:DEFAULT_AUTH_LOGIN,register:DEFAULT_AUTH_REGISTER,passwordReset:DEFAULT_AUTH_PASSWORD_RESET,magicLink:DEFAULT_AUTH_MAGIC_LINK},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 exports_schema={};__export(exports_schema,{ensureSchemaExists:()=>ensureSchemaExists});import{sql as sql2}from"drizzle-orm";var validateIdentifier=(name)=>{if(!name||name.length>63)throw Error(`Invalid identifier: must be 1-63 characters, got ${name.length}`);if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name))throw Error(`Invalid identifier: "${name}" contains unsafe characters`);return name},ensureSchemaExists=async(db,schemaName)=>{let safeName=validateIdentifier(schemaName);await db.execute(sql2.raw(`CREATE SCHEMA IF NOT EXISTS "${safeName}"`))};var init_schema=()=>{};var rowToTenantRecord=(row)=>({id:String(row.id||""),subdomain:String(row.subdomain||""),schemaName:String(row.schemaName||row.schema_name||""),companyId:String(row.companyId||row.company_id||""),companyName:row.companyName!=null?String(row.companyName):row.company_name!=null?String(row.company_name):null,godAdminEmail:String(row.godAdminEmail||row.god_admin_email||""),status:parseStatus(row.status),plan:row.plan!=null?String(row.plan):null,domain:row.domain!=null?String(row.domain):null,settings:parseJsonbToConfig(row.settings),trustedSources:parseTrustedSources(row.trustedSources||row.trusted_sources),maxUsers:row.maxUsers!=null?Number(row.maxUsers):row.max_users!=null?Number(row.max_users):null,provisionedAt:row.provisionedAt!=null?String(row.provisionedAt):row.provisioned_at!=null?String(row.provisioned_at):null,suspendedAt:row.suspendedAt!=null?String(row.suspendedAt):row.suspended_at!=null?String(row.suspended_at):null,suspendedReason:row.suspendedReason!=null?String(row.suspendedReason):row.suspended_reason!=null?String(row.suspended_reason):null}),rowToFeatureRecord=(row,parseConfig)=>({id:String(row.id||""),tenantId:String(row.tenantId||row.tenant_id||""),featureName:String(row.featureName||row.feature_name||""),enabled:Boolean(row.enabled),featureConfig:parseConfig(row.config)}),parseStatus=(value)=>{let valid=["provisioning","active","suspended","archived"],str=String(value||"provisioning");return valid.includes(str)?str:"provisioning"},parseJsonbToConfig=(value)=>{if(!value||typeof value!=="object")return{};let result={};for(let[k,v]of Object.entries(value))if(typeof v==="string"||typeof v==="number"||typeof v==="boolean")result[k]=v;return result},parseTrustedSources=(value)=>{if(!Array.isArray(value))return[];return value.map((item)=>{let entry=item;return{allowHeaderAuth:entry.allowHeaderAuth===!0||entry.allow_header_auth===!0,allowedIps:Array.isArray(entry.allowedIps||entry.allowed_ips)?entry.allowedIps||entry.allowed_ips:void 0,allowedServices:Array.isArray(entry.allowedServices||entry.allowed_services)?entry.allowedServices||entry.allowed_services:void 0}})},extractSubdomain=(host)=>{let hostWithoutPort=host.split(":")[0]||"";if(hostWithoutPort==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(hostWithoutPort))return null;let parts=hostWithoutPort.split(".");if(parts.length<3)return null;let subdomain=parts[0]||"";if(!subdomain||subdomain==="www")return null;return subdomain},isIpInCidr=(ip,cidr)=>{let[cidrIp,prefixStr]=cidr.split("/");if(!cidrIp||!prefixStr)return!1;let prefix=Number.parseInt(prefixStr,10);if(Number.isNaN(prefix))return!1;let ipParts=ip.split(".").map(Number),cidrParts=cidrIp.split(".").map(Number);if(ipParts.length!==4||cidrParts.length!==4)return!1;let ipNum=(ipParts[0]||0)<<24|(ipParts[1]||0)<<16|(ipParts[2]||0)<<8|(ipParts[3]||0),cidrNum=(cidrParts[0]||0)<<24|(cidrParts[1]||0)<<16|(cidrParts[2]||0)<<8|(cidrParts[3]||0),mask=~((1<<32-prefix)-1);return(ipNum&mask)===(cidrNum&mask)},isTrustedSource=(tenant,request,authMode)=>{let trustedSources=tenant.trustedSources;if(!trustedSources||!Array.isArray(trustedSources)||trustedSources.length===0)return authMode==="consumer";let clientIp=request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||request.headers.get("x-real-ip")?.trim()||"",serviceId=request.headers.get("x-service-id")||"";for(let source of trustedSources){if(!source.allowHeaderAuth)continue;if(source.allowedIps&&source.allowedIps.length>0){if(source.allowedIps.some((allowedIp)=>{if(allowedIp.includes("/"))return isIpInCidr(clientIp,allowedIp);return clientIp===allowedIp}))return!0}if(source.allowedServices&&source.allowedServices.length>0){if(source.allowedServices.includes(serviceId))return!0}if((!source.allowedIps||source.allowedIps.length===0)&&(!source.allowedServices||source.allowedServices.length===0))return!0}return!1};function getDatabaseAuthMode(){return process.env.DATABASE_AUTH_MODE||"password"}function getRedisAuthMode(){return process.env.REDIS_AUTH_MODE||"password"}async function acquireToken(scope,label){let{DefaultAzureCredential,ManagedIdentityCredential,ClientSecretCredential}=await import("@azure/identity"),authMode=scope==="https://ossrdbms-aad.database.windows.net/.default"?getDatabaseAuthMode():getRedisAuthMode(),clientId=process.env.AZURE_CLIENT_ID||"",tenantId=process.env.AZURE_TENANT_ID||"",clientSecret=process.env.AZURE_CLIENT_SECRET||"",credential;if(authMode==="managed_identity")credential=clientId?new ManagedIdentityCredential(clientId):new DefaultAzureCredential;else if(authMode==="service_principal"){if(!tenantId||!clientId||!clientSecret)throw Error("[azure-auth] service_principal auth requires AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET");credential=new ClientSecretCredential(tenantId,clientId,clientSecret)}else throw Error(`[azure-auth] Unsupported auth mode: ${authMode}`);let result=await credential.getToken(scope);if(!result)throw Error(`[azure-auth] Failed to acquire token for ${label}`);return console.log(`[azure-auth] ${label} token acquired, expires at ${new Date(result.expiresOnTimestamp).toISOString()}`),{token:result.token,expiresAt:result.expiresOnTimestamp}}async function getPostgresToken(){let now=Date.now();if(pgCachedToken&&now<pgTokenExpiresAt-300000)return pgCachedToken;let{token,expiresAt}=await acquireToken("https://ossrdbms-aad.database.windows.net/.default","PostgreSQL");return pgCachedToken=token,pgTokenExpiresAt=expiresAt,pgCachedToken}async function getRedisToken(){let now=Date.now();if(redisCachedToken&&now<redisTokenExpiresAt-300000)return redisCachedToken;let{token,expiresAt}=await acquireToken("https://redis.azure.com/.default","Redis");return redisCachedToken=token,redisTokenExpiresAt=expiresAt,redisCachedToken}function getRedisTokenExpiresAt(){return redisTokenExpiresAt}var pgCachedToken=null,pgTokenExpiresAt=0,redisCachedToken=null,redisTokenExpiresAt=0;var exports_Azure={};__export(exports_Azure,{getRedisTokenExpiresAt:()=>getRedisTokenExpiresAt,getRedisToken:()=>getRedisToken,getRedisAuthMode:()=>getRedisAuthMode,getPostgresToken:()=>getPostgresToken,getDatabaseAuthMode:()=>getDatabaseAuthMode});var init_Azure=()=>{};import{access,mkdir as mkdir2}from"fs/promises";import{dirname,resolve}from"path";var DEFAULT_CONFIG5,FILE_SIZE_UNITS,resolvePath=(path2)=>{if(!path2||typeof path2!=="string")throw createFileManagerError("INVALID_PATH","Path must be a non-empty string",path2,"resolvePath");return resolve(path2)},extractDirectoryPath=(filePath)=>{let resolvedPath=resolvePath(filePath);return dirname(resolvedPath)},ensureDirectoryExists=async(dirPath)=>{let resolvedPath=resolve(dirPath);try{await mkdir2(resolvedPath,{recursive:!0})}catch(error){if(error.code!=="EEXIST")throw createFileManagerError("DIRECTORY_CREATE_FAILED",`Failed to create directory: ${resolvedPath}`,resolvedPath,"ensureDirectory")}},formatFileSize=(bytes)=>{let size=bytes,unitIndex=0;while(size>=1024&&unitIndex<FILE_SIZE_UNITS.length-1)size/=1024,unitIndex++;return`${size.toFixed(2)} ${FILE_SIZE_UNITS[unitIndex]}`},validateFileExtension=(fileName,expectedExtension)=>{return fileName.toLowerCase().endsWith(expectedExtension.toLowerCase())},ensureFileExtension=(fileName,extension)=>{let normalizedExtension=extension.startsWith(".")?extension:`.${extension}`;if(validateFileExtension(fileName,normalizedExtension))return fileName;return`${fileName}${normalizedExtension}`},createFileManagerError=(code,message,path2,operation)=>{return{code,message,path:path2,operation:operation||"unknown"}},safeJsonStringify=(data)=>{try{return JSON.stringify(data,null,2)}catch{return"{}"}},executeBulkOperation=async(items,operation,concurrency=DEFAULT_CONFIG5.maxConcurrency)=>{let results=[];for(let i=0;i<items.length;i+=concurrency){let batch3=items.slice(i,i+concurrency),batchPromises=[];for(let item of batch3)batchPromises.push(operation(item));let batchResults=await Promise.allSettled(batchPromises);results.push(...batchResults)}return results},validateConfig=(config,options={})=>{let errors=[],warnings=[],strict=options.strict??!0;if(config.defaultEncoding!==void 0){if(!["utf-8","utf8","ascii","base64","hex"].includes(config.defaultEncoding))errors.push(`Invalid defaultEncoding: ${config.defaultEncoding}`)}if(config.maxConcurrency!==void 0){if(!Number.isInteger(config.maxConcurrency)||config.maxConcurrency<1)errors.push("maxConcurrency must be a positive integer");if(config.maxConcurrency>50)warnings.push("maxConcurrency > 50 may cause performance issues")}if(config.defaultCreateDir!==void 0&&typeof config.defaultCreateDir!=="boolean")errors.push("defaultCreateDir must be a boolean");if(config.defaultRecursive!==void 0&&typeof config.defaultRecursive!=="boolean")errors.push("defaultRecursive must be a boolean");if(strict&&!options.allowUnknownKeys){let validKeys=["defaultEncoding","defaultCreateDir","defaultRecursive","maxConcurrency"],configKeys=Object.keys(config);for(let key of configKeys)if(!validKeys.includes(key))errors.push(`Unknown configuration key: ${key}`)}return{isValid:errors.length===0,errors,warnings}},mergeConfig=(partial,base=DEFAULT_CONFIG5)=>{let validation=validateConfig(partial);if(!validation.isValid)throw createFileManagerError("CONFIG_VALIDATION_FAILED",`Configuration validation failed: ${validation.errors.join(", ")}`,void 0,"mergeConfig");return{...base,...partial}},parsePermissions=(mode)=>{let parseOctal=(octal)=>({read:Boolean(octal&4),write:Boolean(octal&2),execute:Boolean(octal&1)}),ownerMode=mode>>6&7,groupMode=mode>>3&7,othersMode=mode&7;return{owner:parseOctal(ownerMode),group:parseOctal(groupMode),others:parseOctal(othersMode)}},validatePermissionMode=(mode)=>{return Number.isInteger(mode)&&mode>=0&&mode<=511};var init_utils4=__esm(()=>{DEFAULT_CONFIG5={defaultEncoding:"utf-8",defaultCreateDir:!0,defaultRecursive:!0,maxConcurrency:5},FILE_SIZE_UNITS=["B","KB","MB","GB","TB"]});import{copyFile,rename,unlink as unlink2}from"fs/promises";import{basename,dirname as dirname2,extname,join as join2}from"path";var DEFAULT_ATOMIC_CONFIG,generateTempPath=(originalPath,suffix=".tmp")=>{let resolvedPath=resolvePath(originalPath),timestamp=Date.now(),random=Math.random().toString(36).substring(2,8);return`${resolvedPath}${suffix}.${timestamp}.${random}`},generateBackupPath=(originalPath,backupDir,useTimestamp=!0)=>{let resolvedPath=resolvePath(originalPath),dir=backupDir?resolvePath(backupDir):dirname2(resolvedPath),name=basename(resolvedPath),ext=extname(name),nameWithoutExt=basename(name,ext),timestamp=useTimestamp?`.${new Date().toISOString().replace(/[:.]/g,"-")}`:"",backupName=`${nameWithoutExt}.backup${timestamp}${ext}`;return join2(dir,backupName)},atomicWrite=async({path:path2,data,tempSuffix=DEFAULT_ATOMIC_CONFIG.tempSuffix,backup=DEFAULT_ATOMIC_CONFIG.backup,sync=DEFAULT_ATOMIC_CONFIG.sync})=>{let resolvedPath=resolvePath(path2),tempPath=generateTempPath(resolvedPath,tempSuffix),backupPath;try{if(await ensureDirectoryExists(extractDirectoryPath(resolvedPath)),backup){if(await Bun.file(resolvedPath).exists())backupPath=generateBackupPath(resolvedPath),await copyFile(resolvedPath,backupPath)}let bytesWritten=await Bun.write(tempPath,data);return await rename(tempPath,resolvedPath),{success:!0,bytesWritten,tempPath,backupPath}}catch(error){try{await unlink2(tempPath)}catch{}throw createFileManagerError("ATOMIC_WRITE_FAILED",`Atomic write failed: ${error}`,resolvedPath,"atomicWrite")}},atomicJsonWrite=async(path2,data,options={})=>{let jsonString=JSON.stringify(data,null,2);return atomicWrite({path:path2,data:jsonString,...options})},createBackup=async({sourcePath,backupDir,keepOriginal=!0,timestamp=DEFAULT_ATOMIC_CONFIG.timestamp})=>{let resolvedSource=resolvePath(sourcePath);if(!await Bun.file(resolvedSource).exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"createBackup");let backupPath=generateBackupPath(resolvedSource,backupDir,timestamp);if(await ensureDirectoryExists(dirname2(backupPath)),keepOriginal)await copyFile(resolvedSource,backupPath);else await rename(resolvedSource,backupPath);return backupPath},restoreFromBackup=async(backupPath,targetPath,deleteBackup=!1)=>{let resolvedBackup=resolvePath(backupPath),resolvedTarget=resolvePath(targetPath);if(!await Bun.file(resolvedBackup).exists())throw createFileManagerError("BACKUP_NOT_FOUND",`Backup file not found: ${backupPath}`,resolvedBackup,"restoreFromBackup");try{if(await ensureDirectoryExists(extractDirectoryPath(resolvedTarget)),deleteBackup)await rename(resolvedBackup,resolvedTarget);else await copyFile(resolvedBackup,resolvedTarget);return!0}catch(error){return console.error(`Error restoring from backup ${backupPath}:`,error),!1}},safeUpdate=async(path2,updateFunction,options={})=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),backupPath;try{if(await file.exists())backupPath=await createBackup({sourcePath:resolvedPath,keepOriginal:!0,timestamp:!0});let currentData=await file.exists()?await file.text():"",newData=await updateFunction(currentData),result=await atomicWrite({path:resolvedPath,data:newData,backup:!1,...options});return{success:result.success,bytesWritten:result.bytesWritten,tempPath:result.tempPath,backupPath}}catch(error){if(backupPath)try{await restoreFromBackup(backupPath,resolvedPath,!1)}catch(rollbackError){console.error("Rollback failed:",rollbackError)}throw error}},batchAtomicWrite=async(operations)=>{let successful=[],failed=[];for(let operation of operations)try{let result=await atomicWrite(operation);successful.push(result)}catch(error){failed.push({operation,error})}return{successful,failed}};var init_atomic=__esm(()=>{init_utils4();DEFAULT_ATOMIC_CONFIG={tempSuffix:".tmp",backup:!1,sync:!0,timestamp:!0}});import{chmod,stat as stat2}from"fs/promises";var PERMISSION_MODES,setFilePermissions=async(path2,mode)=>{let resolvedPath=resolvePath(path2);if(!validatePermissionMode(mode))throw createFileManagerError("INVALID_PERMISSION_MODE",`Invalid permission mode: ${mode.toString(8)}`,resolvedPath,"setFilePermissions");try{return await chmod(resolvedPath,mode),!0}catch(error){return console.error(`Error setting permissions for ${path2}:`,error),!1}},getFilePermissions=async(path2)=>{let resolvedPath=resolvePath(path2);try{let mode=(await stat2(resolvedPath)).mode&511,permissions=parsePermissions(mode);return{path:resolvedPath,mode,owner:permissions.owner,group:permissions.group,others:permissions.others}}catch(error){throw createFileManagerError("PERMISSION_READ_FAILED",`Failed to read permissions: ${error}`,resolvedPath,"getFilePermissions")}},hasPermissions=async(path2,requiredMode)=>{try{return((await getFilePermissions(path2)).mode&requiredMode)===requiredMode}catch{return!1}},makeReadable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|256;return setFilePermissions(path2,newMode)},makeWritable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|128;return setFilePermissions(path2,newMode)},makeExecutable=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode|64;return setFilePermissions(path2,newMode)},makeReadOnly=async(path2)=>{let newMode=(await getFilePermissions(path2)).mode&-147;return setFilePermissions(path2,newMode)},setCommonPermissions=async(path2,pattern)=>{let mode=PERMISSION_MODES[pattern];return setFilePermissions(path2,mode)};var init_permissions=__esm(()=>{init_utils4();PERMISSION_MODES={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 DEFAULT_STREAM_CONFIG,createFileWriter=async(path2,options={})=>{let resolvedPath=resolvePath(path2),config={...DEFAULT_STREAM_CONFIG,...options};await ensureDirectoryExists(extractDirectoryPath(resolvedPath));let writer=Bun.file(resolvedPath).writer({highWaterMark:config.highWaterMark}),isClosed=!1;return{write:(chunk)=>{if(isClosed)throw createFileManagerError("WRITER_CLOSED","Cannot write to closed writer",resolvedPath,"streamWrite");try{let result=writer.write(chunk);if(config.autoFlush)writer.flush();return result}catch(error){throw createFileManagerError("WRITE_FAILED",`Failed to write chunk: ${error}`,resolvedPath,"streamWrite")}},flush:()=>{if(isClosed)return 0;try{return writer.flush()}catch(error){throw createFileManagerError("FLUSH_FAILED",`Failed to flush writer: ${error}`,resolvedPath,"streamFlush")}},end:async(error)=>{if(isClosed)return 0;try{let result=await writer.end(error);return isClosed=!0,result}catch(err){throw isClosed=!0,createFileManagerError("END_FAILED",`Failed to end writer: ${err}`,resolvedPath,"streamEnd")}},ref:()=>{if(!isClosed)writer.ref()},unref:()=>{if(!isClosed)writer.unref()}}},writeStream=async(path2,chunks,options={})=>{let writer=await createFileWriter(path2,options),totalBytes=0;try{for(let chunk of chunks){let bytesWritten=writer.write(chunk);totalBytes+=bytesWritten}return await writer.flush(),await writer.end(),totalBytes}catch(error){try{await writer.end(error)}catch{}throw error}},appendStream=async(path2,chunks,options={})=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),existingContent=await file.exists()?await file.arrayBuffer():new ArrayBuffer(0),allChunks=[];if(existingContent.byteLength>0)allChunks.push(existingContent);return allChunks.push(...chunks),writeStream(resolvedPath,allChunks,options)},copyFileStream=async(sourcePath,destinationPath,options={})=>{let resolvedSource=resolvePath(sourcePath),sourceFile=Bun.file(resolvedSource);if(!await sourceFile.exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"copyFileStream");let sourceStream=sourceFile.stream(),writer=await createFileWriter(destinationPath,options),totalBytes=0;try{let reader=sourceStream.getReader();while(!0){let{done,value}=await reader.read();if(done)break;let bytesWritten=writer.write(value);totalBytes+=bytesWritten}return await writer.flush(),await writer.end(),totalBytes}catch(error){try{await writer.end(error)}catch{}throw error}},readFileStream=async(path2,chunkProcessor)=>{let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath);if(!await file.exists())throw createFileManagerError("FILE_NOT_FOUND",`File not found: ${path2}`,resolvedPath,"readFileStream");let reader=file.stream().getReader();try{while(!0){let{done,value}=await reader.read();if(done)break;await chunkProcessor(value)}}finally{reader.releaseLock()}};var init_streaming=__esm(()=>{init_utils4();DEFAULT_STREAM_CONFIG={highWaterMark:1048576,autoFlush:!0,closeOnEnd:!0}});import{readdir,rm,rmdir,stat as stat3}from"fs/promises";import{extname as extname2,join as join3}from"path";class BunFileManager{static instance;config;constructor(){this.config={...DEFAULT_CONFIG5}}static getInstance(){if(!BunFileManager.instance)BunFileManager.instance=new BunFileManager;return BunFileManager.instance}async createFile({dir,name,data,options={}}){let filePath=resolvePath(join3(dir,name));if(options.createDir!==!1)await ensureDirectoryExists(extractDirectoryPath(filePath));let fileData=options.type?new Blob([data],{type:options.type}):data;return await Bun.write(filePath,fileData)}async createJsonFile(dir,name,data){let fileName=ensureFileExtension(name,".json"),jsonString=safeJsonStringify(data);return this.createFile({dir,name:fileName,data:jsonString,options:{type:"application/json"}})}async createDirectory({path:path2}){await ensureDirectoryExists(path2)}async readFile({path:path2,format="text"}){let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath);if(!await file.exists())throw createFileManagerError("FILE_NOT_FOUND",`File not found: ${path2}`,resolvedPath,"readFile");switch(format){case"text":return await file.text();case"json":return await file.json();case"buffer":return await file.arrayBuffer();case"bytes":return await file.bytes();case"stream":return file.stream();default:return await file.text()}}async readJsonFile(path2){return this.readFile({path:path2,format:"json"})}async getFileInfo(path2){let resolvedPath=resolvePath(path2),file=Bun.file(resolvedPath),fileName=path2.split("/").pop()||path2,stats=null;try{stats=await stat3(resolvedPath)}catch{}return{name:fileName,path:resolvedPath,size:file.size,type:file.type,exists:await file.exists(),extension:extname2(fileName),createdAt:stats?.birthtime,modifiedAt:stats?.mtime}}async readDirectory({path:path2,recursive=!1}){let resolvedPath=resolvePath(path2);return await readdir(resolvedPath,{recursive,encoding:"utf8"})}async getFilesByExtension(dir,extension){let files=await this.readDirectory({path:dir}),normalizedExt=extension.startsWith(".")?extension:`.${extension}`;return files.filter((file)=>file.endsWith(normalizedExt))}async updateFile({path:path2,data,mode="overwrite"}){let resolvedPath=resolvePath(path2);if(mode==="append"){let combinedData=await this.readFile({path:path2,format:"text"})+data;return await Bun.write(resolvedPath,combinedData)}return await Bun.write(resolvedPath,data)}async updateJsonFile(path2,data,merge=!1){let finalData=data;if(merge)try{let existingData=await this.readJsonFile(path2);if(typeof existingData==="object"&&existingData!==null&&!Array.isArray(existingData)&&typeof data==="object"&&data!==null&&!Array.isArray(data))finalData={...existingData,...data}}catch{}return this.updateFile({path:path2,data:safeJsonStringify(finalData),mode:"overwrite"})}async appendToFile(path2,data){return this.updateFile({path:path2,data,mode:"append"})}async deleteFile(path2){try{let resolvedPath=resolvePath(path2);return await Bun.file(resolvedPath).delete(),!0}catch(error){return console.error(`Error deleting file ${path2}:`,error),!1}}async deleteDirectory({path:path2,recursive=!1}){try{let resolvedPath=resolvePath(path2);if(recursive)await rm(resolvedPath,{recursive:!0,force:!0});else await rmdir(resolvedPath);return!0}catch(error){return console.error(`Error deleting directory ${path2}:`,error),!1}}async deleteFiles(paths){let results=await executeBulkOperation(paths,async(path2)=>{if(!await this.deleteFile(path2))throw Error(`Failed to delete: ${path2}`);return path2}),success=[],failed=[];for(let i=0;i<results.length;i++){let result=results[i],originalPath=paths[i];if(result?.status==="fulfilled")success.push(originalPath||"");else failed.push(originalPath||"")}return{success,failed}}async exists(path2){let resolvedPath=resolvePath(path2);return await Bun.file(resolvedPath).exists()}async copyFile(sourcePath,destinationPath){let resolvedSource=resolvePath(sourcePath),resolvedDestination=resolvePath(destinationPath),sourceFile=Bun.file(resolvedSource);if(!await sourceFile.exists())throw createFileManagerError("SOURCE_NOT_FOUND",`Source file not found: ${sourcePath}`,resolvedSource,"copyFile");return await ensureDirectoryExists(extractDirectoryPath(resolvedDestination)),await Bun.write(resolvedDestination,sourceFile)}async moveFile(sourcePath,destinationPath){try{return await this.copyFile(sourcePath,destinationPath),await this.deleteFile(sourcePath),!0}catch(error){return console.error(`Error moving file from ${sourcePath} to ${destinationPath}:`,error),!1}}getFormattedFileSize(bytes){return formatFileSize(bytes)}getConfig(){return{...this.config}}updateConfig(newConfig){let validation=validateConfig(newConfig);if(validation.isValid){let mergedConfig=mergeConfig(newConfig,this.config);Object.assign(this.config,mergedConfig)}return validation}validateConfiguration(config){return validateConfig(config)}async createStreamWriter(path2,options={}){return createFileWriter(path2,options)}async writeStream(path2,chunks,options={}){return writeStream(path2,chunks,options)}async appendStream(path2,chunks,options={}){return appendStream(path2,chunks,options)}async copyFileStream(sourcePath,destinationPath,options={}){return copyFileStream(sourcePath,destinationPath,options)}async readFileStream(path2,chunkProcessor){return readFileStream(path2,chunkProcessor)}async setPermissions(path2,mode){return setFilePermissions(path2,mode)}async setPermissionsAdvanced(options){return setFilePermissions(options.path,options.mode)}async getPermissions(path2){return getFilePermissions(path2)}async checkPermissions(path2,requiredMode){return hasPermissions(path2,requiredMode)}async makeFileReadable(path2){return makeReadable(path2)}async makeFileWritable(path2){return makeWritable(path2)}async makeFileExecutable(path2){return makeExecutable(path2)}async makeFileReadOnly(path2){return makeReadOnly(path2)}async setCommonPermission(path2,pattern){return setCommonPermissions(path2,pattern)}async atomicWrite(options){return atomicWrite(options)}async atomicJsonWrite(path2,data,options={}){return atomicJsonWrite(path2,data,options)}async createFileBackup(options){return createBackup(options)}async restoreFileFromBackup(backupPath,targetPath,deleteBackup=!1){return restoreFromBackup(backupPath,targetPath,deleteBackup)}async safeFileUpdate(path2,updateFunction,options={}){return safeUpdate(path2,updateFunction,options)}async batchAtomicOperations(operations){return batchAtomicWrite(operations)}}var init_core=__esm(()=>{init_atomic();init_permissions();init_streaming();init_utils4()});var fileManager;var init_File=__esm(()=>{init_core();init_utils4();init_core();fileManager=BunFileManager.getInstance()});import{Pool}from"pg";var init_Postgre=()=>{};var init_Managers=__esm(()=>{init_Azure();init_Dapr();init_File();init_Postgre();init_Redis()});var exports_utils={};__export(exports_utils,{validatePayload:()=>validatePayload,validateEnvVariables:()=>validateEnvVariables,toAudit:()=>toAudit,signNewAccessToken:()=>signNewAccessToken,sanitizePayload:()=>sanitizePayload,refreshAccessTokenWithLock:()=>refreshAccessTokenWithLock,parseTokenValuesFromHeaders:()=>parseTokenValuesFromHeaders,parseTimeToSeconds:()=>parseTimeToSeconds2,parseQueryParams:()=>parseQueryParams,initiateRedisManager:()=>initiateRedisManager,getRedisManager:()=>getRedisManager,ensureDatabaseExists:()=>ensureDatabaseExists,createAuditLog:()=>createAuditLog,buildPaginationMeta:()=>buildPaginationMeta});function parseTokenValuesFromHeaders(headers,tokenNames){let cookies=(headers.get("cookie")?.split(";")||[]).reduce((acc,cookie)=>{let trimmed=cookie.trim(),eqIndex=trimmed.indexOf("=");if(eqIndex>0)acc[trimmed.slice(0,eqIndex)]=trimmed.slice(eqIndex+1);return acc},{});return{access_token:cookies[tokenNames.access_token]||headers.get("authorization")?.split(" ")[1],refresh_token:cookies[tokenNames.refresh_token],session_token:cookies[tokenNames.session_token]}}async function initiateRedisManager(config){if(!config.redis){console.log("Redis not configured, skipping");return}let rawWithDapr=config.redis.withDapr;if(typeof rawWithDapr==="string"?process.env[rawWithDapr]?.toLowerCase()!=="false":rawWithDapr??!1){redisManagerInstance=new RedisManager({withDapr:!0,stateStoreName:config.redis.stateStoreName});return}let resolvedUrl=config.redis.url?process.env[config.redis.url]:void 0,resolvedHost=config.redis.host?process.env[config.redis.host]:void 0,resolvedPort=config.redis.port?parseInt(process.env[config.redis.port]||"",10):void 0;if((process.env.REDIS_AUTH_MODE||"password")!=="password"){let{getRedisToken:getRedisToken2,getRedisTokenExpiresAt:getRedisTokenExpiresAt2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure)),clientId=process.env.AZURE_CLIENT_ID||"",initialToken=await getRedisToken2();redisManagerInstance=new RedisManager({host:resolvedHost,port:Number.isNaN(resolvedPort)?void 0:resolvedPort,password:initialToken,username:clientId,tls:!0});let scheduleRedisTokenRefresh=()=>{let expiresAt=getRedisTokenExpiresAt2(),refreshIn=Math.max(expiresAt-Date.now()-300000,30000);setTimeout(async()=>{try{let newToken=await getRedisToken2();if(redisManagerInstance)await redisManagerInstance.reauthenticate(clientId,newToken),console.log("[Redis] Entra ID token refreshed successfully");scheduleRedisTokenRefresh()}catch(err){console.error("[Redis] Token refresh failed:",err.message),setTimeout(scheduleRedisTokenRefresh,30000)}},refreshIn)};scheduleRedisTokenRefresh()}else{let resolvedPassword=process.env.REDIS_PASSWORD||void 0;redisManagerInstance=new RedisManager({url:resolvedUrl,host:resolvedHost,port:Number.isNaN(resolvedPort)?void 0:resolvedPort,...resolvedPassword?{password:resolvedPassword}:{}})}}function getRedisManager(){return redisManagerInstance}function parseTimeToSeconds2(timeString){if(typeof timeString==="number")return timeString;if(!timeString||timeString.trim()==="")throw Error("Time string cannot be empty");let match=timeString.trim().match(/^(\d+(?:\.\d+)?)\s*([smhdwMy])$/);if(!match||!match[1]||!match[2])throw Error(`Invalid time format: "${timeString}". Expected format: "75s", "10m", "2h", "1d", "1w", "2M", "1y"`);let value=parseFloat(match[1]),unit=match[2],multiplier={s:1,m:60,h:3600,d:86400,w:604800,M:2592000,y:31536000}[unit];if(multiplier===void 0)throw Error(`Unknown time unit: "${unit}"`);let seconds=Math.floor(value*multiplier);if(seconds<=0)throw Error(`Time value must be positive: "${timeString}"`);return seconds}function signNewAccessToken({sessionData,options,refreshTokenId,roles,claims}){let secretEnvName=options.authentication?.accessToken?.secret;if(!secretEnvName)throw Error("Access token secret env name is not configured");let secret=process.env[secretEnvName];if(!secret)throw Error(`Access token secret env "${secretEnvName}" is not set`);return signJWT({subject:sessionData.userId,issuer:options.authentication?.accessToken?.issuer,audience:options.authentication?.accessToken?.audience,algorithm:options.authentication?.accessToken?.algorithm,expiresInSeconds:parseTimeToSeconds2(options.authentication?.accessToken?.expiresIn??"15m"),sessionId:sessionData.id,customClaims:{refreshTokenId,...roles&&roles.length>0?{roles}:{},...claims&&claims.length>0?{claims}:{}}},secret)}function toAudit(payload,summary){return payload?{entityName:payload.entity_name,entityId:payload.entity_id===" - "?null:payload.entity_id,operation:payload.operation_type,userId:payload.user_id==="unknown"?null:payload.user_id,summary,ipAddress:payload.ip_address,userAgent:payload.user_agent,path:payload.path,query:payload.query}:void 0}function reconstructBracketParams(query){let result={},arrayGroups={};for(let[key,value]of Object.entries(query)){let match=key.match(/^(\w+)\[\d*\]\[(\w+)\]$/),arrayName=match?.[1],prop=match?.[2];if(arrayName&&prop){if(!arrayGroups[arrayName])arrayGroups[arrayName]={};let group=arrayGroups[arrayName];if(!group[prop])group[prop]=[];let arr=group[prop];if(Array.isArray(value))for(let v of value)arr.push(v);else arr.push(value)}else result[key]=value}for(let[arrayName,props]of Object.entries(arrayGroups)){let propNames=Object.keys(props);if(propNames.length===0)continue;let maxLen=Math.max(...propNames.map((p)=>(props[p]||[]).length)),items=[];for(let i=0;i<maxLen;i++){let item={};for(let p of propNames)item[p]=(props[p]||[])[i];items.push(item)}result[arrayName]=items}return result}function parseQueryParams(query){let q=reconstructBracketParams(query),parseJSONOrPassthrough=(value)=>{if(value===void 0||value===null)return;if(typeof value==="object")return value;if(typeof value==="string")try{return JSON.parse(value)}catch{return}return},page=q.page?parseInt(q.page,10):1,limit=q.limit?parseInt(q.limit,10):20,offset=q.offset?parseInt(q.offset,10):(page-1)*limit;return{page,limit,offset,search:q.search,searchFields:q.searchFields?q.searchFields.split(","):void 0,filters:parseJSONOrPassthrough(q.filters),sort:parseJSONOrPassthrough(q.sort),select:q.select?q.select.split(","):void 0,with:parseJSONOrPassthrough(q.with),distinct:q.distinct==="true",distinctOn:q.distinctOn?q.distinctOn.split(","):void 0}}function buildPaginationMeta(page,limit,offset,totalItems){let totalPages=Math.ceil(totalItems/limit),hasNextPage=page<totalPages,hasPrevPage=page>1;return{page,limit,offset,totalItems,totalPages,hasNextPage,hasPrevPage,nextPage:hasNextPage?page+1:null,prevPage:hasPrevPage?page-1:null}}function getBaseTypeValidator(type){let stringTypes=["varchar","char","text","uuid","citext","bit","varbit"],numberTypes=["integer","smallint","bigint","serial","smallserial","bigserial","real","doublePrecision","numeric","decimal"],booleanTypes=["boolean"];if(stringTypes.includes(type))return(v)=>({valid:typeof v==="string",expectedType:"string"});if(numberTypes.includes(type))return(v)=>({valid:typeof v==="number",expectedType:"number"});if(booleanTypes.includes(type))return(v)=>({valid:typeof v==="boolean",expectedType:"boolean"});if(type==="json"||type==="jsonb")return(v)=>({valid:typeof v==="object",expectedType:"object"});return()=>({valid:!0,expectedType:"any"})}function validatePayload(payload,columns,isPartial=!1){let errors=[];for(let col2 of columns){let value=payload[col2.name]??payload[col2.name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase())],hasDbDefault=col2.default!==void 0||!!col2.defaultRaw||!!col2.generatedByDefaultAsIdentity||!!col2.generatedAlwaysAsIdentity||!!col2.generatedAlwaysAs,isRequired=col2.notNull&&!col2.nullable&&!hasDbDefault;if(value===void 0||value===null){if(isRequired&&!isPartial)errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} is required`});continue}let typeCheck=getBaseTypeValidator(col2.type)(value);if(!typeCheck.valid){errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} must be of type ${typeCheck.expectedType}`});continue}if(typeof value==="string"){let len=value.length;if(col2.length&&len>col2.length)errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} exceeds max length of ${col2.length}`});if(col2.validation?.minLength&&len<col2.validation.minLength)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at least ${col2.validation.minLength} characters`});if(col2.validation?.maxLength&&len>col2.validation.maxLength)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at most ${col2.validation.maxLength} characters`});if(col2.validation?.pattern){if(!new RegExp(col2.validation.pattern).test(value))errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} does not match required pattern`})}if(col2.validation?.format){let formatRegex=FORMAT_PATTERNS[col2.validation.format];if(formatRegex&&!formatRegex.test(value))errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be a valid ${col2.validation.format}`})}}if(typeof value==="number"){if(col2.validation?.min!==void 0&&value<col2.validation.min)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at least ${col2.validation.min}`});if(col2.validation?.max!==void 0&&value>col2.validation.max)errors.push({field:col2.name,message:col2.validation.customMessage||`${col2.name} must be at most ${col2.validation.max}`})}if(col2.enumValues&&col2.enumValues.length>0){if(!col2.enumValues.includes(value))errors.push({field:col2.name,message:col2.validation?.customMessage||`${col2.name} must be one of: ${col2.enumValues.join(", ")}`})}}return{valid:errors.length===0,errors}}function escapeHtml(str){return str.replace(/[&<>"'`=/]/g,(char)=>HTML_ENTITIES[char]||char)}function stripTags(str){return str.replace(/<[^>]*>/g,"")}function normalizeEmail(email){let parts=email.split("@"),localPart=parts[0],domain=parts[1];if(!localPart||!domain)return email;let beforePlus=localPart.split("+")[0];if(!beforePlus)return email;return`${beforePlus.replace(/\./g,"")}@${domain.toLowerCase()}`}function slugify(str){return str.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}function applySanitizer(value,sanitizer){if(value===null||value===void 0)return value;switch(sanitizer){case"trim":return typeof value==="string"?value.trim():value;case"lowercase":return typeof value==="string"?value.toLowerCase():value;case"uppercase":return typeof value==="string"?value.toUpperCase():value;case"escapeHtml":return typeof value==="string"?escapeHtml(value):value;case"stripTags":return typeof value==="string"?stripTags(value):value;case"normalizeEmail":return typeof value==="string"?normalizeEmail(value):value;case"toNumber":if(typeof value==="number")return value;if(typeof value==="string"){let num=Number(value);return Number.isNaN(num)?value:num}return value;case"toBoolean":if(typeof value==="boolean")return value;if(typeof value==="string"){let lower=value.toLowerCase();if(lower==="true"||lower==="1"||lower==="yes")return!0;if(lower==="false"||lower==="0"||lower==="no")return!1}if(typeof value==="number")return value!==0;return value;case"slugify":return typeof value==="string"?slugify(value):value;default:return value}}function sanitizePayload(payload,columns){let sanitized={},toCamel2=(s)=>s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase());for(let key of Object.keys(payload)){let value=payload[key],snakeKey=key.replace(/[A-Z]/g,(l)=>`_${l.toLowerCase()}`),col2=columns.find((c)=>c.name===key||c.name===snakeKey);if(col2?.sanitize&&col2.sanitize.length>0)for(let sanitizer of col2.sanitize)value=applySanitizer(value,sanitizer);if(col2&&(col2.type==="timestamp"||col2.type==="timestamptz"||col2.type==="date")&&typeof value==="string"){let parsed=new Date(value);if(!Number.isNaN(parsed.getTime()))value=parsed}let normalizedKey=key.includes("_")?toCamel2(key):key;sanitized[normalizedKey]=value}return sanitized}function createAuditLog(db,auditTable,entry){if(!db||!auditTable)return;let logEntry={user_id:entry.user_id,entity_name:entry.entity_name,entity_id:entry.entity_id,operation:entry.operation,old_data:entry.old_data??null,new_data:entry.new_data??null,timestamp:new Date().toISOString()};db.insert(auditTable).values(logEntry).execute().catch((err)=>{console.error("Audit log failed:",err)})}async function refreshAccessTokenWithLock(userId,sessionId,generateToken){let redis=new RedisManager,lockKey=`${REFRESH_LOCK_PREFIX}${userId}`,cacheKey=`${ACCESS_TOKEN_CACHE_PREFIX}${userId}:${sessionId}`,cachedResult=await redis.read(cacheKey);if(cachedResult.success&&cachedResult.data)return{success:!0,accessToken:cachedResult.data,fromCache:!0};let lockResult=await redis.acquireLock(lockKey,LOCK_TTL_SECONDS);if(!lockResult.success)return{success:!1,error:lockResult.error};if(lockResult.data)try{let newToken=generateToken();return await redis.create(cacheKey,newToken,ACCESS_TOKEN_CACHE_TTL_SECONDS),{success:!0,accessToken:newToken,fromCache:!1}}finally{await redis.releaseLock(lockKey)}let waitResult=await redis.waitForLock(lockKey,LOCK_WAIT_TIMEOUT_MS,50);if(!waitResult.success)return{success:!1,error:waitResult.error};if(!waitResult.data)return{success:!1,error:"Lock wait timeout"};let newCachedResult=await redis.read(cacheKey);if(newCachedResult.success&&newCachedResult.data)return{success:!0,accessToken:newCachedResult.data,fromCache:!0};let fallbackToken=generateToken();return await redis.create(cacheKey,fallbackToken,ACCESS_TOKEN_CACHE_TTL_SECONDS),{success:!0,accessToken:fallbackToken,fromCache:!1}}function validateEnvVariables(config){let errors=[],resolved={},databaseAuthMode=process.env.DATABASE_AUTH_MODE||"password",redisAuthMode=process.env.REDIS_AUTH_MODE||"password";resolved.databaseAuthMode=databaseAuthMode,resolved.redisAuthMode=redisAuthMode;let entraIdModes=["managed_identity","service_principal"];if(entraIdModes.includes(databaseAuthMode)||entraIdModes.includes(redisAuthMode)){if(!process.env.AZURE_CLIENT_ID)console.warn("[Nucleus] AZURE_CLIENT_ID is not set. Required for user-assigned managed identity.");if([databaseAuthMode,redisAuthMode].filter((m)=>m==="service_principal").length>0){if(!process.env.AZURE_TENANT_ID)errors.push({field:"azure.tenantId",envName:"AZURE_TENANT_ID",message:"AZURE_TENANT_ID is required for service_principal auth mode."});if(!process.env.AZURE_CLIENT_SECRET)errors.push({field:"azure.clientSecret",envName:"AZURE_CLIENT_SECRET",message:"AZURE_CLIENT_SECRET is required for service_principal auth mode."})}}if(config.database?.url){let envValue=process.env[config.database.url];if(!envValue)errors.push({field:"database.url",envName:config.database.url,message:`Environment variable "${config.database.url}" is not set. Please set it in your .env file.`});else resolved.databaseUrl=envValue}let validationWithDapr=typeof config.redis?.withDapr==="string"?process.env[config.redis.withDapr]?.toLowerCase()!=="false":config.redis?.withDapr??!1;if(config.redis&&!validationWithDapr)if(config.redis.url){let envValue=process.env[config.redis.url];if(!envValue)errors.push({field:"redis.url",envName:config.redis.url,message:`Environment variable "${config.redis.url}" is not set. Please set it in your .env file.`});else resolved.redisUrl=envValue}else{if(config.redis.host){if(!process.env[config.redis.host])errors.push({field:"redis.host",envName:config.redis.host,message:`Environment variable "${config.redis.host}" is not set. Please set it in your .env file.`})}if(config.redis.port){if(!process.env[config.redis.port])errors.push({field:"redis.port",envName:config.redis.port,message:`Environment variable "${config.redis.port}" is not set. Please set it in your .env file.`})}}if(config.authentication?.enabled){if(!config.authentication.mode)errors.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(config.authentication.accessToken?.secret){let envValue=process.env[config.authentication.accessToken.secret];if(!envValue)errors.push({field:"authentication.accessToken.secret",envName:config.authentication.accessToken.secret,message:`Environment variable "${config.authentication.accessToken.secret}" is not set. Please set it in your .env file.`});else resolved.accessTokenSecret=envValue}else errors.push({field:"authentication.accessToken.secret",envName:"",message:"authentication.accessToken.secret is required when authentication is enabled."});let isConsumerMode=config.authentication.mode==="consumer";if(config.authentication.refreshToken?.secret){let envValue=process.env[config.authentication.refreshToken.secret];if(!envValue)errors.push({field:"authentication.refreshToken.secret",envName:config.authentication.refreshToken.secret,message:`Environment variable "${config.authentication.refreshToken.secret}" is not set. Please set it in your .env file.`});else resolved.refreshTokenSecret=envValue}else if(!isConsumerMode)errors.push({field:"authentication.refreshToken.secret",envName:"",message:"authentication.refreshToken.secret is required when authentication is enabled."});if(config.authentication.sessionToken?.secret){let envValue=process.env[config.authentication.sessionToken.secret];if(!envValue)errors.push({field:"authentication.sessionToken.secret",envName:config.authentication.sessionToken.secret,message:`Environment variable "${config.authentication.sessionToken.secret}" is not set. Please set it in your .env file.`});else resolved.sessionTokenSecret=envValue}else if(!isConsumerMode)errors.push({field:"authentication.sessionToken.secret",envName:"",message:"authentication.sessionToken.secret is required when authentication is enabled."})}if(config.authentication?.oauth?.enabled&&config.authentication.oauth.providers){let resolvedProviders={};for(let[providerName,providerConfig]of Object.entries(config.authentication.oauth.providers)){if(!providerConfig)continue;let{clientId:clientIdEnvName,clientSecret:clientSecretEnvName,redirectUri:redirectUriEnvName}=providerConfig,clientId=process.env[clientIdEnvName],clientSecret=process.env[clientSecretEnvName],redirectUri=process.env[redirectUriEnvName]??redirectUriEnvName;if(!clientId)errors.push({field:`authentication.oauth.providers.${providerName}.clientId`,envName:clientIdEnvName,message:`Environment variable "${clientIdEnvName}" is not set (OAuth ${providerName} clientId).`});if(!clientSecret)errors.push({field:`authentication.oauth.providers.${providerName}.clientSecret`,envName:clientSecretEnvName,message:`Environment variable "${clientSecretEnvName}" is not set (OAuth ${providerName} clientSecret).`});if(clientId&&clientSecret)resolvedProviders[providerName]={clientId,clientSecret,redirectUri,scopes:providerConfig.scopes,authorizationUrl:providerConfig.authorizationUrl,tokenUrl:providerConfig.tokenUrl,userInfoUrl:providerConfig.userInfoUrl,extraAuthParams:providerConfig.extraAuthParams}}if(Object.keys(resolvedProviders).length>0)resolved.oauthProviders=resolvedProviders}return{valid:errors.length===0,errors,resolved}}async function ensureDatabaseExists(databaseUrl,logger2,authMode){let{Pool:Pool2}=await import("pg"),targetDb=new URL(databaseUrl).pathname.replace("/","");if(!targetDb)return;let adminUrl=new URL(databaseUrl);adminUrl.pathname="/postgres";let pool;if(authMode&&authMode!=="password"){let{getPostgresToken:getPostgresToken2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure));pool=new Pool2({connectionString:adminUrl.toString(),password:getPostgresToken2,ssl:{rejectUnauthorized:!0}})}else pool=new Pool2({connectionString:adminUrl.toString()});try{if((await pool.query("SELECT 1 FROM pg_database WHERE datname = $1",[targetDb])).rowCount===0)logger2.info(`[Database] Creating database "${targetDb}"...`),await pool.query(`CREATE DATABASE "${targetDb}" TEMPLATE template0`),logger2.info(`[Database] Database "${targetDb}" created successfully`);else logger2.info(`[Database] Database "${targetDb}" exists`)}catch(err){let message=err instanceof Error?err.message:String(err);logger2.warn(`[Database] Could not auto-create database: ${message}`)}finally{await pool.end()}}var redisManagerInstance=null,FORMAT_PATTERNS,HTML_ENTITIES,ACCESS_TOKEN_CACHE_PREFIX="access_token:",REFRESH_LOCK_PREFIX="refresh_lock:",LOCK_TTL_SECONDS=5,LOCK_WAIT_TIMEOUT_MS=3000,ACCESS_TOKEN_CACHE_TTL_SECONDS=60;var init_utils5=__esm(()=>{init_Managers();init_Services();FORMAT_PATTERNS={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};HTML_ENTITIES={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}});import{eq as eq8}from"drizzle-orm";import{pgSchema}from"drizzle-orm/pg-core";class TenantRegistry{db;logger;mainSchemaName;mainSchemaTables;mainSchemaRelations;createAllTablesForSchema;createAllRelationsForSchema;appId;authMode;tenantResolution;tenantHeader;redisCacheTtlSeconds;idpUrl;tenantsBySubdomain=new Map;tenantsBySchemaName=new Map;tenantsById=new Map;schemaContexts=new Map;tenantFeatures=new Map;constructor(config){this.db=config.db,this.logger=config.logger,this.mainSchemaName=config.mainSchemaName,this.mainSchemaTables=config.mainSchemaTables,this.mainSchemaRelations=config.mainSchemaRelations,this.createAllTablesForSchema=config.createAllTablesForSchema,this.createAllRelationsForSchema=config.createAllRelationsForSchema,this.appId=config.appId,this.authMode=config.authMode,this.tenantResolution=config.tenantResolution,this.tenantHeader=config.tenantHeader,this.redisCacheTtlSeconds=config.redisCacheTtlSeconds,this.idpUrl=config.idpUrl}async initialize(){this.logger.info("[TenantRegistry] Initializing..."),this.schemaContexts.set(this.mainSchemaName,{schemaName:this.mainSchemaName,schemaTables:this.mainSchemaTables,schemaRelations:this.mainSchemaRelations,tenant:null});let tenants=await this.loadTenantsFromDb();this.logger.info(`[TenantRegistry] Loaded ${tenants.length} tenants from database`);let features=await this.loadTenantFeaturesFromDb();this.logger.info(`[TenantRegistry] Loaded ${features.length} tenant feature mappings`);for(let tenant of tenants)this.indexTenant(tenant);for(let feature of features){let existing=this.tenantFeatures.get(feature.tenantId)||[];existing.push(feature),this.tenantFeatures.set(feature.tenantId,existing)}let activeTenants=tenants.filter((t)=>t.status==="active");for(let tenant of activeTenants)await this.buildSchemaContext(tenant);this.logger.info(`[TenantRegistry] Initialized with ${activeTenants.length} active tenant schemas + main schema`)}resolveFromRequest(request){let url=new URL(request.url),host=request.headers.get("host")||url.host||"";if(this.tenantResolution==="subdomain"||this.tenantResolution==="both"){let subdomain=extractSubdomain(host);if(subdomain){let tenant=this.tenantsBySubdomain.get(subdomain);if(tenant)return this.validateAndReturnTenant(tenant);return{resolved:!1,error:`Tenant not found for subdomain: ${subdomain}`,statusCode:404}}}if(this.tenantResolution==="header"||this.tenantResolution==="both"){let tenantIdOrSubdomain=request.headers.get(this.tenantHeader);if(tenantIdOrSubdomain){let result=this.resolveFromHeader(tenantIdOrSubdomain,request);if(result)return result}}let mainContext=this.schemaContexts.get(this.mainSchemaName);if(mainContext)return{resolved:!0,context:mainContext};return{resolved:!1,error:"No tenant could be resolved and main schema is unavailable",statusCode:500}}getSchemaContext(schemaName){return this.schemaContexts.get(schemaName)}getMainContext(){let ctx=this.schemaContexts.get(this.mainSchemaName);if(!ctx)throw Error("[TenantRegistry] Main schema context not initialized");return ctx}getActiveTenants(){return Array.from(this.tenantsById.values()).filter((t)=>t.status==="active")}getTenantById(id){return this.tenantsById.get(id)}getTenantFeatures(tenantId){return this.tenantFeatures.get(tenantId)||[]}isTenantFeatureEnabled(tenantId,featureName){return(this.tenantFeatures.get(tenantId)||[]).find((f)=>f.featureName===featureName)?.enabled??!1}getTenantIdsWithFeature(featureName){let result=[];for(let[tenantId,features]of this.tenantFeatures)if(features.find((f)=>f.featureName===featureName&&f.enabled))result.push(tenantId);return result}getSchemaNamesWithFeature(featureName){let tenantIds=this.getTenantIdsWithFeature(featureName),schemaNames=[];for(let tenantId of tenantIds){let tenant=this.tenantsById.get(tenantId);if(tenant&&tenant.status==="active")schemaNames.push(tenant.schemaName)}return schemaNames}getAllSchemaNames(){return Array.from(this.schemaContexts.keys())}async provisionTenant(tenant){this.logger.info(`[TenantRegistry] Provisioning tenant: ${tenant.subdomain} \u2192 ${tenant.schemaName}`),await ensureSchemaExists(this.db,tenant.schemaName);let context=await this.buildSchemaContext(tenant);return this.indexTenant(tenant),await this.syncSchemaToDb(context),this.logger.info(`[TenantRegistry] Tenant provisioned: ${tenant.subdomain}`),context}async syncSchemaToDb(context){let{pushSchema}=await import("drizzle-kit/api"),targetSchema=pgSchema(context.schemaName);try{await(await pushSchema({schema:targetSchema,...context.schemaTables},this.db,[context.schemaName])).apply(),this.logger.info(`[TenantRegistry] Schema sync completed for: ${context.schemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);this.logger.warn(`[TenantRegistry] Schema sync warning for ${context.schemaName}: ${msg}`)}}async syncAllSchemas(){for(let[schemaName,context]of this.schemaContexts)this.logger.info(`[TenantRegistry] Syncing schema: ${schemaName}`),await ensureSchemaExists(this.db,schemaName),await this.syncSchemaToDb(context)}async invalidateCache(subdomain){try{let{getRedisManager:getRedisManager2}=await Promise.resolve().then(() => (init_utils5(),exports_utils)),redis=getRedisManager2();if(redis)await redis.remove(`tenant:${subdomain}`),this.logger.info(`[TenantRegistry] Cache invalidated for: ${subdomain}`)}catch{}}async refreshTenant(tenantId){let tenantsTable=this.mainSchemaTables.tenants;if(!tenantsTable)return;let row=(await this.db.select().from(tenantsTable).where(eq8(tenantsTable.id,tenantId)).limit(1))[0];if(!row)return;let tenant=rowToTenantRecord(row),oldTenant=this.tenantsById.get(tenantId);if(oldTenant)this.tenantsBySubdomain.delete(oldTenant.subdomain),this.tenantsBySchemaName.delete(oldTenant.schemaName);if(this.indexTenant(tenant),tenant.status==="active")await this.buildSchemaContext(tenant);else this.schemaContexts.delete(tenant.schemaName);if(oldTenant)await this.invalidateCache(oldTenant.subdomain);await this.invalidateCache(tenant.subdomain)}async initializeFromIdp(){if(!this.idpUrl){this.logger.error("[TenantRegistry] Consumer multi-tenant requires idpUrl (IDP_URL)");return}this.logger.info(`[TenantRegistry] Initializing from IDP: ${this.idpUrl}`),this.schemaContexts.set(this.mainSchemaName,{schemaName:this.mainSchemaName,schemaTables:this.mainSchemaTables,schemaRelations:this.mainSchemaRelations,tenant:null});let tenants=await this.loadTenantsFromIdp();this.logger.info(`[TenantRegistry] Fetched ${tenants.length} tenants from IDP`);for(let tenant of tenants)this.indexTenant(tenant);let activeTenants=tenants.filter((t)=>t.status==="active");for(let tenant of activeTenants)await this.buildSchemaContext(tenant);this.logger.info(`[TenantRegistry] Consumer initialized with ${activeTenants.length} active tenant schemas + main schema`)}isConsumerMode(){return this.authMode==="consumer"&&!!this.idpUrl}async loadTenantsFromIdp(){if(!this.idpUrl)return[];try{let response=await fetch(`${this.idpUrl}/tenants`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!response.ok)return this.logger.warn(`[TenantRegistry] IDP tenant fetch failed: ${response.status} ${response.statusText}`),[];return((await response.json())?.data?.items||[]).map((item)=>rowToTenantRecord(item))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to fetch tenants from IDP: ${msg}`),[]}}async loadTenantsFromDb(){let tenantsTable=this.mainSchemaTables.tenants;if(!tenantsTable)return this.logger.warn("[TenantRegistry] No tenants table found in main schema"),[];try{return(await this.db.select().from(tenantsTable)).map((row)=>rowToTenantRecord(row))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to load tenants: ${msg}`),[]}}async loadTenantFeaturesFromDb(){let featuresTable=this.mainSchemaTables.tenantFeatures;if(!featuresTable)return this.logger.warn("[TenantRegistry] No tenant_features table found in main schema"),[];try{return(await this.db.select().from(featuresTable)).map((row)=>rowToFeatureRecord(row,parseJsonbToConfig))}catch(err){let msg=err instanceof Error?err.message:String(err);return this.logger.warn(`[TenantRegistry] Failed to load tenant features: ${msg}`),[]}}indexTenant(tenant){if(this.tenantsById.set(tenant.id,tenant),this.tenantsBySubdomain.set(tenant.subdomain,tenant),this.tenantsBySchemaName.set(tenant.schemaName,tenant),tenant.domain)this.tenantsBySubdomain.set(tenant.domain,tenant)}async buildSchemaContext(tenant){let schema=pgSchema(tenant.schemaName),schemaTables=this.createAllTablesForSchema(schema),schemaRelations=this.createAllRelationsForSchema?this.createAllRelationsForSchema(schema):{},context={schemaName:tenant.schemaName,schemaTables,schemaRelations,tenant};return this.schemaContexts.set(tenant.schemaName,context),context}resolveFromHeader(tenantIdOrSubdomain,request){let tenant=this.tenantsBySubdomain.get(tenantIdOrSubdomain);if(!tenant)tenant=this.tenantsById.get(tenantIdOrSubdomain);if(!tenant)tenant=this.tenantsBySchemaName.get(tenantIdOrSubdomain);if(!tenant)return{resolved:!1,error:`Tenant not found for header value: ${tenantIdOrSubdomain}`,statusCode:404};if(!isTrustedSource(tenant,request,this.authMode))return{resolved:!1,error:`Untrusted source for tenant: ${tenant.subdomain}`,statusCode:403};return this.validateAndReturnTenant(tenant)}validateAndReturnTenant(tenant){if(tenant.status==="suspended")return{resolved:!1,error:`Tenant ${tenant.subdomain} is suspended: ${tenant.suspendedReason||"No reason provided"}`,statusCode:403};if(tenant.status==="provisioning")return{resolved:!1,error:`Tenant ${tenant.subdomain} is still being provisioned`,statusCode:503};if(tenant.status==="archived")return{resolved:!1,error:`Tenant ${tenant.subdomain} has been archived`,statusCode:410};let context=this.schemaContexts.get(tenant.schemaName);if(!context)return{resolved:!1,error:`Schema context not found for tenant: ${tenant.subdomain}`,statusCode:500};return{resolved:!0,context}}}var init_TenantRegistry=__esm(()=>{init_schema()});var init_Tenant=__esm(()=>{init_schema();init_TenantRegistry()});var init_types5=()=>{};import{and as and4,desc as desc2,eq as eq9,inArray as inArray2}from"drizzle-orm";function toCamel2(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());result[camelKey]=value}return result}function fromCamel2(obj){let result={};for(let[key,value]of Object.entries(obj)){let snakeKey=key.replace(/[A-Z]/g,(c)=>`_${c.toLowerCase()}`);result[snakeKey]=value}return result}class VerificationService{db;schemaTables;config;logger;onNotificationTrigger;constructor(serviceConfig){this.db=serviceConfig.db,this.schemaTables=serviceConfig.schemaTables,this.config=serviceConfig.config,this.logger=serviceConfig.logger}setNotificationHandler(handler){this.onNotificationTrigger=handler}getConnectedNotificationNodeIds(stepNodeId,steps,edges){let result=new Set,getNeighbors=(nid)=>{let neighbors=[];for(let edge of edges){let{sourceNodeId:src,targetNodeId:tgt}=edge;if(src===nid)neighbors.push(tgt);else if(tgt===nid)neighbors.push(src)}return neighbors},directNeighbors=getNeighbors(stepNodeId);for(let neighborId of directNeighbors)if(steps.find((s)=>s.nodeId===neighborId)?.nodeType==="notification")result.add(neighborId);for(let neighborId of directNeighbors)if(steps.find((s)=>s.nodeId===neighborId)?.nodeType==="verifier"){let verifierNeighbors=getNeighbors(neighborId);for(let vNeighborId of verifierNeighbors){if(vNeighborId===stepNodeId)continue;if(steps.find((s)=>s.nodeId===vNeighborId)?.nodeType==="notification")result.add(vNeighborId)}}let ids=[...result];return this.logger.info(`[Verification] Connected notification nodes for step ${stepNodeId}: [${ids.join(", ")}]`),ids}getTable(name){return this.schemaTables[name]}getCol(table,col2){return table[col2]}async listFlows(entityName){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return[];return(await(entityName?this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"entityName"),entityName)):this.db.select().from(flowsTable))).map((r)=>fromCamel2(r))}async getFlow(flowId){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),notifRulesTable=this.getTable("verificationNotificationRules"),notifRecipientsTable=this.getTable("verificationNotificationRecipients"),notifChannelsTable=this.getTable("verificationNotificationChannels");if(!flowsTable)return null;let flowRow=(await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)).limit(1))[0];if(!flowRow)return null;let flow=fromCamel2(flowRow),steps=(stepsTable?await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),edges=(edgesTable?await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),verifierConfigs=(verifierConfigsTable?await this.db.select().from(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),notifRules=(notifRulesTable?await this.db.select().from(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId)):[]).map((r)=>fromCamel2(r)),ruleIds=notifRules.map((r)=>r.id),notifRecipients=(notifRecipientsTable&&ruleIds.length>0?await this.db.select().from(notifRecipientsTable).where(inArray2(this.getCol(notifRecipientsTable,"ruleId"),ruleIds)):[]).map((r)=>fromCamel2(r)),notifChannels=(notifChannelsTable&&ruleIds.length>0?await this.db.select().from(notifChannelsTable).where(inArray2(this.getCol(notifChannelsTable,"ruleId"),ruleIds)):[]).map((r)=>fromCamel2(r));return{flow,graph:{steps,edges,verifier_configs:verifierConfigs,notification_rules:notifRules,notification_recipients:notifRecipients,notification_channels:notifChannels}}}async saveFlow(params){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),notifRulesTable=this.getTable("verificationNotificationRules"),notifRecipientsTable=this.getTable("verificationNotificationRecipients"),notifChannelsTable=this.getTable("verificationNotificationChannels");if(!flowsTable||!stepsTable||!edgesTable)throw Error("Verification tables not configured");let existingFlows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),params.flow_id)).limit(1),flowId=params.flow_id;if(existingFlows.length>0)await this.db.update(flowsTable).set(toCamel2({entity_name:params.entity_name,name:params.name,description:params.description||null,trigger_on:params.trigger_on,trigger_fields:params.trigger_fields||null,is_draft:params.is_draft,viewport:params.viewport||null})).where(eq9(this.getCol(flowsTable,"id"),flowId));else{let[newFlow]=await this.db.insert(flowsTable).values(toCamel2({id:flowId,entity_name:params.entity_name,name:params.name,description:params.description||null,trigger_on:params.trigger_on,trigger_fields:params.trigger_fields||null,is_draft:params.is_draft,viewport:params.viewport||null})).returning();flowId=newFlow.id}if(await this.db.delete(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),flowId)),edgesTable)await this.db.delete(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),flowId));if(verifierConfigsTable)await this.db.delete(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId));if(notifRulesTable){let oldRuleIds=(await this.db.select().from(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId))).map((r)=>r.id);if(oldRuleIds.length>0){if(notifRecipientsTable)for(let rid of oldRuleIds)await this.db.delete(notifRecipientsTable).where(eq9(this.getCol(notifRecipientsTable,"ruleId"),rid));if(notifChannelsTable)for(let rid of oldRuleIds)await this.db.delete(notifChannelsTable).where(eq9(this.getCol(notifChannelsTable,"ruleId"),rid))}await this.db.delete(notifRulesTable).where(eq9(this.getCol(notifRulesTable,"flowId"),flowId))}let{graph}=params;if(graph.steps.length>0)await this.db.insert(stepsTable).values(graph.steps.map((s)=>toCamel2({flow_id:flowId,entity_name:params.entity_name,node_id:s.node_id,node_type:s.node_type,step_order:s.step_order,name:s.name||null,description:s.description||null,position_x:s.position_x,position_y:s.position_y,width:s.width||null,height:s.height||null,style:s.style||null,data:s.data||null})));if(graph.edges.length>0&&edgesTable)await this.db.insert(edgesTable).values(graph.edges.map((e)=>toCamel2({flow_id:flowId,edge_id:e.edge_id,source_node_id:e.source_node_id,target_node_id:e.target_node_id,source_handle:e.source_handle||null,target_handle:e.target_handle||null,edge_type:e.edge_type,label:e.label||null,condition:e.condition||null,style:e.style||null,animated:e.animated})));if(graph.verifier_configs.length>0&&verifierConfigsTable)await this.db.insert(verifierConfigsTable).values(graph.verifier_configs.map((vc)=>toCamel2({flow_id:flowId,node_id:vc.node_id,verifier_type:vc.verifier_type,verifier_user_id:vc.verifier_user_id||null,verifier_role:vc.verifier_role||null,require_signature:vc.require_signature,all_must_approve:vc.all_must_approve})));if(this.logger.info(`[Verification] Save: ${graph.notification_rules.length} rules, ${graph.notification_recipients.length} recipients, ${graph.notification_channels.length} channels`),graph.notification_rules.length>0&¬ifRulesTable)for(let rule of graph.notification_rules){this.logger.info(`[Verification] Saving notification rule: node_id=${rule.node_id}, trigger=${rule.trigger}, title_template=${JSON.stringify(rule.title_template)}, body_template=${JSON.stringify(rule.body_template)}`);let[insertedRule]=await this.db.insert(notifRulesTable).values(toCamel2({flow_id:flowId,node_id:rule.node_id,trigger:rule.trigger,title_template:rule.title_template||null,body_template:rule.body_template||null,starts_at:rule.starts_at||null,expires_at:rule.expires_at||null})).returning(),ruleId=insertedRule.id,ruleRecipients=graph.notification_recipients.filter((r)=>r.rule_id===rule.node_id);if(ruleRecipients.length>0&¬ifRecipientsTable)await this.db.insert(notifRecipientsTable).values(ruleRecipients.map((r)=>toCamel2({rule_id:ruleId,recipient_type:r.recipient_type,recipient_user_id:r.recipient_user_id||null,recipient_role:r.recipient_role||null})));let ruleChannels=graph.notification_channels.filter((c)=>c.rule_id===rule.node_id);if(ruleChannels.length>0&¬ifChannelsTable)await this.db.insert(notifChannelsTable).values(ruleChannels.map((c)=>toCamel2({rule_id:ruleId,channel:c.channel})))}return this.logger.info(`[Verification] Flow saved: ${flowId} for ${params.entity_name}`),{success:!0,flow_id:flowId}}async publishFlow(flowId){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};return await this.db.update(flowsTable).set(toCamel2({is_draft:!1,published_at:new Date})).where(eq9(this.getCol(flowsTable,"id"),flowId)),this.logger.info(`[Verification] Flow published: ${flowId}`),{success:!0,message:"Flow published"}}async deleteFlow(flowId){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};return await this.db.delete(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)),this.logger.info(`[Verification] Flow deleted: ${flowId}`),{success:!0,message:"Flow deleted"}}async startFlow(params){let flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),instancesTable=this.getTable("verificationInstances"),requirementsTable=this.getTable("verificationRequirements"),userRolesTable=this.getTable("user_roles");if(!flowsTable||!stepsTable||!edgesTable||!instancesTable||!requirementsTable)return{success:!1,message:"Verification tables not configured"};let flow=(await this.db.select().from(flowsTable).where(and4(eq9(this.getCol(flowsTable,"id"),params.flow_id),eq9(this.getCol(flowsTable,"isDraft"),!1))).limit(1))[0];if(!flow)return{success:!1,message:"Published flow not found"};if((await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"entityName"),params.entity_name),eq9(this.getCol(instancesTable,"entityId"),params.entity_id),eq9(this.getCol(instancesTable,"status"),"active"))).limit(1)).length>0)return{success:!1,message:"An active verification instance already exists for this entity"};let steps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),params.flow_id)),edges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),params.flow_id)),stepNodes=steps.filter((s)=>s.nodeType==="step");if(stepNodes.sort((a,b)=>a.stepOrder-b.stepOrder),stepNodes.length===0)return{success:!1,message:"Flow has no step nodes"};let[instance]=await this.db.insert(instancesTable).values(toCamel2({flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,started_by:params.started_by||null,status:"active",current_step_order:1,started_at:new Date})).returning(),instanceId=instance.id;if(await this.materializeRequirementsForStep(instanceId,params.flow_id,params.entity_name,params.entity_id,1,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable),this.onNotificationTrigger){let firstStep=stepNodes[0],firstStepNodeId=firstStep?.nodeId,connectedNotifIds=firstStepNodeId?this.getConnectedNotificationNodeIds(firstStepNodeId,steps,edges):[],ctx={flow_name:flow.name,step_name:firstStep?.name||"Step 1",step_order:1,total_steps:stepNodes.length};if(connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,node_id:notifNodeId,context:ctx});else await this.onNotificationTrigger({trigger:"on_flow_started",flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,context:ctx})}return this.logger.info(`[Verification] Flow started: instance ${instanceId} for ${params.entity_name}:${params.entity_id}`),{success:!0,instance_id:instanceId,message:"Flow started"}}async materializeRequirementsForStep(instanceId,flowId,entityName,entityId,stepOrder,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable){if(!requirementsTable)return;let stepNode=steps.find((s)=>s.nodeType==="step"&&s.stepOrder===stepOrder);if(!stepNode)return;let stepNodeId=stepNode.nodeId,verifierNodeIds=edges.filter((e)=>e.targetNodeId===stepNodeId).map((e)=>e.sourceNodeId),verifierNodes=steps.filter((s)=>s.nodeType==="verifier"&&verifierNodeIds.includes(s.nodeId));if(verifierNodes.length===0)return;let verifierConfigs=[];if(verifierConfigsTable)verifierConfigs=await this.db.select().from(verifierConfigsTable).where(eq9(this.getCol(verifierConfigsTable,"flowId"),flowId));for(let verifierNode of verifierNodes){let nodeId=verifierNode.nodeId,config=verifierConfigs.find((vc)=>vc.nodeId===nodeId);if(!config)continue;let{verifierType,allMustApprove}=config;if(verifierType==="role"&&allMustApprove&&userRolesTable){let rolesTable=this.getTable("roles");if(rolesTable){let rolesCols=rolesTable,userRolesCols=userRolesTable,role=(await this.db.select().from(rolesTable).where(eq9(rolesCols.name,config.verifierRole)).limit(1))[0];if(role){let usersWithRole=await this.db.select({user_id:userRolesCols.userId}).from(userRolesTable).where(eq9(userRolesCols.roleId,role.id));for(let userRole of usersWithRole)await this.db.insert(requirementsTable).values(toCamel2({instance_id:instanceId,step_node_id:stepNodeId,verifier_node_id:nodeId,entity_name:entityName,entity_id:entityId,verifier_type:"user",verifier_user_id:userRole.user_id,verifier_role:config.verifierRole||null,require_signature:config.requireSignature,all_must_approve:!0,step_order:stepOrder,status:"pending"}))}}}else await this.db.insert(requirementsTable).values(toCamel2({instance_id:instanceId,step_node_id:stepNodeId,verifier_node_id:nodeId,entity_name:entityName,entity_id:entityId,verifier_type:verifierType,verifier_user_id:config.verifierUserId||null,verifier_role:config.verifierRole||null,require_signature:config.requireSignature,all_must_approve:allMustApprove,step_order:stepOrder,status:"pending"}))}if(this.onNotificationTrigger){let connectedNotifIds=this.getConnectedNotificationNodeIds(stepNodeId,steps,edges);if(this.logger.info(`[Verification] on_step_reached: stepNodeId=${stepNodeId}, connectedNotifIds=[${connectedNotifIds.join(", ")}]`),connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)this.logger.info(`[Verification] Triggering on_step_reached for notifNodeId=${notifNodeId}`),await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:flowId,entity_name:entityName,entity_id:entityId,node_id:notifNodeId,context:{step_name:stepNode.name||`Step ${stepOrder}`,step_order:stepOrder}});else await this.onNotificationTrigger({trigger:"on_step_reached",flow_id:flowId,entity_name:entityName,entity_id:entityId,context:{step_name:stepNode.name||`Step ${stepOrder}`,step_order:stepOrder}})}}async getStatus(entityName,entityId){let instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),verificationsTable=this.getTable("verifications"),requirementsTable=this.getTable("verificationRequirements"),emptyStatus={entity_name:entityName,entity_id:entityId,instance:null,flow:null,current_step:0,total_steps:0,is_completed:!1,is_rejected:!1,verifications:[],pending_requirements:[]};if(!instancesTable||!flowsTable||!verificationsTable||!requirementsTable)return this.logger.error("[Verification] Required tables not found"),emptyStatus;let instanceRow=(await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"entityName"),entityName),eq9(this.getCol(instancesTable,"entityId"),entityId))).orderBy(desc2(this.getCol(instancesTable,"createdAt"))).limit(1))[0];if(!instanceRow)return emptyStatus;let instance=fromCamel2(instanceRow),flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),instance.flow_id)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0,totalSteps=(stepsTable?await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),instance.flow_id),eq9(this.getCol(stepsTable,"nodeType"),"step"))):[]).length,verifications=(await this.db.select().from(verificationsTable).where(eq9(this.getCol(verificationsTable,"instanceId"),instance.id)).orderBy(desc2(this.getCol(verificationsTable,"createdAt")))).map((r)=>fromCamel2(r)),pendingRequirements=(await this.db.select().from(requirementsTable).where(and4(eq9(this.getCol(requirementsTable,"instanceId"),instance.id),eq9(this.getCol(requirementsTable,"status"),"pending")))).map((r)=>fromCamel2(r));return{entity_name:entityName,entity_id:entityId,instance,flow:flow||null,current_step:instance.current_step_order,total_steps:totalSteps,is_completed:instance.status==="completed",is_rejected:instance.status==="rejected",verifications,pending_requirements:pendingRequirements}}async decide(params){let{entity_name,entity_id,user_id,decision,reason,signature_id,diff}=params,verificationsTable=this.getTable("verifications"),requirementsTable=this.getTable("verificationRequirements"),instancesTable=this.getTable("verificationInstances"),stepsTable=this.getTable("verificationSteps"),edgesTable=this.getTable("verificationEdges"),verifierConfigsTable=this.getTable("verificationVerifierConfigs"),userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");if(!verificationsTable||!requirementsTable||!instancesTable)return{success:!1,message:"Verification tables not configured"};let status=await this.getStatus(entity_name,entity_id);if(!status.instance||status.instance.status!=="active")return{success:!1,message:"No active verification instance"};let currentPending=status.pending_requirements.filter((r)=>r.step_order===status.current_step);if(currentPending.length===0)return{success:!1,message:"No pending requirements for current step"};let matchedReq=null;for(let req of currentPending){if(req.verifier_type==="user"&&req.verifier_user_id===user_id){matchedReq=req;break}if(req.verifier_type==="role"&&req.verifier_role&&userRolesTable&&rolesTable){let userRolesCols=userRolesTable,rolesCols=rolesTable;if((await this.db.select({role_name:rolesCols.name}).from(userRolesTable).innerJoin(rolesTable,eq9(userRolesCols.roleId,rolesCols.id)).where(eq9(userRolesCols.userId,user_id))).some((ur)=>ur.role_name===req.verifier_role)){matchedReq=req;break}}}if(!matchedReq)return{success:!1,message:"User is not authorized to verify at this step"};if(matchedReq.require_signature&&!signature_id)return{success:!1,message:"Signature is required for this verification step"};let[newVerification]=await this.db.insert(verificationsTable).values(toCamel2({instance_id:status.instance.id,requirement_id:matchedReq.id,verifier_id:user_id,signature_id:signature_id||null,entity_name,entity_id,step_order:status.current_step,decision,reason:reason||null,diff:diff||null})).returning();if(await this.db.update(requirementsTable).set({status:decision}).where(eq9(this.getCol(requirementsTable,"id"),matchedReq.id)),this.onNotificationTrigger&&status.instance){let stepName=`Step ${status.current_step}`,allSteps=[],allEdges=[];if(stepsTable){allSteps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id));let stepRow=allSteps.find((s)=>s.nodeId===matchedReq.step_node_id);if(stepRow?.name)stepName=stepRow.name}if(edgesTable)allEdges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));let triggerName=decision==="approved"?"on_approved":"on_rejected",ctx={flow_name:status.flow?.name||"",step_name:stepName,step_order:status.current_step,total_steps:status.total_steps,decision},connectedNotifIds=this.getConnectedNotificationNodeIds(matchedReq.step_node_id,allSteps,allEdges);if(connectedNotifIds.length>0)for(let notifNodeId of connectedNotifIds)await this.onNotificationTrigger({trigger:triggerName,flow_id:status.instance.flow_id,entity_name,entity_id,node_id:notifNodeId,verifier_id:user_id,decision,context:ctx});else await this.onNotificationTrigger({trigger:triggerName,flow_id:status.instance.flow_id,entity_name,entity_id,verifier_id:user_id,decision,context:ctx})}if(decision==="rejected"){await this.db.update(instancesTable).set(toCamel2({status:"rejected",completed_at:new Date})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id));let newInstanceId;if(this.config.autoResetOnRejection){this.logger.info(`[Verification] Flow rejected for ${entity_name}:${entity_id}, auto-restarting from step 1`);let restartResult=await this.startFlow({flow_id:status.instance.flow_id,entity_name,entity_id,started_by:status.instance.started_by});if(restartResult.success)newInstanceId=restartResult.instance_id}return{success:!0,message:this.config.autoResetOnRejection?"Verification rejected \u2014 flow restarted from step 1":"Verification rejected",verification:newVerification,flow_completed:!1,new_instance_id:newInstanceId}}let matchedReqId=matchedReq.id,remainingPending=currentPending.filter((r)=>r.id!==matchedReqId);if(remainingPending.length>0)return{success:!0,message:`Step ${status.current_step} partially approved, ${remainingPending.length} verifier(s) remaining`,verification:newVerification,flow_completed:!1};let nextStep=status.current_step+1;if(nextStep>status.total_steps){if(await this.db.update(instancesTable).set(toCamel2({status:"completed",completed_at:new Date})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id)),this.onNotificationTrigger){let completedSteps=[],completedEdges=[];if(stepsTable)completedSteps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id));if(edgesTable)completedEdges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));let lastStepNodeId=matchedReq.step_node_id,completedNotifIds=this.getConnectedNotificationNodeIds(lastStepNodeId,completedSteps,completedEdges),completedCtx={flow_name:status.flow?.name||"",step_order:status.current_step,total_steps:status.total_steps};if(completedNotifIds.length>0)for(let notifNodeId of completedNotifIds)await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:status.instance.flow_id,entity_name,entity_id,node_id:notifNodeId,context:completedCtx});else await this.onNotificationTrigger({trigger:"on_flow_completed",flow_id:status.instance.flow_id,entity_name,entity_id,context:completedCtx})}return{success:!0,message:"Verification flow completed",verification:newVerification,flow_completed:!0}}if(await this.db.update(instancesTable).set(toCamel2({current_step_order:nextStep})).where(eq9(this.getCol(instancesTable,"id"),status.instance.id)),stepsTable&&edgesTable){let steps=await this.db.select().from(stepsTable).where(eq9(this.getCol(stepsTable,"flowId"),status.instance.flow_id)),edges=await this.db.select().from(edgesTable).where(eq9(this.getCol(edgesTable,"flowId"),status.instance.flow_id));await this.materializeRequirementsForStep(status.instance.id,status.instance.flow_id,entity_name,entity_id,nextStep,steps,edges,verifierConfigsTable,requirementsTable,userRolesTable)}return{success:!0,message:`Step ${status.current_step} approved, moving to step ${nextStep}`,verification:newVerification,flow_completed:!1,next_step:nextStep}}async startFlowForEntity(params){let flowsTable=this.getTable("verificationFlows");if(!flowsTable)return{success:!1,message:"Flow table not configured"};let flow=(await this.db.select().from(flowsTable).where(and4(eq9(this.getCol(flowsTable,"entityName"),params.entity_name),eq9(this.getCol(flowsTable,"isDraft"),!1))).limit(1))[0];if(!flow)return{success:!1,message:`No published flow found for entity '${params.entity_name}'`};return this.startFlow({flow_id:flow.id,entity_name:params.entity_name,entity_id:params.entity_id,started_by:params.started_by})}async listEntityStatuses(params){let instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),emptyResult={items:[],total:0,page:1,limit:20};if(!instancesTable||!flowsTable)return emptyResult;let page=params.page||1,limit=params.limit||20,offset=(page-1)*limit,conditions=[eq9(this.getCol(instancesTable,"entityName"),params.entity_name)];if(params.status)conditions.push(eq9(this.getCol(instancesTable,"status"),params.status));let whereClause=conditions.length===1?conditions[0]:and4(...conditions),allInstances=(await this.db.select().from(instancesTable).where(whereClause).orderBy(desc2(this.getCol(instancesTable,"createdAt")))).map((r)=>fromCamel2(r)),total=allInstances.length,paged=allInstances.slice(offset,offset+limit),items=[];for(let inst of paged){let flowId=inst.flow_id,flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),flowId)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0,totalSteps=0;if(stepsTable)totalSteps=(await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),flowId),eq9(this.getCol(stepsTable,"nodeType"),"step")))).length;items.push({instance_id:inst.id,entity_name:inst.entity_name,entity_id:inst.entity_id,flow_id:flowId,flow_name:flow?.name||"Unknown",status:inst.status,current_step_order:inst.current_step_order,total_steps:totalSteps,started_by:inst.started_by,started_at:inst.started_at,completed_at:inst.completed_at})}return{items,total,page,limit}}async getPending(userId){let requirementsTable=this.getTable("verificationRequirements"),instancesTable=this.getTable("verificationInstances"),flowsTable=this.getTable("verificationFlows"),stepsTable=this.getTable("verificationSteps"),userRolesTable=this.getTable("user_roles"),rolesTable=this.getTable("roles");if(this.logger.info(`[Verification.getPending] userId=${userId}, tables: req=${!!requirementsTable} inst=${!!instancesTable} flow=${!!flowsTable} steps=${!!stepsTable} roles=${!!rolesTable} userRoles=${!!userRolesTable}`),!requirementsTable||!instancesTable||!flowsTable)return this.logger.warn("[Verification.getPending] Missing required tables, returning empty"),[];let userRolesCols=userRolesTable,rolesCols=rolesTable,userRoleNames=(userRolesTable&&rolesTable?await this.db.select({role_name:rolesCols.name}).from(userRolesTable).innerJoin(rolesTable,eq9(userRolesCols.roleId,rolesCols.id)).where(eq9(userRolesCols.userId,userId)):[]).map((ur)=>ur.role_name),pendingReqs=(await this.db.select().from(requirementsTable).where(eq9(this.getCol(requirementsTable,"status"),"pending"))).map((r)=>fromCamel2(r));this.logger.info(`[Verification.getPending] Found ${pendingReqs.length} pending requirements, userRoles=${JSON.stringify(userRoleNames)}`);for(let req of pendingReqs)this.logger.info(`[Verification.getPending] Req: verifier_type=${req.verifier_type} verifier_user_id=${req.verifier_user_id} verifier_role=${req.verifier_role} step_order=${req.step_order} entity=${req.entity_name}/${req.entity_id}`);let pendingItems=[];for(let req of pendingReqs){if(!(req.verifier_type==="user"&&req.verifier_user_id===userId||req.verifier_type==="role"&&userRoleNames.includes(req.verifier_role))){this.logger.info(`[Verification.getPending] Skipping req: canVerify=false (type=${req.verifier_type}, reqUserId=${req.verifier_user_id}, loggedInUserId=${userId})`);continue}let instances=await this.db.select().from(instancesTable).where(and4(eq9(this.getCol(instancesTable,"id"),req.instance_id),eq9(this.getCol(instancesTable,"status"),"active"))).limit(1),instance=instances[0]?fromCamel2(instances[0]):void 0;if(!instance)continue;if(instance.current_step_order!==req.step_order)continue;let flows=await this.db.select().from(flowsTable).where(eq9(this.getCol(flowsTable,"id"),instance.flow_id)).limit(1),flow=flows[0]?fromCamel2(flows[0]):void 0;if(!flow)continue;let stepName;if(stepsTable&&req.step_node_id){let stepRow=(await this.db.select().from(stepsTable).where(and4(eq9(this.getCol(stepsTable,"flowId"),instance.flow_id),eq9(this.getCol(stepsTable,"nodeId"),req.step_node_id))).limit(1))[0];if(stepRow?.name)stepName=stepRow.name}pendingItems.push({instance_id:instance.id,entity_name:req.entity_name,entity_id:req.entity_id,flow_name:flow.name,step_order:req.step_order,step_name:stepName,require_signature:req.require_signature,created_at:req.created_at})}return pendingItems}}var init_Verification=__esm(()=>{init_types5()});import*as crypto5 from"crypto";var IYZICO_PATHS,generateAuthString=(apiKey,secretKey,path2,payload,randomKey)=>{let compound=payload?randomKey+path2+payload:randomKey+path2,encryptedData=crypto5.createHmac("sha256",secretKey).update(compound).digest("hex"),authorizationString=`apiKey:${apiKey}&randomKey:${randomKey}&signature:${encryptedData}`;return`IYZWSv2 ${Buffer.from(authorizationString).toString("base64")}`},buildRequest=(config,path2,payload)=>{let body=JSON.stringify(payload),randomKey=Date.now().toString(32),headers=new Headers;return headers.set("Content-Type","application/json"),headers.set("x-iyzi-rnd",randomKey),headers.set("Authorization",generateAuthString(config.apiKey,config.secretKey,path2,body,randomKey)),{url:new URL(`${config.apiUrl}${path2}`).toString(),headers,body}},iyzicoFetch=async(config,path2,payload)=>{let{url,headers,body}=buildRequest(config,path2,payload);try{let json=await(await fetch(url,{method:"POST",headers,body})).json(),isSuccess=json.status==="success";return{success:isSuccess,data:isSuccess?json:null,errorCode:json.errorCode??void 0,errorMessage:json.errorMessage??void 0,rawResponse:json}}catch(error){let message=error instanceof Error?error.message:"Unknown fetch error";return{success:!1,data:null,errorCode:"NETWORK_ERROR",errorMessage:message,rawResponse:{error:message}}}},createIyzicoProvider=(config)=>{let generateConversationId=()=>`nk-${Date.now().toString(16)}`;return{get name(){return"iyzico"},async initialize3DS(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId,price:request.price,paidPrice:request.paidPrice,currency:request.currency,installment:request.installment??1,paymentChannel:request.paymentChannel??"WEB",basketId:request.basketId??Date.now().toString(16),paymentGroup:request.paymentGroup??"PRODUCT",paymentCard:request.paymentCard,buyer:request.buyer,shippingAddress:request.shippingAddress,billingAddress:request.billingAddress,basketItems:request.basketItems,callbackUrl:request.callbackUrl},result=await iyzicoFetch(config,IYZICO_PATHS.INITIALIZE_3DS,payload);return{success:result.success,threeDSHtmlContent:result.data?.threeDSHtmlContent,paymentId:result.data?.paymentId,signature:result.data?.signature,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async complete3DS(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId,paymentId:request.paymentId},result=await iyzicoFetch(config,IYZICO_PATHS.COMPLETE_3DS,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,paidPrice:result.data?.paidPrice,currency:result.data?.currency,installment:result.data?.installment,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,binNumber:result.data?.binNumber,lastFourDigits:result.data?.lastFourDigits,basketId:result.data?.basketId,authCode:result.data?.authCode,signature:result.data?.signature,fraudStatus:result.data?.fraudStatus,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async getPaymentDetail(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),paymentId:request.paymentId,paymentConversationId:request.paymentConversationId},result=await iyzicoFetch(config,IYZICO_PATHS.PAYMENT_DETAIL,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,paidPrice:result.data?.paidPrice,currency:result.data?.currency,basketId:result.data?.basketId,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,lastFourDigits:result.data?.lastFourDigits,binNumber:result.data?.binNumber,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async queryBin(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),binNumber:request.binNumber.slice(0,6)};if(request.price!==void 0)payload.price=request.price;let result=await iyzicoFetch(config,IYZICO_PATHS.BIN_CHECK,payload);return{success:result.success,binNumber:result.data?.binNumber,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,bankName:result.data?.bankName,bankCode:result.data?.bankCode,commercial:result.data?.commercial,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async saveCard(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),card:request.card,email:request.email,externalId:request.externalId},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_SAVE,payload);return{success:result.success,cardUserKey:result.data?.cardUserKey,cardToken:result.data?.cardToken,cardAlias:result.data?.cardAlias,binNumber:result.data?.binNumber,lastFourDigits:result.data?.lastFourDigits,cardType:result.data?.cardType,cardAssociation:result.data?.cardAssociation,cardFamily:result.data?.cardFamily,cardBankName:result.data?.cardBankName,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async listCards(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),cardUserKey:request.cardUserKey},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_LIST,payload),cards=(result.data?.cardDetails??[]).map((cd)=>({cardToken:cd.cardToken,cardAlias:cd.cardAlias,binNumber:cd.binNumber,lastFourDigits:cd.lastFourDigits,cardType:cd.cardType,cardAssociation:cd.cardAssociation,cardFamily:cd.cardFamily,cardBankName:cd.cardBankName,cardBankCode:cd.cardBankCode}));return{success:result.success,cardUserKey:result.data?.cardUserKey,cards,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async deleteCard(request){let payload={locale:request.locale??"tr",conversationId:generateConversationId(),cardUserKey:request.cardUserKey,cardToken:request.cardToken},result=await iyzicoFetch(config,IYZICO_PATHS.CARD_DELETE,payload);return{success:result.success,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async refund(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),paymentTransactionId:request.paymentTransactionId,price:request.price,currency:request.currency??"TRY"};if(request.ip)payload.ip=request.ip;let result=await iyzicoFetch(config,IYZICO_PATHS.REFUND,payload);return{success:result.success,paymentId:result.data?.paymentId,price:result.data?.price,currency:result.data?.currency,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},parseCallback(formData){return{success:formData.mdStatus==="1",paymentId:formData.paymentId??"",conversationId:formData.conversationId??"",mdStatus:formData.mdStatus??"",rawData:formData}},async registerSubMerchant(request){let typeMap={personal:"PERSONAL",private_company:"PRIVATE_COMPANY",limited_or_joint_stock_company:"LIMITED_OR_JOINT_STOCK_COMPANY"},payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantExternalId:request.subMerchantExternalId,subMerchantType:typeMap[request.subMerchantType]??"PERSONAL",name:request.name,email:request.email,gsmNumber:request.gsmNumber,address:request.address,iban:request.iban,contactName:request.contactName,contactSurname:request.contactSurname,identityNumber:request.identityNumber,currency:request.currency??"TRY"};if(request.subMerchantType==="private_company")payload.taxOffice=request.taxOffice,payload.legalCompanyTitle=request.legalCompanyTitle;if(request.subMerchantType==="limited_or_joint_stock_company")payload.taxOffice=request.taxOffice,payload.taxNumber=request.taxNumber,payload.legalCompanyTitle=request.legalCompanyTitle;let result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_CREATE,payload);return{success:result.success,subMerchantKey:result.data?.subMerchantKey,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async updateSubMerchant(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantKey:request.subMerchantKey};if(request.name)payload.name=request.name;if(request.email)payload.email=request.email;if(request.gsmNumber)payload.gsmNumber=request.gsmNumber;if(request.address)payload.address=request.address;if(request.iban)payload.iban=request.iban;if(request.contactName)payload.contactName=request.contactName;if(request.contactSurname)payload.contactSurname=request.contactSurname;if(request.identityNumber)payload.identityNumber=request.identityNumber;if(request.taxOffice)payload.taxOffice=request.taxOffice;if(request.taxNumber)payload.taxNumber=request.taxNumber;if(request.legalCompanyTitle)payload.legalCompanyTitle=request.legalCompanyTitle;if(request.currency)payload.currency=request.currency;let result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_UPDATE,payload);return{success:result.success,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async getSubMerchant(request){let payload={locale:request.locale??"tr",conversationId:request.conversationId??generateConversationId(),subMerchantExternalId:request.subMerchantExternalId},result=await iyzicoFetch(config,IYZICO_PATHS.SUB_MERCHANT_DETAIL,payload);return{success:result.success,subMerchantKey:result.data?.subMerchantKey,name:result.data?.name,email:result.data?.email,gsmNumber:result.data?.gsmNumber,address:result.data?.address,iban:result.data?.iban,subMerchantType:result.data?.subMerchantType,currency:result.data?.currency,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async approveSplit(request){let payload={locale:request.locale??"tr",paymentTransactionId:request.paymentTransactionId},result=await iyzicoFetch(config,IYZICO_PATHS.APPROVAL,payload);return{success:result.success,paymentTransactionId:result.data?.paymentTransactionId,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async disapproveSplit(request){let payload={locale:request.locale??"tr",paymentTransactionId:request.paymentTransactionId},result=await iyzicoFetch(config,IYZICO_PATHS.DISAPPROVAL,payload);return{success:result.success,paymentTransactionId:result.data?.paymentTransactionId,errorCode:result.errorCode,errorMessage:result.errorMessage,rawResponse:result.rawResponse}},async createProduct(request){let localId=`iyzico-prod-${Date.now().toString(36)}`;return{success:!0,providerProductId:localId,name:request.name,rawResponse:{local:!0,id:localId}}},async updateProduct(request){return{success:!0,providerProductId:request.providerProductId,rawResponse:{local:!0,updated:request.providerProductId}}},async getProduct(request){return{success:!0,providerProductId:request.providerProductId,rawResponse:{local:!0,message:"Product data is stored locally for iyzico"}}},async listProducts(_request){return{success:!0,products:[],hasMore:!1,rawResponse:{local:!0,message:"Products are stored locally for iyzico"}}},async archiveProduct(request){return{success:!0,rawResponse:{local:!0,archived:request.providerProductId}}},async createPrice(request){let localId=`iyzico-price-${Date.now().toString(36)}`;return{success:!0,providerPriceId:localId,rawResponse:{local:!0,id:localId,product:request.providerProductId}}},async updatePrice(request){return{success:!0,providerPriceId:request.providerPriceId,rawResponse:{local:!0,updated:request.providerPriceId}}},async getPrice(request){return{success:!0,providerPriceId:request.providerPriceId,rawResponse:{local:!0,message:"Price data is stored locally for iyzico"}}},async listPrices(_request){return{success:!0,prices:[],hasMore:!1,rawResponse:{local:!0,message:"Prices are stored locally for iyzico"}}},async archivePrice(request){return{success:!0,rawResponse:{local:!0,archived:request.providerPriceId}}},async createCustomer(request){return{success:!0,providerCustomerId:`local_cus_${Date.now()}`,email:request.email,rawResponse:{local:!0,message:"Customer stored locally for iyzico"}}},async updateCustomer(request){return{success:!0,providerCustomerId:request.providerCustomerId,rawResponse:{local:!0,message:"Customer updated locally for iyzico"}}},async getCustomer(request){return{success:!0,providerCustomerId:request.providerCustomerId,rawResponse:{local:!0,message:"Customer data is stored locally for iyzico"}}},async listCustomers(_request){return{success:!0,customers:[],hasMore:!1,rawResponse:{local:!0,message:"Customers are stored locally for iyzico"}}},async deleteCustomer(_request){return{success:!0,rawResponse:{local:!0,message:"Customer deleted locally for iyzico"}}},async createSubscription(_request){return{success:!0,providerSubscriptionId:`local_sub_${Date.now()}`,status:"active",rawResponse:{local:!0,message:"Subscription stored locally for iyzico"}}},async updateSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,status:"active",rawResponse:{local:!0,message:"Subscription updated locally for iyzico"}}},async cancelSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,status:"canceled",rawResponse:{local:!0,message:"Subscription canceled locally for iyzico"}}},async getSubscription(request){return{success:!0,providerSubscriptionId:request.providerSubscriptionId,rawResponse:{local:!0,message:"Subscription data is stored locally for iyzico"}}},async listSubscriptions(_request){return{success:!0,subscriptions:[],hasMore:!1,rawResponse:{local:!0,message:"Subscriptions are stored locally for iyzico"}}},async reportUsage(request){return{success:!0,usageRecordId:`local_ur_${Date.now()}`,quantity:request.quantity,timestamp:request.timestamp??Math.floor(Date.now()/1000),rawResponse:{local:!0,message:"Usage recorded locally for iyzico"}}},async listUsageRecordSummaries(_request){return{success:!0,summaries:[],hasMore:!1,rawResponse:{local:!0,message:"Usage summaries are stored locally for iyzico"}}},async createInvoice(_request){return{success:!0,providerInvoiceId:`local_inv_${Date.now()}`,status:"draft",rawResponse:{local:!0,message:"Invoice stored locally for iyzico"}}},async finalizeInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,status:"open",rawResponse:{local:!0,message:"Invoice finalized locally for iyzico"}}},async sendInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice send is a no-op for iyzico"}}},async voidInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice voided locally for iyzico"}}},async payInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,status:"paid",rawResponse:{local:!0,message:"Invoice payment is a no-op for iyzico"}}},async getInvoice(request){return{success:!0,providerInvoiceId:request.providerInvoiceId,rawResponse:{local:!0,message:"Invoice data is stored locally for iyzico"}}},async listInvoices(_request){return{success:!0,invoices:[],hasMore:!1,rawResponse:{local:!0,message:"Invoices are stored locally for iyzico"}}},async getBalance(){return{success:!0,available:[],pending:[],rawResponse:{local:!0,message:"Balance is not tracked by iyzico provider"}}},async createPayout(_request){return{success:!0,providerPayoutId:`local_po_${Date.now()}`,status:"pending",rawResponse:{local:!0,message:"Payout created locally for iyzico"}}},async getPayout(request){return{success:!0,providerPayoutId:request.providerPayoutId,rawResponse:{local:!0,message:"Payout data is stored locally for iyzico"}}},async cancelPayout(request){return{success:!0,providerPayoutId:request.providerPayoutId,status:"canceled",rawResponse:{local:!0,message:"Payout cancelled locally for iyzico"}}},async listPayouts(_request){return{success:!0,payouts:[],hasMore:!1,rawResponse:{local:!0,message:"Payouts are stored locally for iyzico"}}},async createTransfer(_request){return{success:!0,providerTransferId:`local_tr_${Date.now()}`,rawResponse:{local:!0,message:"Transfer created locally for iyzico"}}},async listTransfers(_request){return{success:!0,transfers:[],hasMore:!1,rawResponse:{local:!0,message:"Transfers are stored locally for iyzico"}}}}};var init_IyzicoProvider=__esm(()=>{IYZICO_PATHS={INITIALIZE_3DS:"/payment/3dsecure/initialize",COMPLETE_3DS:"/payment/3dsecure/auth",PAYMENT_AUTH:"/payment/auth",PAYMENT_DETAIL:"/payment/detail",BIN_CHECK:"/payment/bin/check",CARD_SAVE:"/cardstorage/card",CARD_LIST:"/cardstorage/cards",CARD_DELETE:"/cardstorage/card/delete",REFUND:"/payment/refund",SUB_MERCHANT_CREATE:"/onboarding/submerchant",SUB_MERCHANT_UPDATE:"/onboarding/submerchant",SUB_MERCHANT_DETAIL:"/onboarding/submerchant/detail",APPROVAL:"/payment/iyzipos/item/approve",DISAPPROVAL:"/payment/iyzipos/item/disapprove"}});var loadStripe=(config)=>{try{let StripeModule=__require("stripe");return new(StripeModule.default??StripeModule)(config.secretKey,{maxNetworkRetries:config.maxNetworkRetries??2,timeout:config.timeout??30000,...config.apiVersion?{apiVersion:config.apiVersion}:{}})}catch(error){return console.error("[Payment:Stripe] Failed to load stripe package. Install it: bun add stripe",error instanceof Error?error.message:error),null}},createStripeProvider=(config)=>{let stripe=loadStripe(config);if(!stripe)return null;let providerName="stripe";return{get name(){return providerName},async initialize3DS(request){try{let params={amount:Math.round(Number(request.paidPrice)*100),currency:request.currency.toLowerCase(),payment_method_types:["card"],description:`Order ${request.conversationId}`,metadata:{conversationId:request.conversationId,basketId:request.basketId??"",buyerEmail:request.buyer.email,buyerId:request.buyer.id}};if("cardToken"in request.paymentCard&&request.paymentCard.cardToken)params.payment_method=request.paymentCard.cardToken,params.confirm=!0,params.return_url=request.callbackUrl;let paymentIntent=await stripe.paymentIntents.create(params),clientSecret=paymentIntent.client_secret,piId=paymentIntent.id,status=paymentIntent.status;return{success:!0,paymentId:piId,threeDSHtmlContent:clientSecret,signature:status,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment initialization failed",rawResponse:{error:err.message}}}},async complete3DS(request){try{let paymentIntent=await stripe.paymentIntents.retrieve(request.paymentId,{expand:["payment_method"]}),status=paymentIntent.status,isSuccess=status==="succeeded",amountReceived=paymentIntent.amount_received??0,card=paymentIntent.payment_method?.card;return{success:isSuccess,paymentId:paymentIntent.id,price:amountReceived/100,paidPrice:amountReceived/100,currency:paymentIntent.currency?.toUpperCase(),cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,cardFamily:card?.funding??void 0,lastFourDigits:card?.last4??void 0,authCode:status,errorCode:isSuccess?void 0:"PAYMENT_NOT_SUCCEEDED",errorMessage:isSuccess?void 0:`Payment status: ${status}`,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment completion failed",rawResponse:{error:err.message}}}},async getPaymentDetail(request){try{let paymentIntent=await stripe.paymentIntents.retrieve(request.paymentId,{expand:["payment_method"]}),amountReceived=paymentIntent.amount_received??paymentIntent.amount??0,card=paymentIntent.payment_method?.card;return{success:!0,paymentId:paymentIntent.id,price:amountReceived/100,paidPrice:amountReceived/100,currency:paymentIntent.currency?.toUpperCase(),cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,lastFourDigits:card?.last4??void 0,binNumber:void 0,rawResponse:paymentIntent}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Payment detail query failed",rawResponse:{error:err.message}}}},async queryBin(_request){return{success:!1,errorCode:"NOT_SUPPORTED",errorMessage:"BIN query is not supported by Stripe. Card info is available after payment method creation.",rawResponse:{}}},async saveCard(request){try{let customer=await stripe.customers.create({email:request.email,metadata:{externalId:request.externalId??""}}),paymentMethod=await stripe.paymentMethods.create({type:"card",card:{number:request.card.cardNumber,exp_month:Number(request.card.expireMonth),exp_year:Number(request.card.expireYear)}});await stripe.paymentMethods.attach(paymentMethod.id,{customer:customer.id});let card=paymentMethod.card;return{success:!0,cardUserKey:customer.id,cardToken:paymentMethod.id,cardAlias:request.card.cardAlias,binNumber:void 0,lastFourDigits:card?.last4??void 0,cardType:card?.brand??void 0,cardAssociation:card?.brand??void 0,cardFamily:card?.funding??void 0,cardBankName:void 0,rawResponse:{customer,paymentMethod}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to save card",rawResponse:{error:err.message}}}},async listCards(request){try{let response=await stripe.paymentMethods.list({customer:request.cardUserKey,type:"card"}),cards=response.data.map((pm)=>{let card=pm.card;return{cardToken:pm.id,cardAlias:pm.metadata?.alias??"",binNumber:"",lastFourDigits:card?.last4??"",cardType:card?.brand??"",cardAssociation:card?.brand??"",cardFamily:card?.funding??"",cardBankName:"",cardBankCode:0}});return{success:!0,cardUserKey:request.cardUserKey,cards,rawResponse:response}}catch(error){let err=error;return{success:!1,cards:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list cards",rawResponse:{error:err.message}}}},async deleteCard(request){try{return await stripe.paymentMethods.detach(request.cardToken),{success:!0,rawResponse:{detached:request.cardToken}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to delete card",rawResponse:{error:err.message}}}},async refund(request){try{let amountInCents=Math.round(Number(request.price)*100),refund=await stripe.refunds.create({payment_intent:request.paymentTransactionId,amount:amountInCents});return{success:refund.status==="succeeded",paymentId:refund.payment_intent,price:amountInCents/100,currency:refund.currency?.toUpperCase(),errorCode:refund.status!=="succeeded"?"REFUND_FAILED":void 0,errorMessage:refund.status!=="succeeded"?`Refund status: ${refund.status}`:void 0,rawResponse:refund}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Refund failed",rawResponse:{error:err.message}}}},parseCallback(formData){let paymentIntent=formData.payment_intent??formData.paymentId??"",redirectStatus=formData.redirect_status??"";return{success:redirectStatus==="succeeded",paymentId:paymentIntent,conversationId:formData.conversationId??"",mdStatus:redirectStatus,rawData:formData}},async registerSubMerchant(request){try{let account=await stripe.accounts.create({type:"express",country:request.currency==="TRY"?"TR":void 0,email:request.email,business_type:request.subMerchantType==="personal"?"individual":"company",metadata:{externalId:request.subMerchantExternalId,name:request.name,contactName:request.contactName??"",contactSurname:request.contactSurname??""},capabilities:{transfers:{requested:!0}}});return{success:!0,subMerchantKey:account.id,rawResponse:account}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create connected account",rawResponse:{error:err.message}}}},async updateSubMerchant(request){try{let params={metadata:{}},meta=params.metadata;if(request.name)meta.name=request.name;if(request.email)params.email=request.email;if(request.contactName)meta.contactName=request.contactName;if(request.contactSurname)meta.contactSurname=request.contactSurname;return await stripe.accounts.update(request.subMerchantKey,params),{success:!0,rawResponse:{updated:request.subMerchantKey}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update connected account",rawResponse:{error:err.message}}}},async getSubMerchant(request){try{let account=await stripe.accounts.retrieve(request.subMerchantExternalId),meta=account.metadata??{};return{success:!0,subMerchantKey:account.id,name:meta.name,email:account.email,subMerchantType:account.business_type==="individual"?"personal":"company",currency:account.default_currency?.toUpperCase(),rawResponse:account}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to retrieve connected account",rawResponse:{error:err.message}}}},async approveSplit(request){return{success:!0,paymentTransactionId:request.paymentTransactionId,rawResponse:{message:"Stripe transfers are automatic; no manual approval needed."}}},async disapproveSplit(request){try{let reversal=await stripe.transfers.createReversal(request.paymentTransactionId);return{success:!0,paymentTransactionId:reversal.id,rawResponse:reversal}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to reverse transfer",rawResponse:{error:err.message}}}},async createProduct(request){try{let params={name:request.name};if(request.description)params.description=request.description;if(request.type)params.type=request.type;if(request.images)params.images=request.images;if(request.unitLabel)params.unit_label=request.unitLabel;if(request.url)params.url=request.url;if(request.metadata)params.metadata=request.metadata;let product=await stripe.products.create(params);return{success:!0,providerProductId:product.id,name:product.name,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create product",rawResponse:{error:err.message}}}},async updateProduct(request){try{let params={};if(request.name)params.name=request.name;if(request.description!==void 0)params.description=request.description;if(request.images)params.images=request.images;if(request.unitLabel!==void 0)params.unit_label=request.unitLabel;if(request.url!==void 0)params.url=request.url;if(request.active!==void 0)params.active=request.active;if(request.metadata)params.metadata=request.metadata;let product=await stripe.products.update(request.providerProductId,params);return{success:!0,providerProductId:product.id,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update product",rawResponse:{error:err.message}}}},async getProduct(request){try{let product=await stripe.products.retrieve(request.providerProductId);return{success:!0,providerProductId:product.id,name:product.name,description:product.description,type:product.type,active:product.active,images:product.images,unitLabel:product.unit_label,url:product.url,metadata:product.metadata,rawResponse:product}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get product",rawResponse:{error:err.message}}}},async listProducts(request){try{let params={};if(request.active!==void 0)params.active=request.active;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.products.list(params);return{success:!0,products:response.data.map((p)=>({providerProductId:p.id,name:p.name,description:p.description,type:p.type,active:p.active,images:p.images,unitLabel:p.unit_label,metadata:p.metadata})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,products:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list products",rawResponse:{error:err.message}}}},async archiveProduct(request){try{return await stripe.products.update(request.providerProductId,{active:!1}),{success:!0,rawResponse:{archived:request.providerProductId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to archive product",rawResponse:{error:err.message}}}},async createPrice(request){try{let params={product:request.providerProductId,currency:request.currency.toLowerCase(),unit_amount:request.unitAmount};if(request.nickname)params.nickname=request.nickname;if(request.billingScheme)params.billing_scheme=request.billingScheme;if(request.unitAmountDecimal)params.unit_amount_decimal=request.unitAmountDecimal;if(request.metadata)params.metadata=request.metadata;if(request.recurring)params.recurring={interval:request.recurring.interval,...request.recurring.intervalCount?{interval_count:request.recurring.intervalCount}:{},...request.recurring.usageType?{usage_type:request.recurring.usageType}:{},...request.recurring.aggregateUsage?{aggregate_usage:request.recurring.aggregateUsage}:{}};if(request.transformQuantity)params.transform_quantity={divide_by:request.transformQuantity.divideBy,round:request.transformQuantity.round};let price=await stripe.prices.create(params);return{success:!0,providerPriceId:price.id,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create price",rawResponse:{error:err.message}}}},async updatePrice(request){try{let params={};if(request.nickname!==void 0)params.nickname=request.nickname;if(request.active!==void 0)params.active=request.active;if(request.metadata)params.metadata=request.metadata;let price=await stripe.prices.update(request.providerPriceId,params);return{success:!0,providerPriceId:price.id,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update price",rawResponse:{error:err.message}}}},async getPrice(request){try{let price=await stripe.prices.retrieve(request.providerPriceId),rec=price.recurring;return{success:!0,providerPriceId:price.id,providerProductId:price.product,currency:price.currency?.toUpperCase(),unitAmount:price.unit_amount,type:price.type,billingScheme:price.billing_scheme,nickname:price.nickname,active:price.active,recurring:rec?{interval:rec.interval,intervalCount:rec.interval_count??1,usageType:rec.usage_type}:void 0,metadata:price.metadata,rawResponse:price}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get price",rawResponse:{error:err.message}}}},async listPrices(request){try{let params={};if(request.providerProductId)params.product=request.providerProductId;if(request.active!==void 0)params.active=request.active;if(request.type)params.type=request.type;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.prices.list(params);return{success:!0,prices:response.data.map((p)=>{let rec=p.recurring;return{providerPriceId:p.id,providerProductId:p.product,currency:p.currency?.toUpperCase(),unitAmount:p.unit_amount,type:p.type,billingScheme:p.billing_scheme,nickname:p.nickname,active:p.active,recurring:rec?{interval:rec.interval,intervalCount:rec.interval_count??1,usageType:rec.usage_type}:void 0,metadata:p.metadata}}),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,prices:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list prices",rawResponse:{error:err.message}}}},async archivePrice(request){try{return await stripe.prices.update(request.providerPriceId,{active:!1}),{success:!0,rawResponse:{archived:request.providerPriceId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to archive price",rawResponse:{error:err.message}}}},async createCustomer(request){try{let params={email:request.email};if(request.name)params.name=request.name;if(request.phone)params.phone=request.phone;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.address)params.address={line1:request.address.line1,line2:request.address.line2,city:request.address.city,state:request.address.state,postal_code:request.address.postalCode,country:request.address.country};let customer=await stripe.customers.create(params);if(request.taxId)try{await stripe.taxIds?.create({customer:customer.id,type:request.taxId.type,value:request.taxId.value})}catch(_){}return{success:!0,providerCustomerId:customer.id,email:customer.email,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create customer",rawResponse:{error:err.message}}}},async updateCustomer(request){try{let params={};if(request.email)params.email=request.email;if(request.name!==void 0)params.name=request.name;if(request.phone!==void 0)params.phone=request.phone;if(request.description!==void 0)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.address)params.address={line1:request.address.line1,line2:request.address.line2,city:request.address.city,state:request.address.state,postal_code:request.address.postalCode,country:request.address.country};let customer=await stripe.customers.update(request.providerCustomerId,params);return{success:!0,providerCustomerId:customer.id,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update customer",rawResponse:{error:err.message}}}},async getCustomer(request){try{let customer=await stripe.customers.retrieve(request.providerCustomerId);return{success:!0,providerCustomerId:customer.id,email:customer.email,name:customer.name,phone:customer.phone,description:customer.description,metadata:customer.metadata,rawResponse:customer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get customer",rawResponse:{error:err.message}}}},async listCustomers(request){try{let params={};if(request.email)params.email=request.email;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.customers.list(params);return{success:!0,customers:response.data.map((c)=>({providerCustomerId:c.id,email:c.email,name:c.name,phone:c.phone})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,customers:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list customers",rawResponse:{error:err.message}}}},async deleteCustomer(request){try{return await stripe.customers.del(request.providerCustomerId),{success:!0,rawResponse:{deleted:request.providerCustomerId}}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to delete customer",rawResponse:{error:err.message}}}},async createSubscription(request){try{let params={customer:request.providerCustomerId,items:request.items.map((i)=>({price:i.providerPriceId,...i.quantity!==void 0?{quantity:i.quantity}:{}}))};if(request.trialPeriodDays)params.trial_period_days=request.trialPeriodDays;if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.cancelAtPeriodEnd!==void 0)params.cancel_at_period_end=request.cancelAtPeriodEnd;if(request.metadata)params.metadata=request.metadata;if(request.defaultPaymentMethod)params.default_payment_method=request.defaultPaymentMethod;params.payment_behavior="default_incomplete",params.payment_settings={save_default_payment_method:"on_subscription"},params.expand=["latest_invoice.payment_intent"];let sub=await stripe.subscriptions.create(params),pi=sub.latest_invoice?.payment_intent;return{success:!0,providerSubscriptionId:sub.id,status:sub.status,currentPeriodStart:sub.current_period_start?new Date(sub.current_period_start*1000).toISOString():void 0,currentPeriodEnd:sub.current_period_end?new Date(sub.current_period_end*1000).toISOString():void 0,clientSecret:pi?.client_secret,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create subscription",rawResponse:{error:err.message}}}},async updateSubscription(request){try{let params={};if(request.items)params.items=request.items.map((i)=>({...i.id?{id:i.id}:{},price:i.providerPriceId,...i.quantity!==void 0?{quantity:i.quantity}:{}}));if(request.cancelAtPeriodEnd!==void 0)params.cancel_at_period_end=request.cancelAtPeriodEnd;if(request.trialEnd!==void 0)params.trial_end=request.trialEnd;if(request.metadata)params.metadata=request.metadata;if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.defaultPaymentMethod)params.default_payment_method=request.defaultPaymentMethod;if(request.prorationBehavior)params.proration_behavior=request.prorationBehavior;let sub=await stripe.subscriptions.update(request.providerSubscriptionId,params);return{success:!0,providerSubscriptionId:sub.id,status:sub.status,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to update subscription",rawResponse:{error:err.message}}}},async cancelSubscription(request){try{if(request.cancelAtPeriodEnd){let sub2=await stripe.subscriptions.update(request.providerSubscriptionId,{cancel_at_period_end:!0});return{success:!0,providerSubscriptionId:sub2.id,status:sub2.status,rawResponse:sub2}}let params={};if(request.invoiceNow)params.invoice_now=request.invoiceNow;if(request.prorate)params.prorate=request.prorate;let sub=await stripe.subscriptions.cancel(request.providerSubscriptionId,params);return{success:!0,providerSubscriptionId:sub.id,status:sub.status,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to cancel subscription",rawResponse:{error:err.message}}}},async getSubscription(request){try{let sub=await stripe.subscriptions.retrieve(request.providerSubscriptionId),itemsData=sub.items?.data??[];return{success:!0,providerSubscriptionId:sub.id,providerCustomerId:sub.customer,status:sub.status,currentPeriodStart:sub.current_period_start?new Date(sub.current_period_start*1000).toISOString():void 0,currentPeriodEnd:sub.current_period_end?new Date(sub.current_period_end*1000).toISOString():void 0,cancelAtPeriodEnd:sub.cancel_at_period_end,canceledAt:sub.canceled_at?new Date(sub.canceled_at*1000).toISOString():void 0,trialStart:sub.trial_start?new Date(sub.trial_start*1000).toISOString():void 0,trialEnd:sub.trial_end?new Date(sub.trial_end*1000).toISOString():void 0,items:itemsData.map((i)=>({id:i.id,providerPriceId:i.price?.id??i.price,quantity:i.quantity??1})),metadata:sub.metadata,rawResponse:sub}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get subscription",rawResponse:{error:err.message}}}},async listSubscriptions(request){try{let params={};if(request.providerCustomerId)params.customer=request.providerCustomerId;if(request.status)params.status=request.status;if(request.providerPriceId)params.price=request.providerPriceId;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.subscriptions.list(params);return{success:!0,subscriptions:response.data.map((s)=>({providerSubscriptionId:s.id,providerCustomerId:s.customer,status:s.status,currentPeriodStart:s.current_period_start?new Date(s.current_period_start*1000).toISOString():void 0,currentPeriodEnd:s.current_period_end?new Date(s.current_period_end*1000).toISOString():void 0,cancelAtPeriodEnd:s.cancel_at_period_end})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,subscriptions:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list subscriptions",rawResponse:{error:err.message}}}},async reportUsage(request){try{let params={quantity:request.quantity,action:request.action??"increment"};if(request.timestamp)params.timestamp=request.timestamp;let record=await stripe.subscriptionItems.usageRecords.create(request.subscriptionItemId,params);return{success:!0,usageRecordId:record.id,quantity:record.quantity,timestamp:record.timestamp,rawResponse:record}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to report usage",rawResponse:{error:err.message}}}},async listUsageRecordSummaries(request){try{let params={};if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.subscriptionItems.usageRecordSummaries.list(request.subscriptionItemId,params);return{success:!0,summaries:response.data.map((s)=>({id:s.id,totalUsage:s.total_usage,period:s.period,subscriptionItem:s.subscription_item})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,summaries:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list usage summaries",rawResponse:{error:err.message}}}},async createInvoice(request){try{let params={customer:request.providerCustomerId};if(request.collectionMethod)params.collection_method=request.collectionMethod;if(request.daysUntilDue)params.days_until_due=request.daysUntilDue;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.autoAdvance!==void 0)params.auto_advance=request.autoAdvance;let invoice=await stripe.invoices.create(params);if(request.items?.length)for(let item of request.items){let lineParams={customer:request.providerCustomerId,invoice:invoice.id};if(item.providerPriceId)lineParams.price=item.providerPriceId;if(item.quantity)lineParams.quantity=item.quantity;if(item.unitAmount!==void 0)lineParams.unit_amount=item.unitAmount;if(item.currency)lineParams.currency=item.currency;if(item.description)lineParams.description=item.description;await stripe.invoiceItems.create(lineParams)}return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create invoice",rawResponse:{error:err.message}}}},async finalizeInvoice(request){try{let params={};if(request.autoAdvance!==void 0)params.auto_advance=request.autoAdvance;let invoice=await stripe.invoices.finalizeInvoice(request.providerInvoiceId,params);return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to finalize invoice",rawResponse:{error:err.message}}}},async sendInvoice(request){try{let invoice=await stripe.invoices.sendInvoice(request.providerInvoiceId);return{success:!0,providerInvoiceId:invoice.id,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to send invoice",rawResponse:{error:err.message}}}},async voidInvoice(request){try{let invoice=await stripe.invoices.voidInvoice(request.providerInvoiceId);return{success:!0,providerInvoiceId:invoice.id,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to void invoice",rawResponse:{error:err.message}}}},async payInvoice(request){try{let params={};if(request.paymentMethod)params.payment_method=request.paymentMethod;let invoice=await stripe.invoices.pay(request.providerInvoiceId,params);return{success:!0,providerInvoiceId:invoice.id,status:invoice.status,amountPaid:invoice.amount_paid,amountDue:invoice.amount_due,rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to pay invoice",rawResponse:{error:err.message}}}},async getInvoice(request){try{let invoice=await stripe.invoices.retrieve(request.providerInvoiceId),linesData=invoice.lines?.data??[];return{success:!0,providerInvoiceId:invoice.id,providerCustomerId:invoice.customer,providerSubscriptionId:invoice.subscription,status:invoice.status,amountDue:invoice.amount_due,amountPaid:invoice.amount_paid,amountRemaining:invoice.amount_remaining,currency:invoice.currency?.toUpperCase(),description:invoice.description,hostedInvoiceUrl:invoice.hosted_invoice_url,invoicePdf:invoice.invoice_pdf,dueDate:invoice.due_date?new Date(invoice.due_date*1000).toISOString():void 0,periodStart:invoice.period_start?new Date(invoice.period_start*1000).toISOString():void 0,periodEnd:invoice.period_end?new Date(invoice.period_end*1000).toISOString():void 0,metadata:invoice.metadata,lines:linesData.map((l)=>({id:l.id,description:l.description,amount:l.amount,currency:l.currency?.toUpperCase(),quantity:l.quantity,providerPriceId:l.price?.id})),rawResponse:invoice}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get invoice",rawResponse:{error:err.message}}}},async listInvoices(request){try{let params={};if(request.providerCustomerId)params.customer=request.providerCustomerId;if(request.providerSubscriptionId)params.subscription=request.providerSubscriptionId;if(request.status)params.status=request.status;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.invoices.list(params);return{success:!0,invoices:response.data.map((inv)=>({providerInvoiceId:inv.id,providerCustomerId:inv.customer,status:inv.status,amountDue:inv.amount_due,amountPaid:inv.amount_paid,currency:inv.currency?.toUpperCase(),dueDate:inv.due_date?new Date(inv.due_date*1000).toISOString():void 0,hostedInvoiceUrl:inv.hosted_invoice_url})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,invoices:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list invoices",rawResponse:{error:err.message}}}},async getBalance(){try{let bal=await stripe.balance.retrieve(),mapAmounts=(arr)=>(arr??[]).map((a)=>({amount:a.amount,currency:a.currency?.toUpperCase()}));return{success:!0,available:mapAmounts(bal.available),pending:mapAmounts(bal.pending),connectReserved:mapAmounts(bal.connect_reserved),rawResponse:bal}}catch(error){let err=error;return{success:!1,available:[],pending:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get balance",rawResponse:{error:err.message}}}},async createPayout(request){try{let params={amount:request.amount,currency:request.currency.toLowerCase()};if(request.destination)params.destination=request.destination;if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.method)params.method=request.method;if(request.sourceType)params.source_type=request.sourceType;if(request.statementDescriptor)params.statement_descriptor=request.statementDescriptor;let payout=await stripe.payouts.create(params);return{success:!0,providerPayoutId:payout.id,amount:payout.amount,currency:payout.currency?.toUpperCase(),status:payout.status,arrivalDate:payout.arrival_date?new Date(payout.arrival_date*1000).toISOString():void 0,method:payout.method,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create payout",rawResponse:{error:err.message}}}},async getPayout(request){try{let payout=await stripe.payouts.retrieve(request.providerPayoutId);return{success:!0,providerPayoutId:payout.id,amount:payout.amount,currency:payout.currency?.toUpperCase(),status:payout.status,arrivalDate:payout.arrival_date?new Date(payout.arrival_date*1000).toISOString():void 0,method:payout.method,description:payout.description,destination:payout.destination,metadata:payout.metadata,failureCode:payout.failure_code,failureMessage:payout.failure_message,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to get payout",rawResponse:{error:err.message}}}},async cancelPayout(request){try{let payout=await stripe.payouts.cancel(request.providerPayoutId);return{success:!0,providerPayoutId:payout.id,status:payout.status,rawResponse:payout}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to cancel payout",rawResponse:{error:err.message}}}},async listPayouts(request){try{let params={};if(request.status)params.status=request.status;if(request.destination)params.destination=request.destination;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;if(request.arrivalDateGte||request.arrivalDateLte){let arrival={};if(request.arrivalDateGte)arrival.gte=request.arrivalDateGte;if(request.arrivalDateLte)arrival.lte=request.arrivalDateLte;params.arrival_date=arrival}let response=await stripe.payouts.list(params);return{success:!0,payouts:response.data.map((p)=>({providerPayoutId:p.id,amount:p.amount,currency:p.currency?.toUpperCase(),status:p.status,arrivalDate:p.arrival_date?new Date(p.arrival_date*1000).toISOString():void 0,method:p.method,description:p.description})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,payouts:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list payouts",rawResponse:{error:err.message}}}},async createTransfer(request){try{let params={amount:request.amount,currency:request.currency.toLowerCase(),destination:request.destination};if(request.description)params.description=request.description;if(request.metadata)params.metadata=request.metadata;if(request.sourceTransaction)params.source_transaction=request.sourceTransaction;if(request.transferGroup)params.transfer_group=request.transferGroup;let transfer=await stripe.transfers.create(params);return{success:!0,providerTransferId:transfer.id,amount:transfer.amount,currency:transfer.currency?.toUpperCase(),destination:transfer.destination,rawResponse:transfer}}catch(error){let err=error;return{success:!1,errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to create transfer",rawResponse:{error:err.message}}}},async listTransfers(request){try{let params={};if(request.destination)params.destination=request.destination;if(request.transferGroup)params.transfer_group=request.transferGroup;if(request.limit)params.limit=request.limit;if(request.startingAfter)params.starting_after=request.startingAfter;let response=await stripe.transfers.list(params);return{success:!0,transfers:response.data.map((t)=>({providerTransferId:t.id,amount:t.amount,currency:t.currency?.toUpperCase(),destination:t.destination,description:t.description,created:t.created?new Date(t.created*1000).toISOString():void 0})),hasMore:response.has_more,rawResponse:response}}catch(error){let err=error;return{success:!1,transfers:[],errorCode:err.code??"STRIPE_ERROR",errorMessage:err.message??"Failed to list transfers",rawResponse:{error:err.message}}}}}},verifyStripeWebhook=(rawBody,signature,webhookSecret)=>{try{let StripeModule=__require("stripe");return{success:!0,event:new(StripeModule.default??StripeModule)("sk_dummy_for_webhook_verification").webhooks.constructEvent(rawBody,signature,webhookSecret)}}catch(error){return{success:!1,event:null,error:error instanceof Error?error.message:"Webhook verification failed"}}};var resolveEnvValue=(value)=>{let envValue=process.env[value];if(envValue)return envValue;return value},createPaymentService=(config)=>{let paymentConfig=config.payment;if(!paymentConfig?.enabled)return null;let providerName=paymentConfig.provider;if(!providerName)return console.warn("[Payment] payment.enabled=true but no provider specified"),null;let providerConfig=null,provider=null,webhookSecret;switch(providerName){case"iyzico":{let iyzicoConf=paymentConfig.iyzico;if(!iyzicoConf)return console.warn("[Payment] payment.provider=iyzico but no iyzico config block"),null;let apiUrl=resolveEnvValue(iyzicoConf.apiUrl),apiKey=resolveEnvValue(iyzicoConf.apiKey),secretKey=resolveEnvValue(iyzicoConf.secretKey);if(!apiUrl||!apiKey||!secretKey)return console.warn("[Payment] iyzico credentials missing. Ensure env vars are set:",{apiUrl:iyzicoConf.apiUrl,apiKey:iyzicoConf.apiKey,secretKey:iyzicoConf.secretKey}),null;providerConfig={name:"iyzico",apiUrl,apiKey,secretKey},provider=createIyzicoProvider(providerConfig);break}case"stripe":{let stripeConf=paymentConfig.stripe;if(!stripeConf)return console.warn("[Payment] payment.provider=stripe but no stripe config block"),null;let secretKey=resolveEnvValue(stripeConf.secretKey),whSecret=resolveEnvValue(stripeConf.webhookSecret);if(!secretKey)return console.warn("[Payment] Stripe secret key missing. Ensure env var is set:",{secretKey:stripeConf.secretKey}),null;if(!whSecret)console.warn("[Payment] Stripe webhook secret missing. Webhook verification will fail.",{webhookSecret:stripeConf.webhookSecret});webhookSecret=whSecret,provider=createStripeProvider({secretKey,webhookSecret:whSecret,apiVersion:stripeConf.apiVersion,maxNetworkRetries:stripeConf.maxNetworkRetries,timeout:stripeConf.timeout});break}default:return console.warn(`[Payment] Unknown provider: ${providerName}`),null}if(!provider)return null;return console.log(`[Payment] Initialized provider: ${providerName}`),{provider:providerName,providerInstance:provider,webhookSecret}};var init_PaymentService=__esm(()=>{init_IyzicoProvider()});var exports_Payment={};__export(exports_Payment,{verifyStripeWebhook:()=>verifyStripeWebhook,createStripeProvider:()=>createStripeProvider,createPaymentService:()=>createPaymentService,createIyzicoProvider:()=>createIyzicoProvider});var init_Payment=__esm(()=>{init_IyzicoProvider();init_PaymentService()});var init_Services=__esm(()=>{init_ApiKey();init_Auth();init_Authorization();init_Backup();init_Captcha();init_Email();init_Gmail();init_Logger2();init_Monitoring();init_Notification();init_OAuth();init_RateLimiter();init_Tenant();init_Verification();init_Payment()});import path2 from"path";import Elysia2,{t}from"elysia";function mergeCdnConfig(config){if(!config)return DEFAULT_CDN_CONFIG;return{enabled:config.enabled??DEFAULT_CDN_CONFIG.enabled,basePath:config.basePath??DEFAULT_CDN_CONFIG.basePath,cacheMaxAge:config.cacheMaxAge??DEFAULT_CDN_CONFIG.cacheMaxAge,enableRangeRequests:config.enableRangeRequests??DEFAULT_CDN_CONFIG.enableRangeRequests,enableEtag:config.enableEtag??DEFAULT_CDN_CONFIG.enableEtag,corsOrigins:config.corsOrigins??DEFAULT_CDN_CONFIG.corsOrigins}}function getMimeTypeDisposition(mimeType){let inlineTypes=["image/","video/","audio/","text/","application/pdf"];for(let type of inlineTypes)if(mimeType.startsWith(type)||mimeType===type)return"inline";return"attachment"}function sanitizeFilename(filename){return filename.replace(/[^A-Za-z0-9._-]+/g,"_").replace(/_{2,}/g,"_").slice(0,200)}function createCdnRoutes(config){let{cdn,storagePath,logger:logger2,getFileRecord}=config,plugin=new Elysia2({prefix:cdn.basePath});if(!cdn.enabled)return plugin;return plugin.get("/:id",async({params,request,set})=>{let{id}=params,schemaName=request.headers.get("x-schema-name")||void 0,filePath,fileName,mimeType;if(getFileRecord){let fileRecord=await getFileRecord(id,schemaName);if(!fileRecord)return set.status=404,{success:!1,message:"File not found"};filePath=path2.join(fileRecord.path,fileRecord.name),fileName=fileRecord.name,mimeType=fileRecord.mimeType||fileRecord.mime_type||"application/octet-stream"}else filePath=path2.join(storagePath,id),fileName=id,mimeType="application/octet-stream";if(!await fileManager.exists(filePath))return set.status=404,{success:!1,message:"Physical file not found"};let fileInfo=await fileManager.getFileInfo(filePath),lastModified=new Date(fileInfo.modifiedAt||Date.now()).toUTCString(),etag=cdn.enableEtag?`"${fileInfo.size}-${fileInfo.modifiedAt?.getTime()||Date.now()}"`:void 0,cacheHeaders={"Cache-Control":`public, max-age=${cdn.cacheMaxAge}`,"Last-Modified":lastModified};if(etag)cacheHeaders.ETag=etag;if(cdn.corsOrigins.length>0)cacheHeaders["Access-Control-Allow-Origin"]=cdn.corsOrigins[0]==="*"?"*":cdn.corsOrigins.join(", "),cacheHeaders["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";let ifNoneMatch=request.headers.get("if-none-match");if(etag&&ifNoneMatch===etag)return new Response(null,{status:304,headers:cacheHeaders});let bunFile=Bun.file(filePath),range=request.headers.get("range");if(cdn.enableRangeRequests&&range){let rangeMatch=range.match(/bytes=(\d*)-(\d*)/);if(!rangeMatch)return set.status=416,new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${fileInfo.size}`,"Content-Type":mimeType,...cacheHeaders}});let startStr=rangeMatch[1]||"0",endStr=rangeMatch[2]||"",start=parseInt(startStr,10),end=endStr?parseInt(endStr,10):fileInfo.size-1;if(start>=fileInfo.size||end>=fileInfo.size||start>end)return new Response("Range not satisfiable",{status:416,headers:{"Content-Range":`bytes */${fileInfo.size}`,"Content-Type":mimeType,...cacheHeaders}});let chunkSize=end-start+1,chunkBlob=bunFile.slice(start,end+1);return new Response(chunkBlob,{status:206,headers:{"Content-Range":`bytes ${start}-${end}/${fileInfo.size}`,"Accept-Ranges":"bytes","Content-Length":chunkSize.toString(),"Content-Type":mimeType,...cacheHeaders}})}let dispositionType=getMimeTypeDisposition(mimeType),asciiFallbackName=sanitizeFilename(fileName),encodedUtf8Name=encodeURIComponent(fileName),contentDisposition=`${dispositionType}; filename="${asciiFallbackName}"; filename*=UTF-8''${encodedUtf8Name}`;return new Response(bunFile,{status:200,headers:{"Content-Length":fileInfo.size.toString(),"Content-Type":mimeType,"Accept-Ranges":cdn.enableRangeRequests?"bytes":"none","Content-Disposition":contentDisposition,...cacheHeaders}})},{params:t.Object({id:t.String()}),detail:{tags:["CDN"],summary:"Get file by ID",description:"Serve file with streaming, range requests, and caching support"}}),plugin.head("/:id",async({params,request,set})=>{let{id}=params,schemaName=request.headers.get("x-schema-name")||void 0,filePath,mimeType;if(getFileRecord){let fileRecord=await getFileRecord(id,schemaName);if(!fileRecord)return set.status=404,new Response(null,{status:404});filePath=path2.join(fileRecord.path,fileRecord.name),mimeType=fileRecord.mime_type||"application/octet-stream"}else filePath=path2.join(storagePath,id),mimeType="application/octet-stream";if(!await fileManager.exists(filePath))return set.status=404,new Response(null,{status:404});let fileInfo=await fileManager.getFileInfo(filePath),lastModified=new Date(fileInfo.modifiedAt||Date.now()).toUTCString(),etag=cdn.enableEtag?`"${fileInfo.size}-${fileInfo.modifiedAt?.getTime()||Date.now()}"`:void 0,headers={"Content-Length":fileInfo.size.toString(),"Content-Type":mimeType,"Accept-Ranges":cdn.enableRangeRequests?"bytes":"none","Cache-Control":`public, max-age=${cdn.cacheMaxAge}`,"Last-Modified":lastModified};if(etag)headers.ETag=etag;if(cdn.corsOrigins.length>0)headers["Access-Control-Allow-Origin"]=cdn.corsOrigins[0]==="*"?"*":cdn.corsOrigins.join(", "),headers["Access-Control-Allow-Methods"]="GET, HEAD, OPTIONS";return new Response(null,{status:200,headers})},{params:t.Object({id:t.String()}),detail:{tags:["CDN"],summary:"Get file metadata",description:"Get file headers without body for preflight checks"}}),logger2.info(`[CDN] Routes enabled at ${cdn.basePath}`),plugin}var DEFAULT_CDN_CONFIG;var init_cdn=__esm(()=>{init_File();DEFAULT_CDN_CONFIG={enabled:!0,basePath:"/cdn",cacheMaxAge:86400,enableRangeRequests:!0,enableEtag:!0,corsOrigins:["*"]}});import{randomUUID as randomUUID4}from"crypto";import path3 from"path";function mergeStorageConfig(config){if(!config)return DEFAULT_STORAGE_CONFIG;return{enabled:config.enabled??DEFAULT_STORAGE_CONFIG.enabled,basePath:config.basePath??DEFAULT_STORAGE_CONFIG.basePath,maxFileSizeBytes:config.maxFileSizeBytes??DEFAULT_STORAGE_CONFIG.maxFileSizeBytes,allowedMimeTypes:config.allowedMimeTypes??DEFAULT_STORAGE_CONFIG.allowedMimeTypes,blockedMimeTypes:config.blockedMimeTypes??DEFAULT_STORAGE_CONFIG.blockedMimeTypes,formData:{filesField:config.formData?.filesField??DEFAULT_STORAGE_CONFIG.formData.filesField,dataField:config.formData?.dataField??DEFAULT_STORAGE_CONFIG.formData.dataField,maxFiles:config.formData?.maxFiles??DEFAULT_STORAGE_CONFIG.formData.maxFiles}}}function parseFormDataBody(body,config){let result={data:{},files:[]};if(!body||typeof body!=="object")return result;let bodyObj=body,dataField=bodyObj[config.formData.dataField];if(dataField){if(typeof dataField==="string")try{result.data=JSON.parse(dataField)}catch{result.data={}}else if(typeof dataField==="object")result.data=dataField}let filesField=bodyObj[config.formData.filesField];if(filesField){if(filesField instanceof File)result.files=[filesField];else if(Array.isArray(filesField))result.files=filesField.filter((f)=>f instanceof File)}return result}function validateFile(file,config){if(file.size>config.maxFileSizeBytes)return{valid:!1,error:`File ${file.name} exceeds maximum size of ${config.maxFileSizeBytes} bytes`};if(config.blockedMimeTypes.length>0&&config.blockedMimeTypes.includes(file.type))return{valid:!1,error:`File type ${file.type} is not allowed`};if(config.allowedMimeTypes.length>0&&!config.allowedMimeTypes.includes(file.type))return{valid:!1,error:`File type ${file.type} is not in allowed list`};return{valid:!0}}async function uploadFile(file,config,subFolder){let id=randomUUID4(),ext=path3.extname(file.name),uniqueName=`${id}${ext}`,folderPath=subFolder?path3.join(config.basePath,subFolder):config.basePath,arrayBuffer=await file.arrayBuffer(),buffer=new Uint8Array(arrayBuffer);return await fileManager.createFile({dir:folderPath,name:uniqueName,data:buffer,options:{type:file.type,createDir:!0}}),{id,name:uniqueName,originalName:file.name,path:folderPath,mimeType:file.type,size:file.size,createdAt:new Date}}async function uploadFiles(files,config,subFolder){let success=[],failed=[];for(let file of files.slice(0,config.formData.maxFiles)){let validation=validateFile(file,config);if(!validation.valid){failed.push({file:file.name,error:validation.error||"Unknown error"});continue}try{let result=await uploadFile(file,config,subFolder);success.push(result)}catch(error){failed.push({file:file.name,error:error instanceof Error?error.message:"Upload failed"})}}return{success,failed}}async function deleteFile(filePath,fileName){try{let fullPath=path3.join(filePath,fileName);return await fileManager.deleteFile(fullPath)}catch{return!1}}var DEFAULT_STORAGE_CONFIG;var init_helpers=__esm(()=>{init_File();DEFAULT_STORAGE_CONFIG={enabled:!1,basePath:"./uploads",maxFileSizeBytes:104857600,allowedMimeTypes:[],blockedMimeTypes:["application/x-executable","application/x-msdos-program"],formData:{filesField:"files",dataField:"data",maxFiles:10}}});var exports_storage={};__export(exports_storage,{validateFile:()=>validateFile,uploadFiles:()=>uploadFiles,uploadFile:()=>uploadFile,parseFormDataBody:()=>parseFormDataBody,mergeStorageConfig:()=>mergeStorageConfig,mergeCdnConfig:()=>mergeCdnConfig,deleteFile:()=>deleteFile,createCdnRoutes:()=>createCdnRoutes});var init_storage=__esm(()=>{init_cdn();init_helpers()});import crypto6 from"crypto";var{password:password2}=globalThis.Bun;async function hashPassword(plainPassword){return await password2.hash(plainPassword,{algorithm:"bcrypt",cost:10})}function generateVerificationToken(){return crypto6.randomBytes(32).toString("hex")}function parseTimeToMs2(time){let match=time.match(/^(\d+)(s|m|h|d)$/);if(!match||!match[1]||!match[2])return 86400000;let value=Number.parseInt(match[1],10);switch(match[2]){case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;case"d":return value*24*60*60*1000;default:return 86400000}}function validatePasswordStrength(pwd){let errors=[];if(pwd.length<8)errors.push("Password must be at least 8 characters");if(!/[A-Z]/.test(pwd))errors.push("Password must contain uppercase letter");if(!/[a-z]/.test(pwd))errors.push("Password must contain lowercase letter");if(!/[0-9]/.test(pwd))errors.push("Password must contain a number");return{valid:errors.length===0,errors}}var init_utils6=()=>{};var resolveAuthTablesForRequest=(request,authConfig)=>{let defaults={usersTable:authConfig.usersTable,sessionsTable:authConfig.sessionsTable??null,userRolesTable:authConfig.userRolesTable??void 0,rolesTable:authConfig.rolesTable??void 0,roleClaimsTable:authConfig.roleClaimsTable??void 0,claimsTable:authConfig.claimsTable??void 0,oauthAccountsTable:authConfig.oauthAccountsTable??void 0,apiKeysTable:authConfig.apiKeysTable??void 0,schemaTables:authConfig.schemaTables||{}},registry=authConfig.tenantRegistry;if(!registry)return defaults;let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return defaults;let ctx=registry.getSchemaContext(schemaName);if(!ctx)return defaults;let tables=ctx.schemaTables;return{usersTable:tables.users??defaults.usersTable,sessionsTable:tables.userSessions??tables.user_sessions??tables.sessions??defaults.sessionsTable,userRolesTable:tables.userRoles??defaults.userRolesTable,rolesTable:tables.roles??defaults.rolesTable,roleClaimsTable:tables.roleClaims??defaults.roleClaimsTable,claimsTable:tables.claims??defaults.claimsTable,oauthAccountsTable:tables.oauthAccounts??defaults.oauthAccountsTable,apiKeysTable:tables.apiKeys??defaults.apiKeysTable,schemaTables:tables}};import{eq as eq15,sql as sql3}from"drizzle-orm";import{Elysia as Elysia13,t as t12}from"elysia";function createChangeUserIdRoute(config,schemaName="public"){let{db,logger:logger2}=config,routes=new Elysia13;return routes.post("/auth/admin/change-user-id",async(ctx)=>{let{usersTable}=resolveAuthTablesForRequest(ctx.request,config);if(!db||!usersTable)return{success:!1,message:"Database not configured"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Unauthorized"};let requestingUser=(await db.select().from(usersTable).where(eq15(usersTable.id,requestingUserId)).limit(1))[0];if(!requestingUser||!requestingUser.isGod)return ctx.set.status=403,{success:!1,message:"Forbidden: godmin privileges required"};let{currentId,newId}=ctx.body;if(!currentId||!newId)return ctx.set.status=400,{success:!1,message:"currentId and newId are required"};if(currentId===newId)return ctx.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(newId))return ctx.set.status=400,{success:!1,message:"newId must be a valid UUID"};let targetUser=(await db.select().from(usersTable).where(eq15(usersTable.id,currentId)).limit(1))[0];if(!targetUser)return ctx.set.status=404,{success:!1,message:"User not found"};if((await db.select().from(usersTable).where(eq15(usersTable.id,newId)).limit(1)).length>0)return ctx.set.status=409,{success:!1,message:"A user with this ID already exists"};try{let fkResult=await db.execute(sql3`
|
|
61
61
|
SELECT
|
|
62
62
|
tc.constraint_name,
|
|
63
63
|
tc.table_name,
|
|
@@ -185,7 +185,7 @@ var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defP
|
|
|
185
185
|
<p>Redirecting...</p>
|
|
186
186
|
</body>
|
|
187
187
|
</html>
|
|
188
|
-
`,createPaymentRoutes=(config)=>{let{provider,basePath,defaultCurrency,defaultLocale,successRedirectUrl,failedRedirectUrl,errorRedirectUrl,savedMethodsEnabled,threeDSecureEnabled,subMerchantsEnabled,transactionsTable,methodsTable,webhookLogsTable,subMerchantsTable,commissionSplitsTable,productsTable,pricesTable,customersTable,subscriptionsTable,invoicesTable,db,logger:logger2}=config,txTable=transactionsTable,pmTable=methodsTable,whTable=webhookLogsTable,smTable=subMerchantsTable,csTable=commissionSplitsTable,prodTable=productsTable,priceTable=pricesTable,cusTable=customersTable,subTable=subscriptionsTable,invTable=invoicesTable,database=db,app=new Elysia30({prefix:basePath});if(app.post("/initialize",async(ctx)=>{if(!threeDSecureEnabled)return ctx.set.status=400,{success:!1,error:"3D Secure is not enabled"};let userId=ctx.request.headers.get("x-user-id"),body=ctx.body;try{let[transaction]=await database.insert(txTable).values({userId:userId??null,orderId:body.orderId??body.conversationId??null,provider:provider.name,amount:Number(body.paidPrice??body.price??0),currency:body.currency??defaultCurrency,status:"pending",statusCode:1000,statusMessage:"3DS initialization started",isThreeDSecure:!0,installment:body.installment??1,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null,metadata:body.metadata??{}}).returning(),result=await provider.initialize3DS({locale:body.locale??defaultLocale,conversationId:transaction.id,price:body.price,paidPrice:body.paidPrice,currency:body.currency??defaultCurrency,installment:body.installment,paymentChannel:body.paymentChannel,basketId:body.basketId,paymentGroup:body.paymentGroup,paymentCard:body.paymentCard,buyer:body.buyer,shippingAddress:body.shippingAddress,billingAddress:body.billingAddress,basketItems:body.basketItems,callbackUrl:body.callbackUrl??config.callbackUrl??`${basePath}/callback`});if(!result.success)return await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:result.errorMessage??"Initialization failed",providerResponse:result.rawResponse??{},failedAt:new Date}).where(eq28(txTable.id,transaction.id)),ctx.set.status=400,{success:!1,error:result.errorMessage??"Payment initialization failed",errorCode:result.errorCode};return await database.update(txTable).set({status:"processing",statusCode:1001,statusMessage:"3DS initialized, awaiting bank verification",providerPaymentId:result.paymentId,providerResponse:result.rawResponse??{}}).where(eq28(txTable.id,transaction.id)),{success:!0,transactionId:transaction.id,threeDSHtmlContent:result.threeDSHtmlContent,paymentId:result.paymentId}}catch(error3){return logger2.error("[Payment] initialize3DS error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Internal payment error"}}}),app.post("/callback",async(ctx)=>{let requestOrigin=new URL(ctx.request.url).origin,htmlHeaders={"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":requestOrigin,"Access-Control-Allow-Methods":"POST, OPTIONS"};try{let formData=await ctx.request.formData(),rawData={};formData.forEach((value2,key)=>{rawData[key]=String(value2)});let parsed=provider.parseCallback(rawData);if(await database.insert(whTable).values({provider:provider.name,eventType:"three_ds_callback",providerPaymentId:parsed.paymentId,rawPayload:rawData,processed:!1,idempotencyKey:`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null}).onConflictDoNothing(),!parsed.success){if(logger2.warn("[Payment] 3DS callback failed",{mdStatus:parsed.mdStatus,paymentId:parsed.paymentId}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS verification failed: mdStatus=${parsed.mdStatus}`,failedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}let completion=await provider.complete3DS({locale:defaultLocale,conversationId:parsed.conversationId,paymentId:parsed.paymentId});if(!completion.success){if(logger2.error("[Payment] 3DS completion failed",{paymentId:parsed.paymentId,errorCode:completion.errorCode,errorMessage:completion.errorMessage}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS completion failed: ${completion.errorMessage}`,providerResponse:completion.rawResponse??{},failedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}if(parsed.conversationId)await database.update(txTable).set({status:"completed",statusCode:1001,statusMessage:"Payment completed successfully",providerPaymentId:completion.paymentId??parsed.paymentId,providerTransactionId:completion.signature,amount:completion.paidPrice??0,currency:completion.currency??defaultCurrency,paymentMethod:completion.cardAssociation,cardLastFour:completion.lastFourDigits,cardType:completion.cardType,cardAssociation:completion.cardAssociation,installment:completion.installment??1,providerResponse:completion.rawResponse??{},completedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});await database.update(whTable).set({processed:!0,processingResult:{completion}}).where(eq28(whTable.idempotencyKey,`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`)).catch(()=>{}),logger2.info("[Payment] 3DS payment completed",{paymentId:completion.paymentId,amount:completion.paidPrice,currency:completion.currency});let queryParams=new URLSearchParams;if(parsed.conversationId)queryParams.append("transactionId",parsed.conversationId);if(completion.paymentId)queryParams.append("paymentId",completion.paymentId);if(completion.paidPrice)queryParams.append("amount",String(completion.paidPrice));let redirectUrl=`${requestOrigin}${successRedirectUrl}?${queryParams.toString()}`;return new Response(generateRedirectHtml(redirectUrl,"Payment Successful"),{headers:htmlHeaders})}catch(error3){return logger2.error("[Payment] callback error",{error:error3 instanceof Error?error3.message:String(error3)}),new Response(generateRedirectHtml(`${requestOrigin}${errorRedirectUrl}`,"Payment Error"),{headers:htmlHeaders})}}),app.get("/transactions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(txTable).where(eq28(txTable.userId,userId)).orderBy(txTable.createdAt)}}}catch(error3){return logger2.error("[Payment] list transactions error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list transactions"}}}),app.get("/transactions/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[transaction]=await database.select().from(txTable).where(and9(eq28(txTable.id,ctx.params.id),eq28(txTable.userId,userId))).limit(1);if(!transaction)return ctx.set.status=404,{success:!1,error:"Transaction not found"};return{success:!0,data:transaction}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get transaction"}}}),app.post("/bin-query",async(ctx)=>{let body=ctx.body,binNumber=body.binNumber??body.cardNumber;if(!binNumber||typeof binNumber!=="string")return ctx.set.status=400,{success:!1,error:"binNumber is required"};try{let result=await provider.queryBin({locale:body.locale??defaultLocale,binNumber,price:body.price});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"BIN query failed",errorCode:result.errorCode};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"BIN query failed"}}}),app.post("/payment-detail",async(ctx)=>{let body=ctx.body;if(!body.paymentId)return ctx.set.status=400,{success:!1,error:"paymentId is required"};try{let result=await provider.getPaymentDetail({locale:body.locale??defaultLocale,paymentId:body.paymentId,conversationId:body.conversationId,paymentConversationId:body.paymentConversationId});return{success:result.success,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Payment detail query failed"}}}),app.post("/refund",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.paymentTransactionId||!body.price)return ctx.set.status=400,{success:!1,error:"paymentTransactionId and price are required"};try{let result=await provider.refund({locale:body.locale??defaultLocale,conversationId:body.conversationId,paymentTransactionId:body.paymentTransactionId,price:String(body.price),currency:body.currency??defaultCurrency,ip:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Refund failed",errorCode:result.errorCode};if(body.transactionId)await database.update(txTable).set({status:"refunded",refundedAmount:Number(body.price),refundedAt:new Date,statusMessage:"Payment refunded"}).where(eq28(txTable.id,body.transactionId)).catch(()=>{});return logger2.info("[Payment] Refund processed",{paymentId:result.paymentId,price:result.price}),{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Refund failed"}}}),savedMethodsEnabled)app.post("/cards/save",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.email||!body.card)return ctx.set.status=400,{success:!1,error:"email and card are required"};try{let result=await provider.saveCard({locale:body.locale??defaultLocale,email:body.email,externalId:userId,card:body.card});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to save card",errorCode:result.errorCode};let[saved]=await database.insert(pmTable).values({userId,provider:provider.name,type:"card",alias:result.cardAlias??body.card.cardAlias,cardLastFour:result.lastFourDigits,cardType:result.cardType,cardAssociation:result.cardAssociation,cardFamily:result.cardFamily,cardBankName:result.cardBankName,providerCardUserKey:result.cardUserKey,providerCardToken:result.cardToken,binNumber:result.binNumber}).returning();return logger2.info("[Payment] Card saved",{userId,cardAlias:result.cardAlias}),{success:!0,data:saved}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to save card"}}}),app.get("/cards",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(pmTable).where(and9(eq28(pmTable.userId,userId),eq28(pmTable.isActive,!0))).orderBy(pmTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list cards"}}}),app.delete("/cards/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[card]=await database.select().from(pmTable).where(and9(eq28(pmTable.id,ctx.params.id),eq28(pmTable.userId,userId))).limit(1);if(!card)return ctx.set.status=404,{success:!1,error:"Card not found"};if(card.providerCardUserKey&&card.providerCardToken){let deleteResult=await provider.deleteCard({locale:defaultLocale,cardUserKey:card.providerCardUserKey,cardToken:card.providerCardToken});if(!deleteResult.success)logger2.warn("[Payment] Provider card delete failed (proceeding with local delete)",{errorCode:deleteResult.errorCode,errorMessage:deleteResult.errorMessage})}return await database.update(pmTable).set({isActive:!1}).where(eq28(pmTable.id,ctx.params.id)),logger2.info("[Payment] Card deleted",{userId,cardId:ctx.params.id}),{success:!0}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to delete card"}}}),app.post("/cards/sync",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body,cardUserKey=body.cardUserKey;if(!cardUserKey)return ctx.set.status=400,{success:!1,error:"cardUserKey is required"};try{let result=await provider.listCards({locale:body.locale??defaultLocale,cardUserKey});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list cards from provider"};return{success:!0,data:{cardUserKey:result.cardUserKey,cards:result.cards}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to sync cards"}}});if(app.post("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name)return ctx.set.status=400,{success:!1,error:"name is required"};try{let providerResult=await provider.createProduct({name:body.name,description:body.description,type:body.type,images:body.images,unitLabel:body.unitLabel,url:body.url,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create product at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(prodTable).values({provider:provider.name,providerProductId:providerResult.providerProductId,name:body.name,description:body.description??null,type:body.type??"service",status:"active",images:body.images?JSON.stringify(body.images):"[]",unitLabel:body.unitLabel??null,url:body.url??null,metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Product created",{id:saved.id,providerProductId:providerResult.providerProductId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create product error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create product"}}}),app.put("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId){let providerResult=await provider.updateProduct({providerProductId:existing.providerProductId,name:body.name,description:body.description,images:body.images,unitLabel:body.unitLabel,url:body.url,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider product update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.description!==void 0)updateData.description=body.description;if(body.type)updateData.type=body.type;if(body.status)updateData.status=body.status;if(body.images)updateData.images=JSON.stringify(body.images);if(body.unitLabel!==void 0)updateData.unitLabel=body.unitLabel;if(body.url!==void 0)updateData.url=body.url;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(prodTable).set(updateData).where(eq28(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update product"}}}),app.get("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let status=new URL(ctx.request.url).searchParams.get("status"),query=database.select().from(prodTable).where(eq28(prodTable.isActive,!0));if(status)query=database.select().from(prodTable).where(and9(eq28(prodTable.isActive,!0),eq28(prodTable.status,status)));return{success:!0,data:{items:await query.orderBy(prodTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list products"}}}),app.get("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Product not found"};let prices=await database.select().from(priceTable).where(and9(eq28(priceTable.productId,ctx.params.id),eq28(priceTable.isActive,!0))).orderBy(priceTable.createdAt);return{success:!0,data:{...item,prices}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get product"}}}),app.delete("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[existing]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId)await provider.archiveProduct({providerProductId:existing.providerProductId});let[updated]=await database.update(prodTable).set({status:"archived"}).where(eq28(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to archive product"}}}),app.post("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.productId||body.unitAmount===void 0||!body.currency)return ctx.set.status=400,{success:!1,error:"productId, unitAmount, and currency are required"};try{let[product]=await database.select().from(prodTable).where(eq28(prodTable.id,body.productId)).limit(1);if(!product)return ctx.set.status=404,{success:!1,error:"Product not found"};let providerResult=await provider.createPrice({providerProductId:product.providerProductId,currency:body.currency,unitAmount:body.unitAmount,type:body.type,billingScheme:body.billingScheme,nickname:body.nickname,recurring:body.recurring,transformQuantity:body.transformQuantity,unitAmountDecimal:body.unitAmountDecimal,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create price at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(priceTable).values({productId:body.productId,provider:provider.name,providerPriceId:providerResult.providerPriceId,currency:body.currency,unitAmount:body.unitAmount,unitAmountDecimal:body.unitAmountDecimal??null,type:body.type??"one_time",billingScheme:body.billingScheme??"per_unit",nickname:body.nickname??null,recurringInterval:body.recurring?.interval??null,recurringIntervalCount:body.recurring?.intervalCount??1,recurringUsageType:body.recurring?.usageType??"licensed",recurringAggregateUsage:body.recurring?.aggregateUsage??null,transformQuantityDivideBy:body.transformQuantity?.divideBy??null,transformQuantityRound:body.transformQuantity?.round??null,status:"active",metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Price created",{id:saved.id,providerPriceId:providerResult.providerPriceId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create price error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create price"}}}),app.put("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId){let providerResult=await provider.updatePrice({providerPriceId:existing.providerPriceId,nickname:body.nickname,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider price update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.nickname!==void 0)updateData.nickname=body.nickname;if(body.status)updateData.status=body.status;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(priceTable).set(updateData).where(eq28(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update price"}}}),app.get("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),productId=url.searchParams.get("productId"),status=url.searchParams.get("status"),query=database.select().from(priceTable).where(eq28(priceTable.isActive,!0));if(productId&&status)query=database.select().from(priceTable).where(and9(eq28(priceTable.productId,productId),eq28(priceTable.status,status),eq28(priceTable.isActive,!0)));else if(productId)query=database.select().from(priceTable).where(and9(eq28(priceTable.productId,productId),eq28(priceTable.isActive,!0)));else if(status)query=database.select().from(priceTable).where(and9(eq28(priceTable.status,status),eq28(priceTable.isActive,!0)));return{success:!0,data:{items:await query.orderBy(priceTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list prices"}}}),app.get("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Price not found"};return{success:!0,data:item}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get price"}}}),app.delete("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[existing]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId)await provider.archivePrice({providerPriceId:existing.providerPriceId});let[updated]=await database.update(priceTable).set({status:"archived"}).where(eq28(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to archive price"}}}),app.post("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createCustomer({email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0,taxId:body.taxId});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(cusTable).values({user_id:userId,provider:provider.name,provider_customer_id:result.providerCustomerId,email:body.email,name:body.name??null,phone:body.phone??null,description:body.description??null,address:body.address??{},tax_id_type:body.taxId?.type??null,tax_id_value:body.taxId?.value??null,metadata:body.metadata??{}}).returning();return{success:!0,customer:row,providerCustomerId:result.providerCustomerId}}catch(error3){return logger2.error("[Payment] Create customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create customer"}}}),app.put("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};let result=await provider.updateCustomer({providerCustomerId:existing.provider_customer_id,email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0});if(!result.success)return ctx.set.status=400,result;let updates={};if(body.email)updates.email=body.email;if(body.name!==void 0)updates.name=body.name;if(body.phone!==void 0)updates.phone=body.phone;if(body.description!==void 0)updates.description=body.description;if(body.address)updates.address=body.address;if(body.metadata)updates.metadata=body.metadata;let[updated]=await database.update(cusTable).set(updates).where(eq28(cusTable.id,id)).returning();return{success:!0,customer:updated}}catch(error3){return logger2.error("[Payment] Update customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update customer"}}}),app.get("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,customers:await database.select().from(cusTable).where(eq28(cusTable.user_id,userId))}}catch(error3){return logger2.error("[Payment] List customers error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list customers"}}}),app.get("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};return{success:!0,customer}}catch(error3){return logger2.error("[Payment] Get customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get customer"}}}),app.delete("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};return await provider.deleteCustomer({providerCustomerId:existing.provider_customer_id}),await database.delete(cusTable).where(eq28(cusTable.id,id)),{success:!0}}catch(error3){return logger2.error("[Payment] Delete customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to delete customer"}}}),app.post("/subscriptions",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};let items=body.items,result=await provider.createSubscription({providerCustomerId:customer.provider_customer_id,items,trialPeriodDays:body.trialPeriodDays,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,defaultPaymentMethod:body.defaultPaymentMethod});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(subTable).values({customer_id:customerId,provider:provider.name,provider_subscription_id:result.providerSubscriptionId,status:result.status??"incomplete",collection_method:body.collectionMethod??"charge_automatically",current_period_start:result.currentPeriodStart?new Date(result.currentPeriodStart):null,current_period_end:result.currentPeriodEnd?new Date(result.currentPeriodEnd):null,cancel_at_period_end:body.cancelAtPeriodEnd??!1,items,metadata:body.metadata??{}}).returning();return{success:!0,subscription:row,clientSecret:result.clientSecret}}catch(error3){return logger2.error("[Payment] Create subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create subscription"}}}),app.put("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};let result=await provider.updateSubscription({providerSubscriptionId:existing.provider_subscription_id,items:body.items,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,defaultPaymentMethod:body.defaultPaymentMethod,prorationBehavior:body.prorationBehavior});if(!result.success)return ctx.set.status=400,result;let updates={};if(result.status)updates.status=result.status;if(body.cancelAtPeriodEnd!==void 0)updates.cancel_at_period_end=body.cancelAtPeriodEnd;if(body.items)updates.items=body.items;if(body.metadata)updates.metadata=body.metadata;if(body.collectionMethod)updates.collection_method=body.collectionMethod;let[updated]=await database.update(subTable).set(updates).where(eq28(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Update subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update subscription"}}}),app.post("/subscriptions/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};let result=await provider.cancelSubscription({providerSubscriptionId:existing.provider_subscription_id,cancelAtPeriodEnd:body.cancelAtPeriodEnd,invoiceNow:body.invoiceNow,prorate:body.prorate});if(!result.success)return ctx.set.status=400,result;let updates={status:result.status??"canceled",canceled_at:new Date};if(body.cancelAtPeriodEnd)updates.cancel_at_period_end=!0;let[updated]=await database.update(subTable).set(updates).where(eq28(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Cancel subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to cancel subscription"}}}),app.get("/subscriptions",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq28(subTable.customer_id,query.customerId));if(query.status)conditions.push(eq28(subTable.status,query.status));return{success:!0,subscriptions:conditions.length>0?await database.select().from(subTable).where(and9(...conditions)):await database.select().from(subTable)}}catch(error3){return logger2.error("[Payment] List subscriptions error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list subscriptions"}}}),app.get("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[subscription]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!subscription)return ctx.set.status=404,{success:!1,error:"Subscription not found"};return{success:!0,subscription}}catch(error3){return logger2.error("[Payment] Get subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get subscription"}}}),app.post("/usage-records",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.reportUsage({subscriptionItemId:body.subscriptionItemId,quantity:body.quantity,timestamp:body.timestamp,action:body.action});if(!result.success)return ctx.set.status=400,result;return{success:!0,usageRecord:result}}catch(error3){return logger2.error("[Payment] Report usage error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to report usage"}}}),app.get("/usage-records/:subscriptionItemId/summaries",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{subscriptionItemId}=ctx.params,query=ctx.query,result=await provider.listUsageRecordSummaries({subscriptionItemId,limit:query.limit?parseInt(query.limit,10):void 0,startingAfter:query.startingAfter});if(!result.success)return ctx.set.status=400,result;return{success:!0,summaries:result.summaries,hasMore:result.hasMore}}catch(error3){return logger2.error("[Payment] List usage summaries error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list usage summaries"}}}),app.post("/invoices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};let result=await provider.createInvoice({providerCustomerId:customer.provider_customer_id,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,description:body.description,metadata:body.metadata,autoAdvance:body.autoAdvance,items:body.items});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(invTable).values({customer_id:customerId,subscription_id:body.subscriptionId??null,provider:provider.name,provider_invoice_id:result.providerInvoiceId,status:result.status??"draft",collection_method:body.collectionMethod??"charge_automatically",currency:body.currency??defaultCurrency,description:body.description??null,hosted_invoice_url:result.hostedInvoiceUrl??null,invoice_pdf:result.invoicePdf??null,days_until_due:body.daysUntilDue??null,lines:body.items??[],metadata:body.metadata??{}}).returning();return{success:!0,invoice:row,providerInvoiceId:result.providerInvoiceId}}catch(error3){return logger2.error("[Payment] Create invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create invoice"}}}),app.post("/invoices/:id/finalize",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.finalizeInvoice({providerInvoiceId:existing.provider_invoice_id,autoAdvance:body.autoAdvance});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"open",hosted_invoice_url:result.hostedInvoiceUrl??existing.hosted_invoice_url,invoice_pdf:result.invoicePdf??existing.invoice_pdf}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Finalize invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to finalize invoice"}}}),app.post("/invoices/:id/send",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.sendInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;return{success:!0}}catch(error3){return logger2.error("[Payment] Send invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to send invoice"}}}),app.post("/invoices/:id/void",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.voidInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:"void",voided_at:new Date}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Void invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to void invoice"}}}),app.post("/invoices/:id/pay",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.payInvoice({providerInvoiceId:existing.provider_invoice_id,paymentMethod:body.paymentMethod});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"paid",amount_paid:result.amountPaid??existing.amount_paid,amount_due:result.amountDue??existing.amount_due,paid_at:new Date}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Pay invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to pay invoice"}}}),app.get("/invoices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq28(invTable.customer_id,query.customerId));if(query.subscriptionId)conditions.push(eq28(invTable.subscription_id,query.subscriptionId));if(query.status)conditions.push(eq28(invTable.status,query.status));return{success:!0,invoices:conditions.length>0?await database.select().from(invTable).where(and9(...conditions)):await database.select().from(invTable)}}catch(error3){return logger2.error("[Payment] List invoices error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list invoices"}}}),app.get("/invoices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[invoice]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!invoice)return ctx.set.status=404,{success:!1,error:"Invoice not found"};return{success:!0,invoice}}catch(error3){return logger2.error("[Payment] Get invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get invoice"}}}),subMerchantsEnabled)app.post("/sub-merchants",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name||!body.email||!body.subMerchantType)return ctx.set.status=400,{success:!1,error:"name, email, and subMerchantType are required"};try{let externalId=body.externalId??`sm-${Date.now().toString(36)}`,result=await provider.registerSubMerchant({locale:body.locale??defaultLocale,subMerchantExternalId:externalId,subMerchantType:body.subMerchantType,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency??defaultCurrency});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to register sub-merchant",errorCode:result.errorCode};let[saved]=await database.insert(smTable).values({userId:body.userId??null,provider:provider.name,providerSubMerchantKey:result.subMerchantKey,externalId,type:body.subMerchantType,status:"active",name:body.name,email:body.email,gsmNumber:body.gsmNumber??null,address:body.address??null,iban:body.iban??null,contactName:body.contactName??null,contactSurname:body.contactSurname??null,identityNumber:body.identityNumber??null,taxOffice:body.taxOffice??null,taxNumber:body.taxNumber??null,legalCompanyTitle:body.legalCompanyTitle??null,currency:body.currency??defaultCurrency,commissionRate:body.commissionRate??0}).returning();return logger2.info("[Payment] Sub-merchant registered",{externalId,providerKey:result.subMerchantKey}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] register sub-merchant error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to register sub-merchant"}}}),app.put("/sub-merchants/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(smTable).where(eq28(smTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};if(existing.providerSubMerchantKey){let providerResult=await provider.updateSubMerchant({locale:body.locale??defaultLocale,subMerchantKey:existing.providerSubMerchantKey,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency});if(!providerResult.success)logger2.warn("[Payment] Provider sub-merchant update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.email)updateData.email=body.email;if(body.gsmNumber!==void 0)updateData.gsmNumber=body.gsmNumber;if(body.address!==void 0)updateData.address=body.address;if(body.iban!==void 0)updateData.iban=body.iban;if(body.contactName!==void 0)updateData.contactName=body.contactName;if(body.contactSurname!==void 0)updateData.contactSurname=body.contactSurname;if(body.identityNumber!==void 0)updateData.identityNumber=body.identityNumber;if(body.taxOffice!==void 0)updateData.taxOffice=body.taxOffice;if(body.taxNumber!==void 0)updateData.taxNumber=body.taxNumber;if(body.legalCompanyTitle!==void 0)updateData.legalCompanyTitle=body.legalCompanyTitle;if(body.currency!==void 0)updateData.currency=body.currency;if(body.commissionRate!==void 0)updateData.commissionRate=body.commissionRate;if(body.status!==void 0)updateData.status=body.status;let[updated]=await database.update(smTable).set(updateData).where(eq28(smTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update sub-merchant"}}}),app.get("/sub-merchants",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(smTable).where(eq28(smTable.isActive,!0)).orderBy(smTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list sub-merchants"}}}),app.get("/sub-merchants/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(smTable).where(eq28(smTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};return{success:!0,data:item}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get sub-merchant"}}}),app.post("/splits/:splitId/approve",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[split]=await database.select().from(csTable).where(eq28(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.approveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider approval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"approved",approvedAt:new Date}).where(eq28(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split approved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to approve split"}}}),app.post("/splits/:splitId/disapprove",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[split]=await database.select().from(csTable).where(eq28(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.disapproveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider disapproval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"disapproved",disapprovedAt:new Date}).where(eq28(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split disapproved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to disapprove split"}}}),app.get("/splits",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),transactionId=url.searchParams.get("transactionId"),subMerchantId=url.searchParams.get("subMerchantId"),query=database.select().from(csTable);if(transactionId&&subMerchantId)query=query.where(and9(eq28(csTable.transactionId,transactionId),eq28(csTable.subMerchantId,subMerchantId)));else if(transactionId)query=query.where(eq28(csTable.transactionId,transactionId));else if(subMerchantId)query=query.where(eq28(csTable.subMerchantId,subMerchantId));return{success:!0,data:{items:await query.orderBy(csTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list splits"}}});return app.get("/balance",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getBalance();if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get balance"};return{success:!0,data:{available:result.available,pending:result.pending,connectReserved:result.connectReserved}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get balance"}}}),app.post("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createPayout({amount:body.amount,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,method:body.method,sourceType:body.sourceType,statementDescriptor:body.statementDescriptor});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to create payout"}}}),app.get("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listPayouts({status:url.searchParams.get("status")??void 0,destination:url.searchParams.get("destination")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list payouts"};return{success:!0,data:{payouts:result.payouts,hasMore:result.hasMore}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list payouts"}}}),app.get("/payouts/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get payout"}}}),app.post("/payouts/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.cancelPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to cancel payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to cancel payout"}}}),app.post("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createTransfer({amount:body.amount,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,sourceTransaction:body.sourceTransaction,transferGroup:body.transferGroup});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create transfer"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to create transfer"}}}),app.get("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listTransfers({destination:url.searchParams.get("destination")??void 0,transferGroup:url.searchParams.get("transferGroup")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list transfers"};return{success:!0,data:{transfers:result.transfers,hasMore:result.hasMore}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list transfers"}}}),app.options("/callback",()=>{return new Response(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,POST,OPTIONS","Access-Control-Allow-Headers":"Content-Type"}})}),app};var init_payment=()=>{};import{batch,createStore}from"h-state";import{useEffectEvent}from"react";function createInitialState(endpoints){let state={};for(let key of Object.keys(endpoints))state[key]={isPending:!1,data:null,error:null,code:null};return state}function createApiHook(endpoints,factory){let{useStore}=createStore(createInitialState(endpoints),{_callEndpoint:(store)=>async(endpointKey,options)=>{if(!store[endpointKey])return;batch(()=>{store[endpointKey].isPending=!0,store[endpointKey].error=null});try{let response=await factory(endpointKey,options.payload);if(batch(()=>{if(store[endpointKey].isPending=!1,store[endpointKey].code=response.code??null,response.isSuccess&&response.data!==void 0)store[endpointKey].data=response.data,store[endpointKey].error=null;else store[endpointKey].error=response.errors??null}),response.isSuccess)options.onAfterHandle?.(response.data??response);else options.onErrorHandle?.(response.errors??{message:"Request failed"},response.code)}catch(err){batch(()=>{store[endpointKey].isPending=!1,store[endpointKey].error={message:err instanceof Error?err.message:"Unknown error"}}),options.onErrorHandle?.({message:err instanceof Error?err.message:"Unknown error"},null)}}});return function(){let store=useStore(),callEndpoint=useEffectEvent((endpointKey,options)=>{store._callEndpoint(endpointKey,options)}),actions={};for(let key of Object.keys(endpoints)){let startFn=(options)=>{callEndpoint(key,options)};actions[key]={state:store[key],start:startFn}}return actions}}var system_tables_default={$schema:"../schemas/nucleus.tables.schema.json",tables:[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]}]};var AUTH_ENDPOINT_CONFIGS={login:{key:"LOGIN",method:"POST",defaultRoute:"/auth/login",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},register:{key:"REGISTER",method:"POST",defaultRoute:"/auth/register",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},logout:{key:"LOGOUT",method:"POST",defaultRoute:"/auth/logout",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},refresh:{key:"REFRESH",method:"POST",defaultRoute:"/auth/refresh",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},me:{key:"ME",method:"GET",defaultRoute:"/auth/me",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordChange:{key:"PASSWORD_CHANGE",method:"POST",defaultRoute:"/auth/password-change",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordSet:{key:"PASSWORD_SET",method:"POST",defaultRoute:"/auth/password-set",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordReset:{key:"PASSWORD_RESET_REQUEST",method:"POST",defaultRoute:"/auth/password-reset",defaultIsPublic:!0,subEndpoints:[{key:"PASSWORD_RESET_REQUEST",method:"POST",suffix:"/request",_payload:void 0,_success:void 0,_error:void 0},{key:"PASSWORD_RESET_CONFIRM",method:"POST",suffix:"/confirm",_payload:void 0,_success:void 0,_error:void 0}]},sessions:{key:"SESSIONS",method:"GET",defaultRoute:"/auth/sessions",defaultIsPublic:!1,subEndpoints:[{key:"SESSIONS",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_CURRENT",method:"GET",suffix:"/current",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_STATS",method:"GET",suffix:"/stats",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_PENDING",method:"GET",suffix:"/pending",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE",method:"DELETE",suffix:"/:sessionId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE_ALL",method:"DELETE",suffix:"/all",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_APPROVE",method:"POST",suffix:"/approve",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REJECT",method:"POST",suffix:"/reject",_payload:void 0,_success:void 0,_error:void 0}]},magicLink:{key:"MAGIC_LINK",method:"POST",defaultRoute:"/auth/magic-link",defaultIsPublic:!0,subEndpoints:[{key:"MAGIC_LINK",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"MAGIC_LINK_VERIFY",method:"GET",suffix:"/verify",routeKey:"verifyRoute",_payload:void 0,_success:void 0,_error:void 0}]},invite:{key:"INVITE",method:"POST",defaultRoute:"/auth/invite",defaultIsPublic:!1,subEndpoints:[{key:"INVITE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"INVITE_VERIFY",method:"POST",suffix:"/verify",_payload:void 0,_success:void 0,_error:void 0}]},emailVerification:{key:"VERIFY_EMAIL",method:"GET",defaultRoute:"/verify-email",defaultIsPublic:!0,subEndpoints:[{key:"VERIFY_EMAIL",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"RESEND_VERIFICATION",method:"POST",suffix:"",routeKey:"resendRoute",defaultRoute:"/resend-verification",_payload:void 0,_success:void 0,_error:void 0}]},captcha:{key:"CAPTCHA",method:"GET",defaultRoute:"/auth/captcha",defaultIsPublic:!0,subEndpoints:[{key:"CAPTCHA_GENERATE",method:"GET",suffix:"/generate",_payload:void 0,_success:void 0,_error:void 0},{key:"CAPTCHA_VALIDATE",method:"POST",suffix:"/validate",_payload:void 0,_success:void 0,_error:void 0}]},oauth:{key:"OAUTH_PROVIDERS",method:"GET",defaultRoute:"/auth/oauth/providers",defaultIsPublic:!0,subEndpoints:[{key:"OAUTH_PROVIDERS",method:"GET",suffix:"/providers",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_REDIRECT",method:"GET",suffix:"/:provider",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_ACCOUNTS",method:"GET",suffix:"/accounts",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_UNLINK",method:"DELETE",suffix:"/unlink/:provider",_payload:void 0,_success:void 0,_error:void 0}]},apiKeys:{key:"API_KEYS",method:"GET",defaultRoute:"/auth/api-keys",defaultIsPublic:!1,subEndpoints:[{key:"API_KEYS_CREATE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_LIST",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_DETAIL",method:"GET",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_UPDATE",method:"PATCH",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_REVOKE",method:"DELETE",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0}]}};var TENANT_ENDPOINT_CONFIGS={checkSubdomain:{key:"TENANT_CHECK_SUBDOMAIN",method:"GET",suffix:"/check-subdomain/:subdomain",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},provision:{key:"TENANT_PROVISION",method:"POST",suffix:"/provision",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},list:{key:"TENANT_LIST",method:"GET",suffix:"",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},detail:{key:"TENANT_DETAIL",method:"GET",suffix:"/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},suspend:{key:"TENANT_SUSPEND",method:"POST",suffix:"/:id/suspend",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},reactivate:{key:"TENANT_REACTIVATE",method:"POST",suffix:"/:id/reactivate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},selfSignup:{key:"TENANT_SELF_SIGNUP",method:"POST",suffix:"/self-signup",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0}},MONITORING_ENDPOINT_CONFIGS={healthCheck:{key:"MONITORING_HEALTH_CHECK",method:"GET",suffix:"/health",_payload:void 0,_success:void 0,_error:void 0},getSettings:{key:"MONITORING_GET_SETTINGS",method:"GET",suffix:"/settings",_payload:void 0,_success:void 0,_error:void 0},changeSettings:{key:"MONITORING_CHANGE_SETTINGS",method:"PATCH",suffix:"/settings",_payload:void 0,_success:void 0,_error:void 0},getLogs:{key:"MONITORING_GET_LOGS",method:"GET",suffix:"/logs",_payload:void 0,_success:void 0,_error:void 0}};var SYSTEM_TABLE_NAMES=["profiles","addresses","phones","files","users","roles","claims","user_roles","role_claims","audit_logs"],systemTables=system_tables_default.tables.filter((t)=>SYSTEM_TABLE_NAMES.includes(t.table_name));function toUpperSnakeCase(str){return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toUpperCase()}function snakeToCamelCase(str){return str.replace(/_([a-z])/g,(_,letter)=>letter.toUpperCase())}function singularize(str){if(str.endsWith("ies"))return`${str.slice(0,-3)}y`;if(str.endsWith("ses"))return`${str.slice(0,-2)}`;if(str.endsWith("s"))return str.slice(0,-1);return str}function generateEntityEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName),singularName=toUpperSnakeCase(singularize(tableName));switch(method){case"GET":return`GET_${upperName}`;case"POST":return`ADD_${singularName}`;case"PUT":return`UPDATE_${singularName}`;case"PATCH":return`PATCH_${singularName}`;case"DELETE":return`DELETE_${singularName}`}}function generateBulkEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName);switch(method){case"POST":return`BULK_ADD_${upperName}`;case"PUT":return`BULK_UPDATE_${upperName}`;case"DELETE":return`BULK_DELETE_${upperName}`}}function isMethodExcluded(table,method){if(!table.excluded_methods)return!1;let methodMap={GET:"GET",POST:"POST",PUT:"PUT",PATCH:"PATCH",DELETE:"DELETE"};return table.excluded_methods.includes(methodMap[method])}function generateEndpointsFromConfig(config){let endpoints={};for(let table of config.entities){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,sid=table.serviceId;if(!isMethodExcluded(table,"GET")){endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0},endpoints[`GET_${toUpperSnakeCase(tableName)}_DISTINCT`]={method:"GET",path:`${basePath}/distinct/:field`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}if(!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:table.is_public?.POST??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:table.is_public?.PUT??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:table.is_public?.PATCH??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled){if(!isMethodExcluded(table,"POST"))endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:table.is_public?.POST??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:table.is_public?.PUT??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}}return endpoints}function generateAuthEndpoints(config){let endpoints={},auth=config.authentication;if(!auth?.enabled)return endpoints;for(let[featureKey,endpointConfig]of Object.entries(AUTH_ENDPOINT_CONFIGS)){let feature=auth[featureKey];if(!feature?.enabled)continue;let feat=feature,baseRoute=feat.route||endpointConfig.defaultRoute,isPublic=feat.isPublic??endpointConfig.defaultIsPublic;if("subEndpoints"in endpointConfig&&endpointConfig.subEndpoints)for(let sub of endpointConfig.subEndpoints){let subRoute="routeKey"in sub&&sub.routeKey&&feature[sub.routeKey]?String(feature[sub.routeKey]):("defaultRoute"in sub)&&sub.defaultRoute?String(sub.defaultRoute):`${baseRoute}${sub.suffix}`;endpoints[sub.key]={method:sub.method,path:subRoute,isPublic:sub.key==="MAGIC_LINK_VERIFY"?!0:isPublic,_payload:sub._payload,_success:sub._success,_error:sub._error}}else if("_payload"in endpointConfig)endpoints[endpointConfig.key]={method:endpointConfig.method,path:baseRoute,isPublic,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error}}return endpoints}function generateSystemTableEndpoints(){let endpoints={};for(let table of systemTables){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,isFormData=tableName==="files";endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));if(endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},table.bulk_endpoints_enabled)endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}}return endpoints}function generateMonitoringEndpoints(config){let endpoints={},monitoring=config.liveMonitoring;if(!monitoring?.enabled)return endpoints;let basePath=monitoring.basePath||"/monitoring";for(let endpointConfig of Object.values(MONITORING_ENDPOINT_CONFIGS))endpoints[endpointConfig.key]={method:endpointConfig.method,path:`${basePath}${endpointConfig.suffix}`,isPublic:!1,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error};return endpoints}function generateAdminEndpoints(config){let endpoints={};if(!config.authentication?.enabled)return endpoints;return endpoints.ADMIN_IMPERSONATE={method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_IMPERSONATE_STOP={method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CHANGE_USER_ID={method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints}function generateVerificationEndpoints(config){let endpoints={},verification=config.verification,notification=config.notification;if(!verification?.enabled)return endpoints;let basePath=verification.endpoints?.basePath||"/verifications",flowBasePath=verification.flowEndpoints?.basePath||"/verification-flows",notifBasePath=notification?.endpoints?.basePath||"/notifications";if(endpoints.VERIFICATION_STATUS={method:"GET",path:`${basePath}/status/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_DECIDE={method:"POST",path:`${basePath}/:entity_name/:entity_id/decide`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_PENDING={method:"GET",path:`${basePath}/pending`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_HISTORY={method:"GET",path:`${basePath}/history/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START={method:"POST",path:`${basePath}/start`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START_FOR_ENTITY={method:"POST",path:`${basePath}/start-for-entity`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_ENTITY_STATUSES={method:"GET",path:`${basePath}/statuses/:entity_name`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},verification.flowEndpoints?.enabled)endpoints.FLOW_LIST={method:"GET",path:flowBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_GET={method:"GET",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_SAVE={method:"POST",path:flowBasePath,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_PUBLISH={method:"POST",path:`${flowBasePath}/:flow_id/publish`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_DELETE={method:"DELETE",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(notification?.enabled&¬ification.endpoints?.enabled)endpoints.NOTIFICATION_LIST={method:"GET",path:notifBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_UNSEEN_COUNT={method:"GET",path:`${notifBasePath}/unseen-count`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_SEEN={method:"POST",path:`${notifBasePath}/:notification_id/seen`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_ALL_SEEN={method:"POST",path:`${notifBasePath}/seen-all`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};return endpoints}function generateTenantEndpoints(config){let endpoints={};if(!config.database?.isMultiTenant)return endpoints;let basePath="/tenants";for(let endpointConfig of Object.values(TENANT_ENDPOINT_CONFIGS))endpoints[endpointConfig.key]={method:endpointConfig.method,path:`${basePath}${endpointConfig.suffix}`,isPublic:"isPublic"in endpointConfig?endpointConfig.isPublic:!1,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error};return endpoints}function generateAllEndpoints(config,extraEndpoints){let entityEndpoints=generateEndpointsFromConfig(config),authEndpoints=generateAuthEndpoints(config),adminEndpoints=generateAdminEndpoints(config),systemEndpoints=generateSystemTableEndpoints(),monitoringEndpoints=generateMonitoringEndpoints(config),verificationEndpoints=generateVerificationEndpoints(config),tenantEndpoints=generateTenantEndpoints(config);return{...entityEndpoints,...authEndpoints,...adminEndpoints,...systemEndpoints,...monitoringEndpoints,...verificationEndpoints,...tenantEndpoints,...extraEndpoints??{}}}init_Logger();import{randomUUID as randomUUID2}from"crypto";var DEFAULT_CONFIG2={timeout:30000,retries:0,retryDelay:1000,debug:!1};class ServerFetch{config;logger;constructor(config={}){this.config={...DEFAULT_CONFIG2,...config},this.logger=new Logger({service:"ServerFetch",prettyPrint:this.config.debug,colorize:this.config.debug,auditEnabled:!1})}buildUrl(url){if(url.startsWith("http://")||url.startsWith("https://"))return url;return this.config.baseUrl?`${this.config.baseUrl}${url}`:url}buildHeaders(customHeaders){let headers=new Headers;if(this.config.defaultHeaders)for(let[key,value]of Object.entries(this.config.defaultHeaders))headers.set(key,value);if(customHeaders)if(customHeaders instanceof Headers)customHeaders.forEach((value,key)=>{headers.set(key,value)});else if(Array.isArray(customHeaders))for(let[key,value]of customHeaders)headers.set(key,value);else for(let[key,value]of Object.entries(customHeaders))headers.set(key,value);return headers}parseResponseHeaders(headers){let result={};if(headers.forEach((value,key)=>{if(key.toLowerCase()==="set-cookie"){let existing=result[key];result[key]=existing?`${existing}, ${value}`:value}else result[key]=value}),typeof headers.getSetCookie==="function"){let setCookies=headers.getSetCookie();if(setCookies.length>0)result["set-cookie"]=setCookies.join(", ")}return result}async executeWithTimeout(promise,timeoutMs,_requestId){let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),timeoutMs);try{return await Promise.race([promise,new Promise((_,reject)=>{controller.signal.addEventListener("abort",()=>{reject(Error(`Request timeout after ${timeoutMs}ms`))})})])}finally{clearTimeout(timeoutId)}}async fetch(options){let requestId=randomUUID2(),startTime=performance.now(),url=this.buildUrl(options.url),headers=this.buildHeaders(options.headers),timeout=options.timeout??this.config.timeout??30000,retries=options.retries??this.config.retries??0,retryDelay=options.retryDelay??this.config.retryDelay??1000,body;if(options.body)if(typeof options.body==="object"&&!(options.body instanceof FormData)&&!(options.body instanceof URLSearchParams)&&!(options.body instanceof Blob)&&!(options.body instanceof ArrayBuffer)){if(body=JSON.stringify(options.body),!headers.has("content-type"))headers.set("content-type","application/json")}else body=options.body;this.logger.debug(`[${requestId}] ${options.method} ${url}`,{method:options.method,url,hasBody:!!body});let lastError=null,attempt=0;while(attempt<=retries)try{let response=await this.executeWithTimeout(fetch(url,{method:options.method,headers,body}),timeout,requestId),durationMs2=performance.now()-startTime,responseHeaders=this.parseResponseHeaders(response.headers),rawSetCookies=typeof response.headers.getSetCookie==="function"?response.headers.getSetCookie():[],responseData,errorData,rawText=await response.text();if(rawText)try{let json=JSON.parse(rawText);if(response.ok)responseData=json;else errorData=json}catch{if(!response.ok)errorData={message:rawText||response.statusText}}else if(!response.ok)errorData={message:response.statusText};let result={isSuccess:response.ok,response:responseData,errors:errorData,code:response.status,headers:responseHeaders,rawSetCookies,durationMs:durationMs2,requestId,createdAt:new Date};if(response.ok)this.logger.info(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2)});else this.logger.warn(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2),error:errorData});return result}catch(error){if(lastError=error instanceof Error?error:Error(String(error)),attempt++,attempt<=retries)this.logger.warn(`[${requestId}] Retry ${attempt}/${retries} after error`,{method:options.method,url,error:lastError.message,attempt,retries}),await new Promise((resolve)=>setTimeout(resolve,retryDelay))}let durationMs=performance.now()-startTime;return this.logger.error(`[${requestId}] ${options.method} ${url} failed`,lastError,{method:options.method,url,durationMs:Math.round(durationMs),attempts:attempt}),{isSuccess:!1,response:void 0,errors:{message:lastError?.message||"Unknown error"},code:null,headers:{},rawSetCookies:[],durationMs,requestId,createdAt:new Date}}async get(url,options){return this.fetch({...options,url,method:"GET"})}async post(url,body,options){return this.fetch({...options,url,method:"POST",body})}async put(url,body,options){return this.fetch({...options,url,method:"PUT",body})}async patch(url,body,options){return this.fetch({...options,url,method:"PATCH",body})}async delete(url,options){return this.fetch({...options,url,method:"DELETE"})}}var serverFetch=new ServerFetch;var DEFAULT_TOKEN_NAMES={accessToken:"access_token",refreshToken:"refresh_token",sessionToken:"session_token"};function splitSetCookieHeader(header){let cookies=[],current="";for(let i=0;i<header.length;i++){let char=header[i];if(char===","){let next=header.slice(i+1).trimStart();if(/^[a-zA-Z0-9_-]+=/.test(next)){cookies.push(current.trim()),current="";continue}}current+=char}if(current.trim())cookies.push(current.trim());return cookies}function buildRequestHeaders(headersStore,tokenNames){let headers={},forwardHeaders=["x-forwarded-for","x-real-ip","user-agent","accept-language","x-request-id","x-client-ip","cf-connecting-ip","true-client-ip"];for(let header of forwardHeaders){let value=headersStore.get(header);if(value)headers[header]=value}if(!headers["user-agent"])headers["user-agent"]="Nucleus-ServerAction/1.0";let accessToken=headersStore.get(`x-${tokenNames.accessToken}`),refreshToken=headersStore.get(`x-${tokenNames.refreshToken}`),sessionToken=headersStore.get(`x-${tokenNames.sessionToken}`);if(accessToken)headers[`x-${tokenNames.accessToken}`]=accessToken;if(refreshToken)headers[`x-${tokenNames.refreshToken}`]=refreshToken;if(sessionToken)headers[`x-${tokenNames.sessionToken}`]=sessionToken;let cookieHeader=headersStore.get("cookie");if(cookieHeader)headers.cookie=cookieHeader;return headers}function toCamelCase(str){return str.replace(/_([a-z])/g,(_,c)=>c.toUpperCase())}function convertKeysToCamelCase(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.startsWith("_")?key:toCamelCase(key);if(value instanceof Date)result[camelKey]=value.toISOString();else if(value&&typeof value==="object"&&!Array.isArray(value))result[camelKey]=convertKeysToCamelCase(value);else result[camelKey]=value}return result}var JSON_STRINGIFY_KEYS=new Set(["filters","sort","with","searchFields","select","distinctOn"]);function appendQueryParams(url,params){let searchParams=new URLSearchParams;for(let[key,value]of Object.entries(params)){if(value===void 0||value===null)continue;if(JSON_STRINGIFY_KEYS.has(key)&&typeof value==="object"){searchParams.append(key,JSON.stringify(value));continue}if(value instanceof Date)searchParams.append(key,value.toISOString());else if(Array.isArray(value))searchParams.append(key,value.filter((v)=>v!=null).map(String).join(","));else if(typeof value==="object")searchParams.append(key,JSON.stringify(value));else searchParams.append(key,String(value))}let queryString=searchParams.toString();if(!queryString)return url;return url.includes("?")?`${url}&${queryString}`:`${url}?${queryString}`}function createServerFactory(endpoints,config,getCookies,getHeaders){let tokenNames={...DEFAULT_TOKEN_NAMES,...config.tokenNames},serverFetch2=new ServerFetch({baseUrl:config.baseUrl,debug:config.debug,timeout:30000,retries:0});return async function(endpointKey,payload){let endpoint=endpoints[endpointKey];if(!endpoint)return{isSuccess:!1,errors:{message:`Endpoint "${endpointKey}" not found`},code:404};let cookieStore=await getCookies(),headersStore=await getHeaders(),allHeaders={};if(headersStore.forEach((value,key)=>{allHeaders[key]=value}),(endpoint.path.includes("/auth/login")||endpoint.path.includes("/auth/oauth"))&&endpoint.method==="POST")try{cookieStore.delete(tokenNames.accessToken),cookieStore.delete(tokenNames.refreshToken),cookieStore.delete(tokenNames.sessionToken)}catch(_){}let headers=buildRequestHeaders(headersStore,tokenNames),url=endpoint.path,body,pathParamNames=new Set,pathParamRegex=/:([a-zA-Z_][a-zA-Z0-9_]*)/g,paramMatch=pathParamRegex.exec(url);while(paramMatch!==null){if(paramMatch[1])pathParamNames.add(paramMatch[1]);paramMatch=pathParamRegex.exec(url)}if(payload&&typeof payload==="object"&&!(payload instanceof FormData)){let payloadObj=payload;for(let[key,value]of Object.entries(payloadObj))if(value!=null){if(pathParamNames.has(key))url=url.replace(`:${key}`,String(value));else if(key.startsWith("_")&&pathParamNames.has(key.substring(1)))url=url.replace(`:${key.substring(1)}`,String(value));else if(key==="id"&&pathParamNames.has("id"))url=url.replace(":id",String(value))}}if(endpoint.method==="GET"&&payload&&typeof payload==="object"){let queryPayload={...payload};for(let paramName of pathParamNames)delete queryPayload[paramName],delete queryPayload[`_${paramName}`];url=appendQueryParams(url,queryPayload)}else if(payload!==void 0){if(endpoint.isFormData&&payload instanceof FormData)body=payload;else if(Array.isArray(payload)){if(body=payload.map((item)=>item&&typeof item==="object"?convertKeysToCamelCase(item):item),!headers["content-type"])headers["content-type"]="application/json"}else if(body=endpoint.skipCamelCase?payload:convertKeysToCamelCase(payload),!headers["content-type"])headers["content-type"]="application/json"}let response=await serverFetch2.fetch({url,method:endpoint.method,headers,body}),setCookiesToProcess=response.rawSetCookies.length>0?response.rawSetCookies:response.headers["set-cookie"]?splitSetCookieHeader(response.headers["set-cookie"]):[];if(setCookiesToProcess.length>0)try{for(let cookie of setCookiesToProcess){let[nameValue,...options]=cookie.split(";");if(!nameValue)continue;let eqIdx=nameValue.indexOf("=");if(eqIdx===-1)continue;let name=nameValue.substring(0,eqIdx).trim(),value=nameValue.substring(eqIdx+1).trim();if(name&&value){let cookieOptions={};for(let opt of options){let trimmed=opt.trim(),optEqIdx=trimmed.indexOf("="),optName=optEqIdx===-1?trimmed:trimmed.substring(0,optEqIdx),optValue=optEqIdx===-1?void 0:trimmed.substring(optEqIdx+1);if(!optName)continue;let optNameLower=optName.toLowerCase();if(optNameLower==="path")cookieOptions.path=optValue;else if(optNameLower==="domain")cookieOptions.domain=optValue;else if(optNameLower==="max-age")cookieOptions.maxAge=Number(optValue);else if(optNameLower==="expires"&&optValue)cookieOptions.expires=new Date(optValue);else if(optNameLower==="httponly")cookieOptions.httpOnly=!0;else if(optNameLower==="secure")cookieOptions.secure=!0;else if(optNameLower==="samesite")cookieOptions.sameSite=optValue}cookieStore.set(name,value,cookieOptions)}}}catch(cookieError){console.warn("[ServerFactory] Failed to process Set-Cookie headers:",cookieError instanceof Error?cookieError.message:String(cookieError))}let normalizedResponse=response.response;if(response.isSuccess&&normalizedResponse&&typeof normalizedResponse==="object"&&!Array.isArray(normalizedResponse)){let raw=normalizedResponse;if("success"in raw&&!("data"in raw)){let{success,message,error,...rest}=raw;normalizedResponse={success,...message!==void 0?{message}:{},...error!==void 0?{error}:{},...Object.keys(rest).length>0?{data:rest}:{}}}}return{isSuccess:response.isSuccess,data:normalizedResponse,errors:response.errors,code:response.code,message:response.isSuccess?void 0:response.errors?.message}}}import{batch as batch2,createStore as createStore2}from"h-state";var initialState={connection:{status:"disconnected",clientId:null,subscribedTopics:[],error:null,reconnectAttempt:0},events:[],maxEvents:100},{useStore:usePubSubStore}=createStore2(initialState,{setConnectionStatus:(store)=>(status)=>{store.connection.status=status},setClientId:(store)=>(clientId)=>{store.connection.clientId=clientId},setSubscribedTopics:(store)=>(topics)=>{store.connection.subscribedTopics=topics},setError:(store)=>(error)=>{store.connection.error=error},setReconnectAttempt:(store)=>(attempt)=>{store.connection.reconnectAttempt=attempt},addEvent:(store)=>(event)=>{let updated=[event,...store.events];store.events=updated.slice(0,store.maxEvents)},clearEvents:(store)=>()=>{store.events=[]},reset:(store)=>()=>{batch2(()=>{store.connection.status="disconnected",store.connection.clientId=null,store.connection.subscribedTopics=[],store.connection.error=null,store.connection.reconnectAttempt=0,store.events=[]})}});import{useEffect,useEffectEvent as useEffectEvent2,useRef}from"react";function buildWsUrl(config){if(config.wsUrl){let base=config.wsUrl.replace(/\/$/,""),path2=config.wsPath||"/api/events/subscribe",topics2=(config.topics||["*"]).join(",");return`${base}${path2}?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics2)}`}if(typeof window>"u")return"";let protocol=window.location.protocol==="https:"?"wss:":"ws:",host=window.location.host,path=config.wsPath||"/api/events/subscribe",topics=(config.topics||["*"]).join(",");return`${protocol}//${host}${path}?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics)}`}var eventIdCounter=0;function usePubSub(config){let store=usePubSubStore(),wsRef=useRef(null),heartbeatRef=useRef(null),reconnectTimeoutRef=useRef(null),isDestroyedRef=useRef(!1),configRef=useRef(config);configRef.current=config;let autoReconnect=config.autoReconnect??!0,maxReconnectAttempts=config.maxReconnectAttempts??10,reconnectBaseDelay=config.reconnectBaseDelay??1000,reconnectMaxDelay=config.reconnectMaxDelay??30000,heartbeatInterval=config.heartbeatInterval??30000,debug=config.debug??!1,log=(...args)=>{if(debug)console.log("[usePubSub]",...args)},clearHeartbeat=()=>{if(heartbeatRef.current)clearInterval(heartbeatRef.current),heartbeatRef.current=null},clearReconnectTimeout=()=>{if(reconnectTimeoutRef.current)clearTimeout(reconnectTimeoutRef.current),reconnectTimeoutRef.current=null},startHeartbeat=(ws)=>{clearHeartbeat(),heartbeatRef.current=setInterval(()=>{if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({type:"ping"}))},heartbeatInterval)},handleMessage=useEffectEvent2((event)=>{try{let message=JSON.parse(event.data);switch(message.type){case"connected":store.setConnectionStatus("connected"),store.setClientId(message.clientId),store.setSubscribedTopics(message.subscribedTopics),store.setReconnectAttempt(0),store.setError(null),log("Connected, clientId:",message.clientId);break;case"subscribed":store.setSubscribedTopics(message.topics),log("Subscribed to:",message.topics);break;case"event":{let pubsubEvent={id:`evt_${Date.now()}_${eventIdCounter++}`,topic:message.topic,data:message.data,timestamp:message.timestamp,receivedAt:Date.now(),messageId:message.messageId,isRedelivery:message.isRedelivery};if(store.addEvent(pubsubEvent),message.messageId&&wsRef.current?.readyState===WebSocket.OPEN)wsRef.current.send(JSON.stringify({type:"ack",messageId:message.messageId}));break}case"pong":break;case"error":store.setError(Error(message.error)),log("Server error:",message.error);break}}catch{log("Failed to parse message")}}),scheduleReconnect=useEffectEvent2((attempt)=>{if(isDestroyedRef.current)return;if(!autoReconnect)return;if(attempt>=maxReconnectAttempts){store.setConnectionStatus("disconnected"),store.setError(Error("Max reconnection attempts reached")),log("Max reconnect attempts reached");return}let delay=Math.min(reconnectBaseDelay*2**attempt,reconnectMaxDelay);log(`Reconnecting in ${delay}ms (attempt ${attempt+1}/${maxReconnectAttempts})`),store.setConnectionStatus("reconnecting"),store.setReconnectAttempt(attempt+1),clearReconnectTimeout(),reconnectTimeoutRef.current=setTimeout(()=>{if(!isDestroyedRef.current)connectWs()},delay)}),connectWs=useEffectEvent2(()=>{if(isDestroyedRef.current)return;if(wsRef.current?.readyState===WebSocket.OPEN)return;if(!configRef.current.userId)return;if(wsRef.current){if(wsRef.current.onopen=null,wsRef.current.onmessage=null,wsRef.current.onerror=null,wsRef.current.onclose=null,wsRef.current.readyState===WebSocket.OPEN||wsRef.current.readyState===WebSocket.CONNECTING)wsRef.current.close();wsRef.current=null}let url=buildWsUrl(configRef.current);if(!url)return;store.setConnectionStatus("connecting"),store.setError(null),log("Connecting to:",url);let ws=new WebSocket(url);wsRef.current=ws,ws.onopen=()=>{log("WebSocket opened"),startHeartbeat(ws)},ws.onmessage=handleMessage,ws.onerror=()=>{log("WebSocket error"),store.setError(Error("WebSocket connection error"))},ws.onclose=(event)=>{if(log("WebSocket closed",event.code,event.reason),clearHeartbeat(),store.setConnectionStatus("disconnected"),store.setClientId(null),!isDestroyedRef.current&&event.code!==4001){let currentAttempt=store.connection.reconnectAttempt;scheduleReconnect(currentAttempt)}}}),disconnect=useEffectEvent2(()=>{if(clearHeartbeat(),clearReconnectTimeout(),wsRef.current){if(wsRef.current.onopen=null,wsRef.current.onmessage=null,wsRef.current.onerror=null,wsRef.current.onclose=null,wsRef.current.readyState===WebSocket.OPEN||wsRef.current.readyState===WebSocket.CONNECTING)wsRef.current.close();wsRef.current=null}store.setConnectionStatus("disconnected"),store.setClientId(null)}),subscribe=useEffectEvent2((topics)=>{if(wsRef.current?.readyState!==WebSocket.OPEN)return;wsRef.current.send(JSON.stringify({type:"subscribe",topics}))}),unsubscribe=useEffectEvent2((topics)=>{if(wsRef.current?.readyState!==WebSocket.OPEN)return;wsRef.current.send(JSON.stringify({type:"unsubscribe",topics}))}),getEventsByTopic=useEffectEvent2((topic)=>{return store.events.filter((e)=>e.topic===topic)});return useEffect(()=>{if(isDestroyedRef.current=!1,config.userId)connectWs();return()=>{isDestroyedRef.current=!0,disconnect()}},[config.userId]),useEffect(()=>{if(store.connection.status==="connected"&&config.topics)subscribe(config.topics)},[config.topics?.join(",")]),{isConnected:store.connection.status==="connected",isConnecting:store.connection.status==="connecting"||store.connection.status==="reconnecting",clientId:store.connection.clientId,subscribedTopics:store.connection.subscribedTopics,events:store.events,error:store.connection.error,reconnectAttempt:store.connection.reconnectAttempt,connect:connectWs,disconnect,subscribe,unsubscribe,clearEvents:store.clearEvents,getEventsByTopic}}import{randomUUID as randomUUID5}from"crypto";var import_fast_decode_uri_component=__toESM(require_fast_decode_uri_component(),1);import{Elysia,NotFoundError}from"elysia";var fs,path,isBun=typeof Bun<"u"&&!!Bun.file;function getBuiltinModule(){if(fs||(fs=process.getBuiltinModule("fs/promises")),path||(path=process.getBuiltinModule("path")),!path){console.warn("@elysiajs/static require path to be available.");return}return[fs,path]}async function listHTMLFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*.html"),files=[];for await(let file of glob.scan(dir))files.push(path.join(dir,file));return files}return[]}async function listFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*"),files2=[];for await(let file of glob.scan(dir))files2.push(path.join(dir,file));return files2}let files=await fs.readdir(dir).catch(()=>[]);return(await Promise.all(files.map(async(name)=>{let file=dir+path.sep+name,stats=await fs.stat(file).catch(()=>null);return stats?stats.isDirectory()?await listFiles(file):[path.resolve(dir,file)]:[]}))).flat()}function fileExists(path2){return fs||getBuiltinModule(),fs.stat(path2).then(()=>!0,()=>!1)}class LRUCache{constructor(max=250,ttl=10800){this.max=max,this.ttl=ttl,this.map=new Map}get(key){let entry=this.map.get(key);if(entry)return entry[1]<=Date.now()?void this.delete(key):(this.map.delete(key),this.map.set(key,entry),entry[0])}set(key,value){if(this.interval||(this.interval=setInterval(()=>{let now=Date.now();for(let[key2,entry]of this.map)entry[1]<=now&&this.map.delete(key2)},this.ttl)),this.map.has(key))this.map.delete(key);else if(this.map.size>=this.max){let oldestKey=this.map.keys().next().value;oldestKey!==void 0&&this.delete(oldestKey)}this.map.set(key,[value,Date.now()+this.ttl*1000])}delete(key){this.map.get(key)&&this.map.delete(key)}clear(){this.map.clear()}size(){return this.map.size}[Symbol.dispose](){this.interval&&clearInterval(this.interval)}}function isCached(headers,etag,filePath){if(headers["cache-control"]&&/no-cache|no-store/.test(headers["cache-control"]))return!1;if("if-none-match"in headers){let ifNoneMatch=headers["if-none-match"];return ifNoneMatch==="*"?!0:ifNoneMatch===null||typeof etag!="string"?!1:ifNoneMatch===etag}if(headers["if-modified-since"]){let ifModifiedSince=headers["if-modified-since"];try{return fs.stat(filePath).then((stat)=>{if(stat.mtime!==void 0&&stat.mtime.getTime()<=Date.parse(ifModifiedSince))return!0})}catch{}}return!1}var Crypto;function getFile(path2){return isBun?Bun.file(path2):(fs||getBuiltinModule(),fs.readFile(path2))}async function generateETag(file){return isBun?new Bun.CryptoHasher("md5").update(await file.arrayBuffer()).digest("base64"):(Crypto||(Crypto=process.getBuiltinModule("crypto")),Crypto?Crypto.createHash("md5").update(file).digest("base64"):void console.warn("[@elysiajs/static] crypto is required to generate etag."))}var isNotEmpty=(obj)=>{if(!obj)return!1;for(let _ in obj)return!0;return!1};async function staticPlugin({assets="public",prefix="/public",staticLimit=1024,alwaysStatic=!1,ignorePatterns=[".DS_Store",".git",".env"],headers:initialHeaders,maxAge=86400,directive="public",etag:useETag=!0,extension=!0,indexHTML=!0,decodeURI,silent}={}){if(typeof process>"u"||typeof process.getBuiltinModule>"u")return silent||console.warn("[@elysiajs/static] require process.getBuiltinModule. Static plugin is disabled"),new Elysia;let builtinModule=getBuiltinModule();if(!builtinModule)return new Elysia;let[fs2,path2]=builtinModule,normalizePath=path2.sep!=="/"?(p)=>p.replace(/\\/g,"/"):(p)=>p,fileCache=new LRUCache;prefix===path2.sep&&(prefix="");let assetsDir=path2.resolve(assets),shouldIgnore=ignorePatterns.length?(file)=>ignorePatterns.find((pattern)=>typeof pattern=="string"?pattern.includes(file):pattern.test(file)):()=>!1,app=new Elysia({name:"static",seed:prefix});if(alwaysStatic){let files=await listFiles(path2.resolve(assets));if(files.length<=staticLimit)for(let absolutePath of files){let handleCache2=function({headers:requestHeaders}){if(etag){let cached=isCached(requestHeaders,etag,absolutePath);if(cached===!0)return new Response(null,{status:304,headers:isNotEmpty(initialHeaders)?initialHeaders:void 0});if(cached!==!1){let cache2=fileCache.get(pathName);return cache2?cache2.clone():cached.then((cached2)=>{if(cached2)return new Response(null,{status:304,headers:initialHeaders||void 0});let response2=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(prefix,response2),response2.clone()})}}let cache=fileCache.get(pathName);if(cache)return cache.clone();let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()};var handleCache=handleCache2;if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,"");decodeURI&&(relativePath=import_fast_decode_uri_component.default(relativePath)??relativePath);let pathName=normalizePath(path2.join(prefix,relativePath));if(isBun&&absolutePath.endsWith(".html")){let htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default);continue}extension||(pathName=normalizePath(pathName.slice(0,pathName.lastIndexOf("."))));let file=isBun?getFile(absolutePath):await getFile(absolutePath);if(!file)return silent||console.warn(`[@elysiajs/static] Failed to load file: ${absolutePath}`),new Elysia;let etag=await generateETag(file);app.get(pathName,useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0)),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0))}return app}if(!(`GET_${prefix}/*`in app.routeTree)){if(isBun){let htmls=await listHTMLFiles(path2.resolve(assets));for(let absolutePath of htmls){if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,""),pathName=normalizePath(path2.join(prefix,relativePath)),htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default)}}app.onError(()=>{}).get(`${prefix.endsWith("/")?prefix.slice(0,-1):prefix}/*`,async({params,headers:requestHeaders})=>{let pathName=normalizePath(path2.join(assets,decodeURI?import_fast_decode_uri_component.default(params["*"])??params["*"]:params["*"]));if(shouldIgnore(pathName))throw new NotFoundError;let cache=fileCache.get(pathName);if(cache)return cache.clone();try{let fileStat=await fs2.stat(pathName).catch(()=>null);if(!fileStat)throw new NotFoundError;if(!indexHTML&&fileStat.isDirectory())throw new NotFoundError;let file;if(!isBun&&indexHTML){let htmlPath=path2.join(pathName,"index.html"),cache2=fileCache.get(htmlPath);if(cache2)return cache2.clone();await fileExists(htmlPath)&&(file=await getFile(htmlPath))}if(!file&&!fileStat.isDirectory()&&await fileExists(pathName))file=await getFile(pathName);else throw new NotFoundError;if(!useETag)return new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0);let etag=await generateETag(file);if(etag&&await isCached(requestHeaders,etag,pathName))return new Response(null,{status:304});let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()}catch(error){throw error instanceof NotFoundError?error:(silent||console.error("[@elysiajs/static]",error),new NotFoundError)}})}return app}init_Services();init_ApiKey();init_Captcha();import{pushSchema}from"drizzle-kit/api";import{and as and10,eq as eq29}from"drizzle-orm";import{drizzle as drizzle2}from"drizzle-orm/node-postgres";import{pgSchema as pgSchema2}from"drizzle-orm/pg-core";import Elysia31 from"elysia";var SYSTEM_TABLES=[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]}];var METHOD_MAP={GET:["GET"],POST:["POST"],PUT:["PUT"],DELETE:["DELETE"],PATCH:["PATCH"],TOGGLE:["PATCH"],VERIFICATION:["POST"]};function buildAuthPublicRoutes(config,basePath){let routes=[],auth=config.authentication;if(!auth)return routes;if(auth.login?.enabled&&auth.login?.isPublic)routes.push({path:auth.login.route||`${basePath}/auth/login`,method:"POST",source:"auth"});if(auth.register?.enabled&&auth.register?.isPublic)routes.push({path:auth.register.route||`${basePath}/auth/register`,method:"POST",source:"auth"});if(auth.logout?.enabled&&auth.logout?.isPublic)routes.push({path:auth.logout.route||`${basePath}/auth/logout`,method:"POST",source:"auth"});if(auth.refresh?.enabled&&auth.refresh?.isPublic)routes.push({path:auth.refresh.route||`${basePath}/auth/refresh`,method:"POST",source:"auth"});if(auth.passwordReset?.enabled&&auth.passwordReset?.isPublic){let baseRoute=auth.passwordReset.route||`${basePath}/auth/password-reset`;routes.push({path:`${baseRoute}/request`,method:"POST",source:"auth"},{path:`${baseRoute}/confirm`,method:"POST",source:"auth"})}if(auth.passwordChange?.enabled&&auth.passwordChange?.isPublic)routes.push({path:auth.passwordChange.route||`${basePath}/auth/password-change`,method:"POST",source:"auth"});if(auth.magicLink?.enabled&&auth.magicLink?.isPublic)routes.push({path:auth.magicLink.route||`${basePath}/auth/magic-link`,method:"POST",source:"auth"},{path:auth.magicLink.verifyRoute||`${basePath}/auth/magic-link/verify`,method:"GET",source:"auth"});if(auth.register?.enabled&&auth.register?.emailVerification?.enabled)routes.push({path:`${basePath}/verify-email`,method:"GET",source:"auth"},{path:`${basePath}/resend-verification`,method:"POST",source:"auth"});if(auth.invite?.enabled&&auth.invite?.isPublic)routes.push({path:auth.invite.route||`${basePath}/auth/invite`,method:"POST",source:"auth"});if(auth.invite?.enabled){let inviteRoute=auth.invite.route||`${basePath}/auth/invite`;routes.push({path:`${inviteRoute}/verify`,method:"POST",source:"auth"})}if(auth.passwordSet?.enabled)routes.push({path:auth.passwordSet.route||`${basePath}/auth/password-set`,method:"POST",source:"auth"});if(auth.captcha?.enabled&&auth.captcha?.isPublic){let baseRoute=auth.captcha.route||`${basePath}/auth/captcha`;routes.push({path:`${baseRoute}/generate`,method:"GET",source:"auth"},{path:`${baseRoute}/validate`,method:"POST",source:"auth"})}if(auth.sessions?.enabled){let sessionsRoute=auth.sessions.route||`${basePath}/auth/sessions`;routes.push({path:`${sessionsRoute}/approve`,method:"POST",source:"auth"},{path:`${sessionsRoute}/reject`,method:"POST",source:"auth"},{path:`${sessionsRoute}/approve-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/reject-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/approval-status`,method:"GET",source:"auth"})}if(auth.oauth?.enabled){let oauthBase=auth.oauth.basePath||`${basePath}/auth/oauth`,knownProviders=["google","github","microsoft","discord","facebook","twitter","apple","custom"];routes.push({path:`${oauthBase}/providers`,method:"GET",source:"auth"});for(let provider of knownProviders)routes.push({path:`${oauthBase}/${provider}`,method:"GET",source:"auth"},{path:`${oauthBase}/${provider}/callback`,method:"GET",source:"auth"})}return routes}function buildEntityPublicRoutes(entities,basePath,_schema){let routes=[];for(let entity of entities){if(!entity.is_public)continue;let camelName=entity.table_name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase()),entityPath=`${basePath}/${camelName}`;for(let[nucleusMethod,isPublic]of Object.entries(entity.is_public)){if(!isPublic)continue;let httpMethods=METHOD_MAP[nucleusMethod];if(!httpMethods)continue;for(let method of httpMethods)if(method==="GET")routes.push({path:entityPath,method:"GET",source:"entity"}),routes.push({path:`${entityPath}/:id`,method:"GET",source:"entity"});else if(method==="POST")routes.push({path:entityPath,method:"POST",source:"entity"});else if(method==="PUT"||method==="PATCH")routes.push({path:`${entityPath}/:id`,method,source:"entity"});else if(method==="DELETE")routes.push({path:`${entityPath}/:id`,method:"DELETE",source:"entity"})}}return routes}function buildSystemTablePublicRoutes(systemTables2,basePath,schema){return buildEntityPublicRoutes(systemTables2,basePath,schema)}function buildPublicRoutes(config,systemTables2,basePath="",schema="public"){let authRoutes=buildAuthPublicRoutes(config,basePath),entityRoutes=buildEntityPublicRoutes(config.entities||[],basePath,schema),systemRoutes=buildSystemTablePublicRoutes(systemTables2,basePath,schema),pubsubRoutes=[];if(config.pubsub?.enabled){let pubsubBasePath=config.pubsub.basePath||"/subs",wsPath=config.pubsub.wsPath||"/api/events/subscribe";pubsubRoutes.push({path:`${pubsubBasePath}/:topic`,method:"POST",source:"system"},{path:wsPath,method:"GET",source:"system"})}let paymentRoutes=[];if(config.payment?.enabled){let paymentBasePath=config.payment.basePath||"/payment";paymentRoutes.push({path:`${paymentBasePath}/callback`,method:"POST",source:"system"},{path:`${paymentBasePath}/callback`,method:"OPTIONS",source:"system"},{path:`${paymentBasePath}/bin-query`,method:"POST",source:"system"})}let tenantRoutes=[];if(config.database?.isMultiTenant)tenantRoutes.push({path:`${basePath}/tenants/check-subdomain/:subdomain`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/self-signup`,method:"POST",source:"system"});let customRoutes=[{path:"/nucleus-core",method:"GET",source:"custom"},{path:"/public",method:"GET",source:"custom"},{path:"/docs",method:"GET",source:"custom"},{path:"/docs/json",method:"GET",source:"custom"},{path:"/swagger",method:"GET",source:"custom"},{path:"/swagger/json",method:"GET",source:"custom"}];return[...authRoutes,...entityRoutes,...systemRoutes,...pubsubRoutes,...paymentRoutes,...tenantRoutes,...customRoutes]}function isPublicRoute(publicRoutes,path2,method){let normalizedPath=path2.replace(/\/$/,""),normalizedMethod=method.toUpperCase();for(let route of publicRoutes){if(route.method!==normalizedMethod)continue;if(matchPath(route.path,normalizedPath))return!0}return!1}function matchPath(pattern,path2){if(pattern===path2)return!0;let patternParts=pattern.split("/").filter(Boolean),pathParts=path2.split("/").filter(Boolean);if(patternParts.length!==pathParts.length)return!1;for(let i=0;i<patternParts.length;i++){let patternPart=patternParts[i],pathPart=pathParts[i];if(patternPart?.startsWith(":"))continue;if(patternPart!==pathPart)return!1}return!0}import{and as and5,asc,desc as desc3,eq as eq10,ilike,inArray as inArray3,notInArray,or}from"drizzle-orm";import{drizzle}from"drizzle-orm/node-postgres";import{Elysia as Elysia3,t as t3}from"elysia";init_Authorization();init_utils5();init_storage();import{t as t2}from"elysia";function buildBodySchemaFromEntityColumns(entityColumns){let properties={};if(!entityColumns||entityColumns.length===0)return t2.Object({},{additionalProperties:!0});for(let col2 of entityColumns)switch(col2.type?.toLowerCase()||"string"){case"integer":case"int":case"serial":case"bigserial":case"numeric":case"decimal":properties[col2.name]=col2.notNull?t2.Number():t2.Optional(t2.Number());break;case"boolean":properties[col2.name]=col2.notNull?t2.Boolean():t2.Optional(t2.Boolean());break;case"timestamp":case"timestamptz":case"date":properties[col2.name]=col2.notNull?t2.String({format:"date-time"}):t2.Optional(t2.String({format:"date-time"}));break;case"json":case"jsonb":properties[col2.name]=t2.Optional(t2.Unknown());break;case"uuid":properties[col2.name]=col2.notNull?t2.String({format:"uuid"}):t2.Optional(t2.String({format:"uuid"}));break;default:properties[col2.name]=col2.notNull?t2.String():t2.Optional(t2.String())}return t2.Object(properties,{additionalProperties:!0})}function createBulkUpdateSchema(entityColumns){return t2.Array(t2.Object({id:t2.String(),data:buildBodySchemaFromEntityColumns(entityColumns)}))}function createEntityRoutes(app,config){let{db,schemaTables,schemaRelations,entities,logger:logger2,databaseUrl,dbPool,storage,authorization,authMode,idpUrl,tenantRegistry}=config,getReqSchema=(request)=>{if(!tenantRegistry)return{tables:schemaTables,relations:schemaRelations};let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return{tables:schemaTables,relations:schemaRelations};let ctx=tenantRegistry.getSchemaContext(schemaName);return ctx?{tables:ctx.schemaTables,relations:ctx.schemaRelations}:{tables:schemaTables,relations:schemaRelations}},storageConfig=mergeStorageConfig(storage),authEnabled=authorization?.enabled??!1,isConsumerMode=authMode==="consumer";if(!db)return app;function snakeToCamel(s){return s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase())}let allTables=Object.keys(schemaTables),entityTableNames=entities.map((e)=>snakeToCamel(e.table_name)),systemTableNames=allTables.filter((tbl)=>!entityTableNames.includes(tbl)),AUTH_TABLES=["userSessions","passwordResetTokens","magicLinkTokens"],EMAIL_REQUIRED_TABLES=["passwordResetTokens","magicLinkTokens"],FORM_DATA_TABLES=["files"],systemTableDefMap=new Map(SYSTEM_TABLES.map((t4)=>[snakeToCamel(t4.table_name),t4])),systemTables2=systemTableNames.filter((name)=>{if(EMAIL_REQUIRED_TABLES.includes(name)&&!config.emailServiceAvailable)return logger2.info(`Skipping ${name} routes - email service not available`),!1;return!0}).map((name)=>{let def=systemTableDefMap.get(name);return{table_name:def?.table_name??name,group_name:AUTH_TABLES.includes(name)?"Authentication":name,is_form_data:FORM_DATA_TABLES.includes(name),bulk_endpoints_enabled:def?.bulk_endpoints_enabled??!1,excluded_methods:def?.excluded_methods?[...def.excluded_methods]:[],columns:def?.columns?[...def.columns]:void 0}}),allEntities=[...entities,...systemTables2];logger2.info(`All entities: ${allEntities.map((e)=>e.table_name).join(", ")}`);for(let table of allEntities){let rawTableName=table.table_name,tableName=snakeToCamel(rawTableName),swaggerTag=table.group_name||rawTableName,defaultDrizzleTable=schemaTables[tableName];if(!defaultDrizzleTable)continue;let tableRelations=schemaRelations[`${tableName}Relations`];logger2.info(`Creating routes for table: ${tableName}`);let defaultTableColumns=defaultDrizzleTable,defaultIdCol=defaultTableColumns.id,database=db,drizzleTable=defaultDrizzleTable,tableColumns=defaultTableColumns,idCol=defaultIdCol,resolveCol=(field)=>tableColumns[field]??tableColumns[snakeToCamel(field)],getTableForRequest=(request)=>{if(!tenantRegistry)return{drizzleTable,tableColumns,idCol,resolveCol,schemaTables,schemaRelations};let reqSchema=getReqSchema(request),reqTable=reqSchema.tables[tableName]||drizzleTable,reqCols=reqTable,reqIdCol=reqCols.id;return{drizzleTable:reqTable,tableColumns:reqCols,idCol:reqIdCol,resolveCol:(field)=>reqCols[field]??reqCols[snakeToCamel(field)],schemaTables:reqSchema.tables,schemaRelations:reqSchema.relations}},bulkUpdateSchema=createBulkUpdateSchema(table.columns),bulkDeleteSchema=t3.Array(t3.String()),performAuthCheck=async(request,method,reqFields,reqRelations)=>{let userId=request.headers.get("x-user-id");if(!authEnabled||!userId)return null;if(isConsumerMode){let userClaims=(request.headers.get("x-user-claims")||"").split(",").filter(Boolean),userRoles=(request.headers.get("x-user-roles")||"").split(",").filter(Boolean);if(idpUrl){let accessToken=request.headers.get("x-access-token")||(request.headers.get("cookie")||"").match(/access_token=([^;]+)/)?.[1]||"";return checkAuthorizationViaIDP({idpUrl,accessToken,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2})}return checkAuthorizationFromJWT({userClaims,userRoles,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2})}let reqCtx=getTableForRequest(request);return checkAuthorization({userId,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,db:database,schemaTables:reqCtx.schemaTables,logger:logger2})},entityRoutes=new Elysia3({prefix:`/${tableName}`});if(!table.excluded_methods?.includes("GET"))entityRoutes.get("/",async(ctx)=>{if(!database)return{success:!1,message:"DB not initialized"};let{drizzleTable:drizzleTable2,resolveCol:resolveCol2,schemaRelations:schemaRelations2}=getTableForRequest(ctx.request),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=Object.keys(schemaRelations2).filter((k)=>k.startsWith(`${tableName}Relations`)).map((k)=>k.replace("Relations","")),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};let q=parseQueryParams(ctx.query),conditions=[];if(authEnabled&&authResult?.scopeFilters)for(let[field,value]of Object.entries(authResult.scopeFilters)){let col2=resolveCol2(field);if(col2)conditions.push(eq10(col2,value))}if(q.search&&q.searchFields){let searchConditions=q.searchFields.map((f)=>{let trimmed=f.trim(),col2=resolveCol2(trimmed);return col2?ilike(col2,`%${q.search}%`):null}).filter((c)=>c!==null);if(searchConditions.length>0){let orCondition=or(...searchConditions);if(orCondition)conditions.push(orCondition)}}if(q.filters){let{ne,gt,gte,lt,lte,like,isNull,isNotNull}=await import("drizzle-orm");for(let filter of q.filters){let col2=resolveCol2(filter.field);if(!col2)continue;switch(filter.operator){case"eq":conditions.push(eq10(col2,filter.value));break;case"neq":conditions.push(ne(col2,filter.value));break;case"gt":conditions.push(gt(col2,filter.value));break;case"gte":conditions.push(gte(col2,filter.value));break;case"lt":conditions.push(lt(col2,filter.value));break;case"lte":conditions.push(lte(col2,filter.value));break;case"like":conditions.push(like(col2,filter.value));break;case"ilike":conditions.push(ilike(col2,filter.value));break;case"in":conditions.push(inArray3(col2,filter.value));break;case"notIn":conditions.push(notInArray(col2,filter.value));break;case"isNull":conditions.push(isNull(col2));break;case"isNotNull":conditions.push(isNotNull(col2));break}}}let baseQuery=database.select().from(drizzleTable2);if(conditions.length>0){let{and:and6}=await import("drizzle-orm"),combined=and6(...conditions);if(combined)baseQuery=baseQuery.where(combined)}if(q.sort&&q.sort.length>0){let orderClauses=q.sort.map((s)=>{let col2=resolveCol2(s.field);if(!col2)return null;return s.direction==="desc"?desc3(col2):asc(col2)}).filter((o)=>o!==null);if(orderClauses.length>0)baseQuery=baseQuery.orderBy(...orderClauses)}let page=q.page??1,limit=q.limit??20,offset=q.offset??(page-1)*limit,countQuery=database.select().from(drizzleTable2);if(conditions.length>0){let{and:and6}=await import("drizzle-orm"),combined=and6(...conditions);if(combined)countQuery.where(combined)}let totalItems=(await countQuery).length;baseQuery=baseQuery.limit(limit).offset(offset);let items=await baseQuery,meta=buildPaginationMeta(page,limit,offset,totalItems);if(authEnabled&&authResult?.allowedFields)items=filterResponseFields(items,authResult.allowedFields);return{success:!0,data:{items,meta}}},{detail:{tags:[swaggerTag],summary:`List ${tableName}`,description:`Get paginated list of ${tableName} records with filtering, sorting, and search`}}),entityRoutes.get("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2,schemaRelations:schemaRelations2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,q=parseQueryParams(ctx.query),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=q.with?.map((w)=>w.name),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};if(q.with&&q.with.length>0&&tableRelations&&(databaseUrl||dbPool)){let allowedWith=authEnabled&&authResult?.allowedRelations?q.with.filter((w)=>authResult.allowedRelations?.includes(w.name)??!1):q.with,result2=await(dbPool?drizzle(dbPool,{schema:{...schemaTables2,...schemaRelations2}}):drizzle(databaseUrl,{schema:{...schemaTables2,...schemaRelations2}})).query[tableName]?.findFirst({where:eq10(idCol2,params.id),with:allowedWith.reduce((acc,rel)=>{return acc[rel.name]=rel.limit?{limit:rel.limit}:!0,acc},{})});if(authEnabled&&authResult?.allowedFields&&result2)result2=filterResponseFields(result2,authResult.allowedFields);if(authEnabled&&authResult?.allowedRelations&&result2)result2=filterResponseRelations(result2,authResult.allowedRelations);return{success:!0,data:result2||null}}let result=(await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)))[0]||null;if(authEnabled&&authResult?.allowedFields&&result)result=filterResponseFields(result,authResult.allowedFields);return{success:!0,data:result}},{detail:{tags:[swaggerTag],summary:`Get ${tableName} by ID`,description:`Get a single ${tableName} record by its ID with optional relations`}}),entityRoutes.get("/distinct/:field",async(ctx)=>{let{drizzleTable:drizzleTable2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let params=ctx.params,col2=resolveCol2(params.field);if(!col2)return{success:!1,message:"Field not found"};return{success:!0,data:await database.selectDistinct({value:col2}).from(drizzleTable2)}},{detail:{tags:[swaggerTag],summary:`Get distinct ${tableName} values`,description:`Get distinct values for a specific field in ${tableName}`}});if(!table.excluded_methods?.includes("POST"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let userId=ctx.request.headers.get("x-user-id"),postFormAuthResult=await performAuthCheck(ctx.request,"POST");if(postFormAuthResult&&!postFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postFormAuthResult.reason||"Forbidden"};let{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}let uploadedFiles=null;if(files.length>0){if(uploadedFiles=await uploadFiles(files,storageConfig,table.table_name),uploadedFiles.failed.length>0&&uploadedFiles.success.length===0)return{success:!1,message:"File upload failed",errors:uploadedFiles.failed};if(uploadedFiles.success.length>0){let firstFile=uploadedFiles.success[0];if(firstFile){let ext=firstFile.originalName.split(".").pop()||"";payload={...payload,id:firstFile.id,name:firstFile.name,originalName:firstFile.originalName,path:firstFile.path,mimeType:firstFile.mimeType,size:firstFile.size,extension:ext,uploadedBy:userId}}}}if(userId)payload.createdBy=userId;let result=await database.insert(drizzleTable2).values(payload).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",userId:userId||void 0,summary:`Created ${table.table_name}`,newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{type:"formdata",body:t3.Object({[storageConfig.formData.dataField]:t3.Optional(t3.Union([t3.String(),t3.Any()])),[storageConfig.formData.filesField]:t3.Optional(t3.Union([t3.File(),t3.Array(t3.File())]))}),detail:{tags:[swaggerTag],summary:`Create ${tableName} with files`,description:`Create a new ${tableName} record with file upload support`}});else entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2,schemaTables:schemaTables2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let payload=ctx.body,userId=ctx.request.headers.get("x-user-id"),postAuthResult=await performAuthCheck(ctx.request,"POST");if(postAuthResult&&!postAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postAuthResult.reason||"Forbidden"};if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(userId)payload.createdBy=userId;if(tableName==="userRoles"&&payload.userId&&payload.roleId){let cols=drizzleTable2,existing=await database.select().from(drizzleTable2).where(and5(eq10(cols.userId,payload.userId),eq10(cols.roleId,payload.roleId))).limit(1);if(existing.length>0)return{success:!0,data:existing[0]}}let result=await database.insert(drizzleTable2).values(payload).returning();if(tableName==="roleClaims"&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName==="userRoles"&&payload.roleId&&payload.userId)try{let{roles:rolesTable,users:usersTable}=schemaTables2;if(rolesTable&&usersTable){if((await database.select().from(rolesTable).where(eq10(rolesTable.id,payload.roleId)).limit(1))[0]?.name==="godmin")await database.update(usersTable).set({isGod:!0}).where(eq10(usersTable.id,payload.userId))}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole create")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",userId:userId||void 0,summary:`Created ${table.table_name}`,newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Create ${tableName}`,description:`Create a new ${tableName} record`}});if(!table.excluded_methods?.includes("PUT"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),putFormAuthResult=await performAuthCheck(ctx.request,"PUT");if(putFormAuthResult&&!putFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putFormAuthResult.reason||"Forbidden"};let{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data,oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}let uploadedFiles=null;if(files.length>0)uploadedFiles=await uploadFiles(files,storageConfig,table.table_name);let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:{record:result[0],files:uploadedFiles?.success||[],fileErrors:uploadedFiles?.failed||[]}}},{type:"formdata",body:t3.Object({[storageConfig.formData.dataField]:t3.Optional(t3.Union([t3.String(),t3.Any()])),[storageConfig.formData.filesField]:t3.Optional(t3.Union([t3.File(),t3.Array(t3.File())]))}),detail:{tags:[swaggerTag],summary:`Update ${tableName} with files`,description:`Full update of ${tableName} record with file upload support`}});else entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),putAuthResult=await performAuthCheck(ctx.request,"PUT");if(putAuthResult&&!putAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Update ${tableName}`,description:`Full update of ${tableName} record`}});if(!table.excluded_methods?.includes("PATCH"))entityRoutes.patch("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),patchAuthResult=await performAuthCheck(ctx.request,"PATCH");if(patchAuthResult&&!patchAuthResult.authorized)return ctx.set.status=403,{success:!1,message:patchAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"PATCH",userId:userId||void 0,summary:`Patched ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Patch ${tableName}`,description:`Partial update of ${tableName} record`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),deleteAuthResult=await performAuthCheck(ctx.request,"DELETE");if(deleteAuthResult&&!deleteAuthResult.authorized)return ctx.set.status=403,{success:!1,message:deleteAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(await database.delete(drizzleTable2).where(eq10(idCol2,params.id)),tableName==="roleClaims"&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName==="userRoles"&&oldRecord[0])try{let deletedUserRole=oldRecord[0],rolesTable=schemaTables2.roles,usersTable=schemaTables2.users;if(rolesTable&&usersTable&&deletedUserRole.roleId&&deletedUserRole.userId){if((await database.select().from(rolesTable).where(eq10(rolesTable.id,deletedUserRole.roleId)).limit(1))[0]?.name==="godmin")await database.update(usersTable).set({isGod:!1}).where(eq10(usersTable.id,deletedUserRole.userId))}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole delete")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"DELETE",userId:userId||void 0,summary:`Deleted ${table.table_name} (${params.id})`,oldValues:oldRecord[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:null}},{detail:{tags:[swaggerTag],summary:`Delete ${tableName}`,description:`Delete a ${tableName} record`}});if(table.bulk_endpoints_enabled){if(!table.excluded_methods?.includes("POST"))entityRoutes.post("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};let userId=ctx.request.headers.get("x-user-id"),bulkPostAuth=await performAuthCheck(ctx.request,"POST");if(bulkPostAuth&&!bulkPostAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPostAuth.reason||"Forbidden"};try{let sanitizedItems=[];for(let raw of items){let payload=raw;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(userId)payload.createdBy=userId;sanitizedItems.push(payload)}return{success:!0,data:await database.transaction(async(tx)=>{let results=[];for(let payload of sanitizedItems){let result=await tx.insert(drizzleTable2).values(payload).returning();results.push(result[0])}return results})}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:t3.Array(t3.Object({},{additionalProperties:!0})),detail:{tags:[swaggerTag],summary:`Bulk create ${tableName}`,description:`Create multiple ${tableName} records`}});if(!table.excluded_methods?.includes("PUT"))entityRoutes.put("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};let userId=ctx.request.headers.get("x-user-id"),bulkPutAuth=await performAuthCheck(ctx.request,"PUT");if(bulkPutAuth&&!bulkPutAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPutAuth.reason||"Forbidden"};try{return{success:!0,data:await database.transaction(async(tx)=>{let results=[];for(let item of items){let payload=item.data;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await tx.update(drizzleTable2).set(payload).where(eq10(idCol2,item.id)).returning();results.push(result[0])}return results})}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:bulkUpdateSchema,detail:{tags:[swaggerTag],summary:`Bulk update ${tableName}`,description:`Update multiple ${tableName} records`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let ids=ctx.body;if(!Array.isArray(ids))return{success:!1,message:"Body must be an array of ids"};let bulkDeleteAuth=await performAuthCheck(ctx.request,"DELETE");if(bulkDeleteAuth&&!bulkDeleteAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkDeleteAuth.reason||"Forbidden"};try{return await database.transaction(async(tx)=>{for(let id of ids)await tx.delete(drizzleTable2).where(eq10(idCol2,id))}),{success:!0,data:{deleted:ids.length}}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:bulkDeleteSchema,detail:{tags:[swaggerTag],summary:`Bulk delete ${tableName}`,description:`Delete multiple ${tableName} records`}})}app.use(entityRoutes)}return app}import Elysia4,{t as t4}from"elysia";function parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h)$/);if(!match||!match[1]||!match[2])return 5000;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;default:return 5000}}function createMonitoringRoutes(config){let{monitoringService,logger:logger2,endpoints}=config,plugin=new Elysia4({prefix:endpoints.basePath});if(!endpoints.enabled)return plugin;if(endpoints.stream.enabled)plugin.get(endpoints.stream.path,async function*({request}){logger2.info("[Monitoring] SSE stream connected");let intervalMs=parseTimeToMs(endpoints.stream.interval),isConnected=!0;request.signal.addEventListener("abort",()=>{isConnected=!1,logger2.info("[Monitoring] SSE stream disconnected")});let initialSnapshot=await monitoringService.getLatestSnapshot();if(initialSnapshot)yield{event:"snapshot",data:JSON.stringify(initialSnapshot)};while(isConnected){if(await new Promise((resolve2)=>setTimeout(resolve2,intervalMs)),!isConnected)break;let snapshot=await monitoringService.getLatestSnapshot();if(snapshot)yield{event:"snapshot",data:JSON.stringify(snapshot)};let alerts=monitoringService.getActiveAlerts();if(alerts.length>0)yield{event:"alerts",data:JSON.stringify(alerts)}}},{detail:{tags:["Monitoring"],summary:"Stream real-time monitoring data",description:"Server-Sent Events stream for real-time monitoring metrics"}});if(endpoints.snapshot.enabled)plugin.get(endpoints.snapshot.path,async()=>{let snapshot=await monitoringService.getLatestSnapshot();if(!snapshot)return{isSuccess:!1,message:"No monitoring data available",data:null};return{isSuccess:!0,message:"Current monitoring snapshot",data:snapshot}},{detail:{tags:["Monitoring"],summary:"Get current monitoring snapshot",description:"Returns the latest monitoring metrics snapshot"}});if(endpoints.history.enabled)plugin.get(endpoints.history.path,async({query})=>{let minutes=Math.min(query.minutes?parseInt(String(query.minutes),10):60,endpoints.history.maxMinutes),history=await monitoringService.getHistory(minutes);return{isSuccess:!0,message:`Monitoring history for last ${minutes} minutes`,data:{minutes,count:history.length,snapshots:history}}},{query:t4.Object({minutes:t4.Optional(t4.Numeric())}),detail:{tags:["Monitoring"],summary:"Get monitoring history",description:"Returns historical monitoring data for the specified time range"}});if(endpoints.alerts.enabled)plugin.get(endpoints.alerts.path,()=>{let alerts=monitoringService.getActiveAlerts();return{isSuccess:!0,message:"Active alerts",data:{count:alerts.length,alerts}}},{detail:{tags:["Monitoring"],summary:"Get active alerts",description:"Returns all currently active monitoring alerts"}}),plugin.post(`${endpoints.alerts.path}/:alertId/acknowledge`,({params})=>{if(!monitoringService.acknowledgeAlert(params.alertId))return{isSuccess:!1,message:"Alert not found",data:null};return{isSuccess:!0,message:"Alert acknowledged",data:{alertId:params.alertId}}},{params:t4.Object({alertId:t4.String()}),detail:{tags:["Monitoring"],summary:"Acknowledge an alert",description:"Mark an alert as acknowledged"}});return logger2.info(`[Monitoring] Routes enabled at ${endpoints.basePath} (stream: ${endpoints.stream.enabled}, snapshot: ${endpoints.snapshot.enabled}, history: ${endpoints.history.enabled}, alerts: ${endpoints.alerts.enabled})`),plugin}import{eq as eq11}from"drizzle-orm";import{Elysia as Elysia5,t as t5}from"elysia";var RESERVED_SUBDOMAINS=["www","api","app","admin","dashboard","mail","ftp","cdn","static","assets","docs","help","support","status","blog","dev","staging","test","demo","localhost"],DEFAULT_SELF_SIGNUP_LIMITS={maxSignupsPerIpPerWindow:3,ipWindowMs:3600000,maxTenantsPerEmail:1};var col2=(table,name)=>table[name];function createCheckSubdomainRoute(config){let checkRoute=new Elysia5;return checkRoute.get("/tenants/check-subdomain/:subdomain",async(ctx)=>{let{subdomain}=ctx.params,normalized=subdomain.toLowerCase().trim();if(!/^[a-z][a-z0-9-]*$/.test(normalized)||normalized.length<2||normalized.length>63)return ctx.set.status=400,{isSuccess:!1,message:"Invalid subdomain format. Must start with a letter, contain only lowercase letters, numbers, and hyphens, and be 2-63 characters.",data:{available:!1,subdomain:normalized}};if(RESERVED_SUBDOMAINS.includes(normalized))return{isSuccess:!0,message:"Subdomain is reserved",data:{available:!1,subdomain:normalized}};let tenantRegistry=config.getTenantRegistry(),db=config.getDb();if(tenantRegistry){if(tenantRegistry.getActiveTenants().find((t6)=>t6.subdomain===normalized))return{isSuccess:!0,message:"Subdomain is already taken",data:{available:!1,subdomain:normalized}}}if(db&&tenantRegistry){let tenantsTable=tenantRegistry.getMainContext().schemaTables.tenants;if(tenantsTable)try{if((await db.select().from(tenantsTable).where(eq11(col2(tenantsTable,"subdomain"),normalized)).limit(1)).length>0)return{isSuccess:!0,message:"Subdomain is already taken",data:{available:!1,subdomain:normalized}}}catch{}}return{isSuccess:!0,message:"Subdomain is available",data:{available:!0,subdomain:normalized}}},{params:t5.Object({subdomain:t5.String({minLength:2,maxLength:63})}),detail:{tags:["Tenants"],summary:"Check subdomain availability",description:"Public endpoint to check if a subdomain is available for registration. No authentication required."}}),checkRoute}init_Logger2();import{eq as eq12}from"drizzle-orm";import{Elysia as Elysia6,t as t6}from"elysia";var col3=(table,name)=>table[name];function createManageRoutes(config){let log=config.logger.scoped(TENANT_SUSPEND),manageRoutes=new Elysia6;return manageRoutes.get("/tenants",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available",data:null};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required",data:null};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required",data:null};let allTenants=[...tenantRegistry.getActiveTenants(),...Array.from(getAllTenants(tenantRegistry)).filter((t7)=>t7.status!=="active")];return{success:!0,message:`Found ${allTenants.length} tenants`,data:{items:allTenants.map((t7)=>({id:t7.id,subdomain:t7.subdomain,schemaName:t7.schemaName,companyId:t7.companyId,companyName:t7.companyName,godAdminEmail:t7.godAdminEmail,status:t7.status,plan:t7.plan,domain:t7.domain,maxUsers:t7.maxUsers,provisionedAt:t7.provisionedAt,suspendedAt:t7.suspendedAt})),totalCount:allTenants.length}}},{detail:{tags:["Tenants"],summary:"List tenants",description:"List all tenants in the platform. Requires godmin privileges."}}),manageRoutes.get("/tenants/:id",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available",data:null};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required",data:null};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required",data:null};let{id}=ctx.params,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found",data:null};let features=tenantRegistry.getTenantFeatures(id);return{success:!0,message:"Tenant found",data:{...tenant,features:features.map((f)=>({featureName:f.featureName,enabled:f.enabled}))}}},{detail:{tags:["Tenants"],summary:"Get tenant details",description:"Get detailed information about a specific tenant. Requires godmin privileges."}}),manageRoutes.post("/tenants/:id/suspend",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let{id}=ctx.params,body=ctx.body,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found"};if(tenant.status==="suspended")return ctx.set.status=400,{success:!1,message:"Tenant is already suspended"};let mainContext=tenantRegistry.getMainContext(),tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available"};let now=new Date;await db.update(tenantsTable).set({status:"suspended",suspendedAt:now,suspendedReason:body.reason||"Suspended by godmin",updatedAt:now}).where(eq12(col3(tenantsTable,"id"),id));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId:id,eventType:"suspended",eventData:JSON.stringify({reason:body.reason||"Suspended by godmin"}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record suspend event")}return await tenantRegistry.refreshTenant(id),log.info("Tenant suspended",{tenantId:id,reason:body.reason}),{success:!0,message:`Tenant "${tenant.subdomain}" suspended`}},{body:t6.Object({reason:t6.Optional(t6.String())}),detail:{tags:["Tenants"],summary:"Suspend tenant",description:"Suspend a tenant, preventing all access. Requires godmin privileges."}}),manageRoutes.post("/tenants/:id/reactivate",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let{id}=ctx.params,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found"};if(tenant.status!=="suspended")return ctx.set.status=400,{success:!1,message:`Tenant is not suspended (current: ${tenant.status})`};let mainContext=tenantRegistry.getMainContext(),tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available"};let now=new Date;await db.update(tenantsTable).set({status:"active",suspendedAt:null,suspendedReason:null,updatedAt:now}).where(eq12(col3(tenantsTable,"id"),id));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId:id,eventType:"reactivated",eventData:JSON.stringify({previousReason:tenant.suspendedReason}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record reactivate event")}return await tenantRegistry.refreshTenant(id),log.info("Tenant reactivated",{tenantId:id}),{success:!0,message:`Tenant "${tenant.subdomain}" reactivated`}},{detail:{tags:["Tenants"],summary:"Reactivate tenant",description:"Reactivate a suspended tenant. Requires godmin privileges."}}),manageRoutes}var verifyGodmin=async(db,tenantRegistry,userId)=>{let usersTable=tenantRegistry.getMainContext().schemaTables.users;if(!usersTable)return!1;return(await db.select().from(usersTable).where(eq12(col3(usersTable,"id"),userId)).limit(1))[0]?.isGod===!0},getAllTenants=(registry)=>{let schemaNames=registry.getAllSchemaNames(),tenants=[];for(let name of schemaNames){let ctx=registry.getSchemaContext(name);if(ctx?.tenant)tenants.push(ctx.tenant)}return tenants};init_Logger2();init_utils6();import{eq as eq13}from"drizzle-orm";import{Elysia as Elysia7,t as t7}from"elysia";var col4=(table,name)=>table[name],ProvisionBodySchema=t7.Object({subdomain:t7.String({minLength:2,maxLength:63,pattern:"^[a-z][a-z0-9-]*$"}),companyId:t7.String({minLength:1}),companyName:t7.Optional(t7.String()),godAdminEmail:t7.String({format:"email"}),plan:t7.Optional(t7.String()),domain:t7.Optional(t7.String())});function createProvisionRoute(config){let log=config.logger.scoped(TENANT_PROVISION),provisionRoutes=new Elysia7;return provisionRoutes.post("/tenants/provision",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant provisioning not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};let mainContext=tenantRegistry.getMainContext(),usersTable=mainContext.schemaTables.users;if(!usersTable)return ctx.set.status=503,{success:!1,message:"Users table not available"};let requestingUser=(await db.select().from(usersTable).where(eq13(col4(usersTable,"id"),requestingUserId)).limit(1))[0];if(!requestingUser||!requestingUser.isGod)return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let body=ctx.body,tenantSchemaName=`tenant_${body.subdomain.replace(/-/g,"_")}`;if(tenantRegistry.getActiveTenants().find((t8)=>t8.subdomain===body.subdomain))return ctx.set.status=409,{success:!1,message:`Subdomain "${body.subdomain}" is already taken`};let tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available in main schema"};let tenantId=crypto.randomUUID(),now=new Date;try{await db.insert(tenantsTable).values({id:tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName,companyId:body.companyId,companyName:body.companyName||null,godAdminEmail:body.godAdminEmail,status:"provisioning",plan:body.plan||null,domain:body.domain||null,createdAt:now,updatedAt:now}),log.info("Tenant record created",{tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Failed to insert tenant record",{error:msg}),ctx.set.status=500,{success:!1,message:`Failed to create tenant record: ${msg}`}}try{let tenantRecord={id:tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName,companyId:body.companyId,companyName:body.companyName||null,godAdminEmail:body.godAdminEmail,status:"provisioning",plan:body.plan||null,domain:body.domain||null,settings:{},trustedSources:[],maxUsers:null,provisionedAt:null,suspendedAt:null,suspendedReason:null},tenantContext=await tenantRegistry.provisionTenant(tenantRecord);log.info("Schema provisioned",{tenantId,schemaName:tenantSchemaName,tableCount:Object.keys(tenantContext.schemaTables).length});let tenantUsersTable=tenantContext.schemaTables.users;if(tenantUsersTable){let godminId=crypto.randomUUID(),tempPassword=crypto.randomUUID().slice(0,16),hashedPassword=await hashPassword(tempPassword);await db.insert(tenantUsersTable).values({id:godminId,email:body.godAdminEmail,password:hashedPassword,isGod:!0,isActive:!0,createdAt:now,updatedAt:now}),log.info("Godmin user seeded",{tenantId,godminEmail:body.godAdminEmail,godminId})}await db.update(tenantsTable).set({status:"active",provisionedAt:now,updatedAt:now}).where(eq13(col4(tenantsTable,"id"),tenantId));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId,eventType:"provisioned",eventData:JSON.stringify({schemaName:tenantSchemaName,godAdminEmail:body.godAdminEmail,plan:body.plan||null}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record tenant_event, continuing")}return await tenantRegistry.refreshTenant(tenantId),log.info("Provisioning complete",{tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName}),await config.logger.audit({entityName:"tenants",entityId:tenantId,operation:"PROVISION",userId:requestingUserId,summary:`Tenant "${body.subdomain}" provisioned by godmin`,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:new URL(ctx.request.url).pathname,query:""}),{success:!0,message:"Tenant provisioned successfully",data:{tenantId,schemaName:tenantSchemaName,subdomain:body.subdomain,godAdminEmail:body.godAdminEmail,status:"active"}}}catch(err){let msg=err instanceof Error?err.message:String(err);log.error("Provisioning failed",{error:msg,tenantId});try{await db.update(tenantsTable).set({status:"provisioning",updatedAt:now}).where(eq13(col4(tenantsTable,"id"),tenantId))}catch{}return ctx.set.status=500,{success:!1,message:`Provisioning failed: ${msg}`}}},{body:ProvisionBodySchema,detail:{tags:["Tenants"],summary:"Provision new tenant",description:"Create a new tenant with its own schema, tables, and godmin user. Requires godmin privileges."}}),provisionRoutes}init_Logger2();init_utils6();import{eq as eq14}from"drizzle-orm";import{Elysia as Elysia8,t as t8}from"elysia";var col5=(table,name)=>table[name],ipRateMap=new Map,lastCleanup=Date.now();function cleanupRateMap(windowMs){let now=Date.now();if(now-lastCleanup<600000)return;lastCleanup=now;for(let[key,entry]of ipRateMap.entries())if(now-entry.windowStart>windowMs)ipRateMap.delete(key)}function isIpRateLimited(ip,maxPerWindow,windowMs){let now=Date.now(),entry=ipRateMap.get(ip);if(!entry||now-entry.windowStart>windowMs)return ipRateMap.set(ip,{count:1,windowStart:now}),!1;return entry.count++,entry.count>maxPerWindow}var SelfSignupBodySchema=t8.Object({email:t8.String({format:"email"}),password:t8.String({minLength:8}),subdomain:t8.String({minLength:2,maxLength:63,pattern:"^[a-z][a-z0-9-]*$"}),plan:t8.Optional(t8.String()),companyName:t8.Optional(t8.String())});function createSelfSignupRoute(config){let log=config.logger.scoped(TENANT_SELF_SIGNUP),limits={...DEFAULT_SELF_SIGNUP_LIMITS,...config.selfSignupLimits},selfSignupRoutes=new Elysia8;return selfSignupRoutes.post("/tenants/self-signup",async(ctx)=>{cleanupRateMap(limits.ipWindowMs);let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant provisioning not available"};let ip=ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown";if(isIpRateLimited(ip,limits.maxSignupsPerIpPerWindow,limits.ipWindowMs))return log.warn("Self-signup rate limited",{ip}),ctx.set.status=429,{success:!1,message:"Too many signup attempts. Please try again later."};let body=ctx.body,email=body.email.toLowerCase().trim(),subdomain=body.subdomain.toLowerCase().trim();if(RESERVED_SUBDOMAINS.includes(subdomain))return ctx.set.status=400,{success:!1,message:"This subdomain is reserved."};let mainContext=tenantRegistry.getMainContext(),usersTable=mainContext.schemaTables.users,tenantsTable=mainContext.schemaTables.tenants;if(!usersTable||!tenantsTable)return ctx.set.status=503,{success:!1,message:"Required tables not available."};if(tenantRegistry.getActiveTenants().find((t9)=>t9.subdomain===subdomain))return ctx.set.status=409,{success:!1,message:"This subdomain is already taken."};try{if((await db.select().from(tenantsTable).where(eq14(col5(tenantsTable,"subdomain"),subdomain)).limit(1)).length>0)return ctx.set.status=409,{success:!1,message:"This subdomain is already taken."}}catch{}try{if((await db.select().from(tenantsTable).where(eq14(col5(tenantsTable,"godAdminEmail"),email))).length>=limits.maxTenantsPerEmail)return ctx.set.status=409,{success:!1,message:`Tenant limit reached. Maximum ${limits.maxTenantsPerEmail} tenant(s) per account.`}}catch{}let userId,hashedPassword=await hashPassword(body.password),now=new Date,existingUsers=await db.select().from(usersTable).where(eq14(col5(usersTable,"email"),email)).limit(1);if(existingUsers.length>0)userId=existingUsers[0].id,log.info("Self-signup: existing user resolved",{userId,email});else{userId=crypto.randomUUID();try{await db.insert(usersTable).values({id:userId,email,password:hashedPassword,isActive:!0,createdAt:now,updatedAt:now}),log.info("Self-signup: user created",{userId,email})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Self-signup: user creation failed",{error:msg}),ctx.set.status=500,{success:!1,message:"Failed to create account."}}}let tenantId=crypto.randomUUID(),tenantSchemaName=`tenant_${subdomain.replace(/-/g,"_")}`;try{await db.insert(tenantsTable).values({id:tenantId,subdomain,schemaName:tenantSchemaName,companyId:userId,companyName:body.companyName||subdomain,godAdminEmail:email,status:"provisioning",plan:body.plan||null,createdAt:now,updatedAt:now}),log.info("Tenant record created",{tenantId,subdomain})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Tenant record creation failed",{error:msg}),ctx.set.status=500,{success:!1,message:"Failed to create tenant."}}try{let tenantRecord={id:tenantId,subdomain,schemaName:tenantSchemaName,companyId:userId,companyName:body.companyName||subdomain,godAdminEmail:email,status:"provisioning",plan:body.plan||null,domain:null,settings:{},trustedSources:[],maxUsers:null,provisionedAt:null,suspendedAt:null,suspendedReason:null},tenantContext=await tenantRegistry.provisionTenant(tenantRecord);log.info("Schema provisioned",{tenantId,schemaName:tenantSchemaName,tableCount:Object.keys(tenantContext.schemaTables).length});let tenantUsersTable=tenantContext.schemaTables.users;if(tenantUsersTable)await db.insert(tenantUsersTable).values({id:userId,email,password:hashedPassword,isGod:!0,isActive:!0,createdAt:now,updatedAt:now}),log.info("Godmin seeded in tenant schema",{tenantId,email,userId});await db.update(tenantsTable).set({status:"active",provisionedAt:now,updatedAt:now}).where(eq14(col5(tenantsTable,"id"),tenantId));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId,eventType:"self_signup",eventData:JSON.stringify({email,subdomain,plan:body.plan||null}),performedBy:userId,ipAddress:ip,createdAt:now,updatedAt:now})}catch{}return await tenantRegistry.refreshTenant(tenantId),log.info("Self-signup complete",{tenantId,subdomain,email}),await config.logger.audit({entityName:"tenants",entityId:tenantId,operation:"SELF_SIGNUP",userId,summary:`Self-signup: tenant "${subdomain}" provisioned by ${email}`,ipAddress:ip,userAgent:ctx.request.headers.get("user-agent")||"unknown",path:new URL(ctx.request.url).pathname,query:""}),{success:!0,message:"Tenant created successfully",data:{tenantId,subdomain,schemaName:tenantSchemaName,userId,email,status:"active"}}}catch(err){let msg=err instanceof Error?err.message:String(err);log.error("Self-signup provisioning failed",{error:msg,tenantId});try{await db.update(tenantsTable).set({status:"provisioning",updatedAt:now}).where(eq14(col5(tenantsTable,"id"),tenantId))}catch{}return ctx.set.status=500,{success:!1,message:"Provisioning failed. Please try again."}}},{body:SelfSignupBodySchema,detail:{tags:["Tenants"],summary:"Self-service tenant signup",description:"Public endpoint for self-service signup. Creates user account, provisions tenant schema, and seeds godmin. Rate-limited by IP with configurable max tenants per email."}}),selfSignupRoutes}function createTenantRoutes(app,config){return app.use(createCheckSubdomainRoute(config)),app.use(createProvisionRoute(config)),app.use(createSelfSignupRoute(config)),app.use(createManageRoutes(config)),app}import Elysia9,{t as t9}from"elysia";var STREAM_HEADERS={"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"},textEncoder=new TextEncoder,encodeEvent=(event,data)=>{let payload=typeof data==="string"?data:JSON.stringify(data);return textEncoder.encode(`event: ${event}
|
|
188
|
+
`,createPaymentRoutes=(config)=>{let{provider,basePath,defaultCurrency,defaultLocale,successRedirectUrl,failedRedirectUrl,errorRedirectUrl,savedMethodsEnabled,threeDSecureEnabled,subMerchantsEnabled,transactionsTable,methodsTable,webhookLogsTable,subMerchantsTable,commissionSplitsTable,productsTable,pricesTable,customersTable,subscriptionsTable,invoicesTable,db,logger:logger2}=config,txTable=transactionsTable,pmTable=methodsTable,whTable=webhookLogsTable,smTable=subMerchantsTable,csTable=commissionSplitsTable,prodTable=productsTable,priceTable=pricesTable,cusTable=customersTable,subTable=subscriptionsTable,invTable=invoicesTable,database=db,app=new Elysia30({prefix:basePath});if(app.post("/initialize",async(ctx)=>{if(!threeDSecureEnabled)return ctx.set.status=400,{success:!1,error:"3D Secure is not enabled"};let userId=ctx.request.headers.get("x-user-id"),body=ctx.body;try{let[transaction]=await database.insert(txTable).values({userId:userId??null,orderId:body.orderId??body.conversationId??null,provider:provider.name,amount:Number(body.paidPrice??body.price??0),currency:body.currency??defaultCurrency,status:"pending",statusCode:1000,statusMessage:"3DS initialization started",isThreeDSecure:!0,installment:body.installment??1,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null,metadata:body.metadata??{}}).returning(),result=await provider.initialize3DS({locale:body.locale??defaultLocale,conversationId:transaction.id,price:body.price,paidPrice:body.paidPrice,currency:body.currency??defaultCurrency,installment:body.installment,paymentChannel:body.paymentChannel,basketId:body.basketId,paymentGroup:body.paymentGroup,paymentCard:body.paymentCard,buyer:body.buyer,shippingAddress:body.shippingAddress,billingAddress:body.billingAddress,basketItems:body.basketItems,callbackUrl:body.callbackUrl??config.callbackUrl??`${basePath}/callback`});if(!result.success)return await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:result.errorMessage??"Initialization failed",providerResponse:result.rawResponse??{},failedAt:new Date}).where(eq28(txTable.id,transaction.id)),ctx.set.status=400,{success:!1,error:result.errorMessage??"Payment initialization failed",errorCode:result.errorCode};return await database.update(txTable).set({status:"processing",statusCode:1001,statusMessage:"3DS initialized, awaiting bank verification",providerPaymentId:result.paymentId,providerResponse:result.rawResponse??{}}).where(eq28(txTable.id,transaction.id)),{success:!0,transactionId:transaction.id,threeDSHtmlContent:result.threeDSHtmlContent,paymentId:result.paymentId}}catch(error3){return logger2.error("[Payment] initialize3DS error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Internal payment error"}}}),app.post("/callback",async(ctx)=>{let requestOrigin=new URL(ctx.request.url).origin,htmlHeaders={"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":requestOrigin,"Access-Control-Allow-Methods":"POST, OPTIONS"};try{let formData=await ctx.request.formData(),rawData={};formData.forEach((value2,key)=>{rawData[key]=String(value2)});let parsed=provider.parseCallback(rawData);if(await database.insert(whTable).values({provider:provider.name,eventType:"three_ds_callback",providerPaymentId:parsed.paymentId,rawPayload:rawData,processed:!1,idempotencyKey:`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null}).onConflictDoNothing(),!parsed.success){if(logger2.warn("[Payment] 3DS callback failed",{mdStatus:parsed.mdStatus,paymentId:parsed.paymentId}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS verification failed: mdStatus=${parsed.mdStatus}`,failedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}let completion=await provider.complete3DS({locale:defaultLocale,conversationId:parsed.conversationId,paymentId:parsed.paymentId});if(!completion.success){if(logger2.error("[Payment] 3DS completion failed",{paymentId:parsed.paymentId,errorCode:completion.errorCode,errorMessage:completion.errorMessage}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS completion failed: ${completion.errorMessage}`,providerResponse:completion.rawResponse??{},failedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}if(parsed.conversationId)await database.update(txTable).set({status:"completed",statusCode:1001,statusMessage:"Payment completed successfully",providerPaymentId:completion.paymentId??parsed.paymentId,providerTransactionId:completion.signature,amount:completion.paidPrice??0,currency:completion.currency??defaultCurrency,paymentMethod:completion.cardAssociation,cardLastFour:completion.lastFourDigits,cardType:completion.cardType,cardAssociation:completion.cardAssociation,installment:completion.installment??1,providerResponse:completion.rawResponse??{},completedAt:new Date}).where(eq28(txTable.id,parsed.conversationId)).catch(()=>{});await database.update(whTable).set({processed:!0,processingResult:{completion}}).where(eq28(whTable.idempotencyKey,`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`)).catch(()=>{}),logger2.info("[Payment] 3DS payment completed",{paymentId:completion.paymentId,amount:completion.paidPrice,currency:completion.currency});let queryParams=new URLSearchParams;if(parsed.conversationId)queryParams.append("transactionId",parsed.conversationId);if(completion.paymentId)queryParams.append("paymentId",completion.paymentId);if(completion.paidPrice)queryParams.append("amount",String(completion.paidPrice));let redirectUrl=`${requestOrigin}${successRedirectUrl}?${queryParams.toString()}`;return new Response(generateRedirectHtml(redirectUrl,"Payment Successful"),{headers:htmlHeaders})}catch(error3){return logger2.error("[Payment] callback error",{error:error3 instanceof Error?error3.message:String(error3)}),new Response(generateRedirectHtml(`${requestOrigin}${errorRedirectUrl}`,"Payment Error"),{headers:htmlHeaders})}}),app.get("/transactions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(txTable).where(eq28(txTable.userId,userId)).orderBy(txTable.createdAt)}}}catch(error3){return logger2.error("[Payment] list transactions error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list transactions"}}}),app.get("/transactions/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[transaction]=await database.select().from(txTable).where(and9(eq28(txTable.id,ctx.params.id),eq28(txTable.userId,userId))).limit(1);if(!transaction)return ctx.set.status=404,{success:!1,error:"Transaction not found"};return{success:!0,data:transaction}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get transaction"}}}),app.post("/bin-query",async(ctx)=>{let body=ctx.body,binNumber=body.binNumber??body.cardNumber;if(!binNumber||typeof binNumber!=="string")return ctx.set.status=400,{success:!1,error:"binNumber is required"};try{let result=await provider.queryBin({locale:body.locale??defaultLocale,binNumber,price:body.price});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"BIN query failed",errorCode:result.errorCode};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"BIN query failed"}}}),app.post("/payment-detail",async(ctx)=>{let body=ctx.body;if(!body.paymentId)return ctx.set.status=400,{success:!1,error:"paymentId is required"};try{let result=await provider.getPaymentDetail({locale:body.locale??defaultLocale,paymentId:body.paymentId,conversationId:body.conversationId,paymentConversationId:body.paymentConversationId});return{success:result.success,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Payment detail query failed"}}}),app.post("/refund",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.paymentTransactionId||!body.price)return ctx.set.status=400,{success:!1,error:"paymentTransactionId and price are required"};try{let result=await provider.refund({locale:body.locale??defaultLocale,conversationId:body.conversationId,paymentTransactionId:body.paymentTransactionId,price:String(body.price),currency:body.currency??defaultCurrency,ip:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Refund failed",errorCode:result.errorCode};if(body.transactionId)await database.update(txTable).set({status:"refunded",refundedAmount:Number(body.price),refundedAt:new Date,statusMessage:"Payment refunded"}).where(eq28(txTable.id,body.transactionId)).catch(()=>{});return logger2.info("[Payment] Refund processed",{paymentId:result.paymentId,price:result.price}),{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Refund failed"}}}),savedMethodsEnabled)app.post("/cards/save",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.email||!body.card)return ctx.set.status=400,{success:!1,error:"email and card are required"};try{let result=await provider.saveCard({locale:body.locale??defaultLocale,email:body.email,externalId:userId,card:body.card});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to save card",errorCode:result.errorCode};let[saved]=await database.insert(pmTable).values({userId,provider:provider.name,type:"card",alias:result.cardAlias??body.card.cardAlias,cardLastFour:result.lastFourDigits,cardType:result.cardType,cardAssociation:result.cardAssociation,cardFamily:result.cardFamily,cardBankName:result.cardBankName,providerCardUserKey:result.cardUserKey,providerCardToken:result.cardToken,binNumber:result.binNumber}).returning();return logger2.info("[Payment] Card saved",{userId,cardAlias:result.cardAlias}),{success:!0,data:saved}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to save card"}}}),app.get("/cards",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(pmTable).where(and9(eq28(pmTable.userId,userId),eq28(pmTable.isActive,!0))).orderBy(pmTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list cards"}}}),app.delete("/cards/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[card]=await database.select().from(pmTable).where(and9(eq28(pmTable.id,ctx.params.id),eq28(pmTable.userId,userId))).limit(1);if(!card)return ctx.set.status=404,{success:!1,error:"Card not found"};if(card.providerCardUserKey&&card.providerCardToken){let deleteResult=await provider.deleteCard({locale:defaultLocale,cardUserKey:card.providerCardUserKey,cardToken:card.providerCardToken});if(!deleteResult.success)logger2.warn("[Payment] Provider card delete failed (proceeding with local delete)",{errorCode:deleteResult.errorCode,errorMessage:deleteResult.errorMessage})}return await database.update(pmTable).set({isActive:!1}).where(eq28(pmTable.id,ctx.params.id)),logger2.info("[Payment] Card deleted",{userId,cardId:ctx.params.id}),{success:!0}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to delete card"}}}),app.post("/cards/sync",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body,cardUserKey=body.cardUserKey;if(!cardUserKey)return ctx.set.status=400,{success:!1,error:"cardUserKey is required"};try{let result=await provider.listCards({locale:body.locale??defaultLocale,cardUserKey});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list cards from provider"};return{success:!0,data:{cardUserKey:result.cardUserKey,cards:result.cards}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to sync cards"}}});if(app.post("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name)return ctx.set.status=400,{success:!1,error:"name is required"};try{let providerResult=await provider.createProduct({name:body.name,description:body.description,type:body.type,images:body.images,unitLabel:body.unitLabel,url:body.url,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create product at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(prodTable).values({provider:provider.name,providerProductId:providerResult.providerProductId,name:body.name,description:body.description??null,type:body.type??"service",status:"active",images:body.images?JSON.stringify(body.images):"[]",unitLabel:body.unitLabel??null,url:body.url??null,metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Product created",{id:saved.id,providerProductId:providerResult.providerProductId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create product error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create product"}}}),app.put("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId){let providerResult=await provider.updateProduct({providerProductId:existing.providerProductId,name:body.name,description:body.description,images:body.images,unitLabel:body.unitLabel,url:body.url,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider product update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.description!==void 0)updateData.description=body.description;if(body.type)updateData.type=body.type;if(body.status)updateData.status=body.status;if(body.images)updateData.images=JSON.stringify(body.images);if(body.unitLabel!==void 0)updateData.unitLabel=body.unitLabel;if(body.url!==void 0)updateData.url=body.url;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(prodTable).set(updateData).where(eq28(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update product"}}}),app.get("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let status=new URL(ctx.request.url).searchParams.get("status"),query=database.select().from(prodTable).where(eq28(prodTable.isActive,!0));if(status)query=database.select().from(prodTable).where(and9(eq28(prodTable.isActive,!0),eq28(prodTable.status,status)));return{success:!0,data:{items:await query.orderBy(prodTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list products"}}}),app.get("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Product not found"};let prices=await database.select().from(priceTable).where(and9(eq28(priceTable.productId,ctx.params.id),eq28(priceTable.isActive,!0))).orderBy(priceTable.createdAt);return{success:!0,data:{...item,prices}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get product"}}}),app.delete("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[existing]=await database.select().from(prodTable).where(eq28(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId)await provider.archiveProduct({providerProductId:existing.providerProductId});let[updated]=await database.update(prodTable).set({status:"archived"}).where(eq28(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to archive product"}}}),app.post("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.productId||body.unitAmount===void 0||!body.currency)return ctx.set.status=400,{success:!1,error:"productId, unitAmount, and currency are required"};try{let[product]=await database.select().from(prodTable).where(eq28(prodTable.id,body.productId)).limit(1);if(!product)return ctx.set.status=404,{success:!1,error:"Product not found"};let providerResult=await provider.createPrice({providerProductId:product.providerProductId,currency:body.currency,unitAmount:body.unitAmount,type:body.type,billingScheme:body.billingScheme,nickname:body.nickname,recurring:body.recurring,transformQuantity:body.transformQuantity,unitAmountDecimal:body.unitAmountDecimal,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create price at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(priceTable).values({productId:body.productId,provider:provider.name,providerPriceId:providerResult.providerPriceId,currency:body.currency,unitAmount:body.unitAmount,unitAmountDecimal:body.unitAmountDecimal??null,type:body.type??"one_time",billingScheme:body.billingScheme??"per_unit",nickname:body.nickname??null,recurringInterval:body.recurring?.interval??null,recurringIntervalCount:body.recurring?.intervalCount??1,recurringUsageType:body.recurring?.usageType??"licensed",recurringAggregateUsage:body.recurring?.aggregateUsage??null,transformQuantityDivideBy:body.transformQuantity?.divideBy??null,transformQuantityRound:body.transformQuantity?.round??null,status:"active",metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Price created",{id:saved.id,providerPriceId:providerResult.providerPriceId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create price error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create price"}}}),app.put("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId){let providerResult=await provider.updatePrice({providerPriceId:existing.providerPriceId,nickname:body.nickname,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider price update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.nickname!==void 0)updateData.nickname=body.nickname;if(body.status)updateData.status=body.status;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(priceTable).set(updateData).where(eq28(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update price"}}}),app.get("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),productId=url.searchParams.get("productId"),status=url.searchParams.get("status"),query=database.select().from(priceTable).where(eq28(priceTable.isActive,!0));if(productId&&status)query=database.select().from(priceTable).where(and9(eq28(priceTable.productId,productId),eq28(priceTable.status,status),eq28(priceTable.isActive,!0)));else if(productId)query=database.select().from(priceTable).where(and9(eq28(priceTable.productId,productId),eq28(priceTable.isActive,!0)));else if(status)query=database.select().from(priceTable).where(and9(eq28(priceTable.status,status),eq28(priceTable.isActive,!0)));return{success:!0,data:{items:await query.orderBy(priceTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list prices"}}}),app.get("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Price not found"};return{success:!0,data:item}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get price"}}}),app.delete("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[existing]=await database.select().from(priceTable).where(eq28(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId)await provider.archivePrice({providerPriceId:existing.providerPriceId});let[updated]=await database.update(priceTable).set({status:"archived"}).where(eq28(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to archive price"}}}),app.post("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createCustomer({email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0,taxId:body.taxId});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(cusTable).values({user_id:userId,provider:provider.name,provider_customer_id:result.providerCustomerId,email:body.email,name:body.name??null,phone:body.phone??null,description:body.description??null,address:body.address??{},tax_id_type:body.taxId?.type??null,tax_id_value:body.taxId?.value??null,metadata:body.metadata??{}}).returning();return{success:!0,customer:row,providerCustomerId:result.providerCustomerId}}catch(error3){return logger2.error("[Payment] Create customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create customer"}}}),app.put("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};let result=await provider.updateCustomer({providerCustomerId:existing.provider_customer_id,email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0});if(!result.success)return ctx.set.status=400,result;let updates={};if(body.email)updates.email=body.email;if(body.name!==void 0)updates.name=body.name;if(body.phone!==void 0)updates.phone=body.phone;if(body.description!==void 0)updates.description=body.description;if(body.address)updates.address=body.address;if(body.metadata)updates.metadata=body.metadata;let[updated]=await database.update(cusTable).set(updates).where(eq28(cusTable.id,id)).returning();return{success:!0,customer:updated}}catch(error3){return logger2.error("[Payment] Update customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update customer"}}}),app.get("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,customers:await database.select().from(cusTable).where(eq28(cusTable.user_id,userId))}}catch(error3){return logger2.error("[Payment] List customers error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list customers"}}}),app.get("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};return{success:!0,customer}}catch(error3){return logger2.error("[Payment] Get customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get customer"}}}),app.delete("/customers/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(cusTable).where(eq28(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};return await provider.deleteCustomer({providerCustomerId:existing.provider_customer_id}),await database.delete(cusTable).where(eq28(cusTable.id,id)),{success:!0}}catch(error3){return logger2.error("[Payment] Delete customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to delete customer"}}}),app.post("/subscriptions",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};let items=body.items,result=await provider.createSubscription({providerCustomerId:customer.provider_customer_id,items,trialPeriodDays:body.trialPeriodDays,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,defaultPaymentMethod:body.defaultPaymentMethod});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(subTable).values({customer_id:customerId,provider:provider.name,provider_subscription_id:result.providerSubscriptionId,status:result.status??"incomplete",collection_method:body.collectionMethod??"charge_automatically",current_period_start:result.currentPeriodStart?new Date(result.currentPeriodStart):null,current_period_end:result.currentPeriodEnd?new Date(result.currentPeriodEnd):null,cancel_at_period_end:body.cancelAtPeriodEnd??!1,items,metadata:body.metadata??{}}).returning();return{success:!0,subscription:row,clientSecret:result.clientSecret}}catch(error3){return logger2.error("[Payment] Create subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create subscription"}}}),app.put("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};let result=await provider.updateSubscription({providerSubscriptionId:existing.provider_subscription_id,items:body.items,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,defaultPaymentMethod:body.defaultPaymentMethod,prorationBehavior:body.prorationBehavior});if(!result.success)return ctx.set.status=400,result;let updates={};if(result.status)updates.status=result.status;if(body.cancelAtPeriodEnd!==void 0)updates.cancel_at_period_end=body.cancelAtPeriodEnd;if(body.items)updates.items=body.items;if(body.metadata)updates.metadata=body.metadata;if(body.collectionMethod)updates.collection_method=body.collectionMethod;let[updated]=await database.update(subTable).set(updates).where(eq28(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Update subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update subscription"}}}),app.post("/subscriptions/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};let result=await provider.cancelSubscription({providerSubscriptionId:existing.provider_subscription_id,cancelAtPeriodEnd:body.cancelAtPeriodEnd,invoiceNow:body.invoiceNow,prorate:body.prorate});if(!result.success)return ctx.set.status=400,result;let updates={status:result.status??"canceled",canceled_at:new Date};if(body.cancelAtPeriodEnd)updates.cancel_at_period_end=!0;let[updated]=await database.update(subTable).set(updates).where(eq28(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Cancel subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to cancel subscription"}}}),app.get("/subscriptions",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq28(subTable.customer_id,query.customerId));if(query.status)conditions.push(eq28(subTable.status,query.status));return{success:!0,subscriptions:conditions.length>0?await database.select().from(subTable).where(and9(...conditions)):await database.select().from(subTable)}}catch(error3){return logger2.error("[Payment] List subscriptions error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list subscriptions"}}}),app.get("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[subscription]=await database.select().from(subTable).where(eq28(subTable.id,id));if(!subscription)return ctx.set.status=404,{success:!1,error:"Subscription not found"};return{success:!0,subscription}}catch(error3){return logger2.error("[Payment] Get subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get subscription"}}}),app.post("/usage-records",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.reportUsage({subscriptionItemId:body.subscriptionItemId,quantity:body.quantity,timestamp:body.timestamp,action:body.action});if(!result.success)return ctx.set.status=400,result;return{success:!0,usageRecord:result}}catch(error3){return logger2.error("[Payment] Report usage error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to report usage"}}}),app.get("/usage-records/:subscriptionItemId/summaries",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{subscriptionItemId}=ctx.params,query=ctx.query,result=await provider.listUsageRecordSummaries({subscriptionItemId,limit:query.limit?parseInt(query.limit,10):void 0,startingAfter:query.startingAfter});if(!result.success)return ctx.set.status=400,result;return{success:!0,summaries:result.summaries,hasMore:result.hasMore}}catch(error3){return logger2.error("[Payment] List usage summaries error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list usage summaries"}}}),app.post("/invoices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq28(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};let result=await provider.createInvoice({providerCustomerId:customer.provider_customer_id,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,description:body.description,metadata:body.metadata,autoAdvance:body.autoAdvance,items:body.items});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(invTable).values({customer_id:customerId,subscription_id:body.subscriptionId??null,provider:provider.name,provider_invoice_id:result.providerInvoiceId,status:result.status??"draft",collection_method:body.collectionMethod??"charge_automatically",currency:body.currency??defaultCurrency,description:body.description??null,hosted_invoice_url:result.hostedInvoiceUrl??null,invoice_pdf:result.invoicePdf??null,days_until_due:body.daysUntilDue??null,lines:body.items??[],metadata:body.metadata??{}}).returning();return{success:!0,invoice:row,providerInvoiceId:result.providerInvoiceId}}catch(error3){return logger2.error("[Payment] Create invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create invoice"}}}),app.post("/invoices/:id/finalize",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.finalizeInvoice({providerInvoiceId:existing.provider_invoice_id,autoAdvance:body.autoAdvance});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"open",hosted_invoice_url:result.hostedInvoiceUrl??existing.hosted_invoice_url,invoice_pdf:result.invoicePdf??existing.invoice_pdf}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Finalize invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to finalize invoice"}}}),app.post("/invoices/:id/send",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.sendInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;return{success:!0}}catch(error3){return logger2.error("[Payment] Send invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to send invoice"}}}),app.post("/invoices/:id/void",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.voidInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:"void",voided_at:new Date}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Void invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to void invoice"}}}),app.post("/invoices/:id/pay",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};let result=await provider.payInvoice({providerInvoiceId:existing.provider_invoice_id,paymentMethod:body.paymentMethod});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"paid",amount_paid:result.amountPaid??existing.amount_paid,amount_due:result.amountDue??existing.amount_due,paid_at:new Date}).where(eq28(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Pay invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to pay invoice"}}}),app.get("/invoices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq28(invTable.customer_id,query.customerId));if(query.subscriptionId)conditions.push(eq28(invTable.subscription_id,query.subscriptionId));if(query.status)conditions.push(eq28(invTable.status,query.status));return{success:!0,invoices:conditions.length>0?await database.select().from(invTable).where(and9(...conditions)):await database.select().from(invTable)}}catch(error3){return logger2.error("[Payment] List invoices error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list invoices"}}}),app.get("/invoices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[invoice]=await database.select().from(invTable).where(eq28(invTable.id,id));if(!invoice)return ctx.set.status=404,{success:!1,error:"Invoice not found"};return{success:!0,invoice}}catch(error3){return logger2.error("[Payment] Get invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get invoice"}}}),subMerchantsEnabled)app.post("/sub-merchants",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name||!body.email||!body.subMerchantType)return ctx.set.status=400,{success:!1,error:"name, email, and subMerchantType are required"};try{let externalId=body.externalId??`sm-${Date.now().toString(36)}`,result=await provider.registerSubMerchant({locale:body.locale??defaultLocale,subMerchantExternalId:externalId,subMerchantType:body.subMerchantType,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency??defaultCurrency});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to register sub-merchant",errorCode:result.errorCode};let[saved]=await database.insert(smTable).values({userId:body.userId??null,provider:provider.name,providerSubMerchantKey:result.subMerchantKey,externalId,type:body.subMerchantType,status:"active",name:body.name,email:body.email,gsmNumber:body.gsmNumber??null,address:body.address??null,iban:body.iban??null,contactName:body.contactName??null,contactSurname:body.contactSurname??null,identityNumber:body.identityNumber??null,taxOffice:body.taxOffice??null,taxNumber:body.taxNumber??null,legalCompanyTitle:body.legalCompanyTitle??null,currency:body.currency??defaultCurrency,commissionRate:body.commissionRate??0}).returning();return logger2.info("[Payment] Sub-merchant registered",{externalId,providerKey:result.subMerchantKey}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] register sub-merchant error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to register sub-merchant"}}}),app.put("/sub-merchants/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(smTable).where(eq28(smTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};if(existing.providerSubMerchantKey){let providerResult=await provider.updateSubMerchant({locale:body.locale??defaultLocale,subMerchantKey:existing.providerSubMerchantKey,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency});if(!providerResult.success)logger2.warn("[Payment] Provider sub-merchant update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.email)updateData.email=body.email;if(body.gsmNumber!==void 0)updateData.gsmNumber=body.gsmNumber;if(body.address!==void 0)updateData.address=body.address;if(body.iban!==void 0)updateData.iban=body.iban;if(body.contactName!==void 0)updateData.contactName=body.contactName;if(body.contactSurname!==void 0)updateData.contactSurname=body.contactSurname;if(body.identityNumber!==void 0)updateData.identityNumber=body.identityNumber;if(body.taxOffice!==void 0)updateData.taxOffice=body.taxOffice;if(body.taxNumber!==void 0)updateData.taxNumber=body.taxNumber;if(body.legalCompanyTitle!==void 0)updateData.legalCompanyTitle=body.legalCompanyTitle;if(body.currency!==void 0)updateData.currency=body.currency;if(body.commissionRate!==void 0)updateData.commissionRate=body.commissionRate;if(body.status!==void 0)updateData.status=body.status;let[updated]=await database.update(smTable).set(updateData).where(eq28(smTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to update sub-merchant"}}}),app.get("/sub-merchants",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(smTable).where(eq28(smTable.isActive,!0)).orderBy(smTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list sub-merchants"}}}),app.get("/sub-merchants/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(smTable).where(eq28(smTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};return{success:!0,data:item}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get sub-merchant"}}}),app.post("/splits/:splitId/approve",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[split]=await database.select().from(csTable).where(eq28(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.approveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider approval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"approved",approvedAt:new Date}).where(eq28(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split approved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to approve split"}}}),app.post("/splits/:splitId/disapprove",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[split]=await database.select().from(csTable).where(eq28(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.disapproveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider disapproval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"disapproved",disapprovedAt:new Date}).where(eq28(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split disapproved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to disapprove split"}}}),app.get("/splits",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),transactionId=url.searchParams.get("transactionId"),subMerchantId=url.searchParams.get("subMerchantId"),query=database.select().from(csTable);if(transactionId&&subMerchantId)query=query.where(and9(eq28(csTable.transactionId,transactionId),eq28(csTable.subMerchantId,subMerchantId)));else if(transactionId)query=query.where(eq28(csTable.transactionId,transactionId));else if(subMerchantId)query=query.where(eq28(csTable.subMerchantId,subMerchantId));return{success:!0,data:{items:await query.orderBy(csTable.createdAt)}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list splits"}}});return app.get("/balance",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getBalance();if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get balance"};return{success:!0,data:{available:result.available,pending:result.pending,connectReserved:result.connectReserved}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get balance"}}}),app.post("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createPayout({amount:body.amount,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,method:body.method,sourceType:body.sourceType,statementDescriptor:body.statementDescriptor});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to create payout"}}}),app.get("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listPayouts({status:url.searchParams.get("status")??void 0,destination:url.searchParams.get("destination")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list payouts"};return{success:!0,data:{payouts:result.payouts,hasMore:result.hasMore}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list payouts"}}}),app.get("/payouts/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to get payout"}}}),app.post("/payouts/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.cancelPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to cancel payout"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to cancel payout"}}}),app.post("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createTransfer({amount:body.amount,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,sourceTransaction:body.sourceTransaction,transferGroup:body.transferGroup});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create transfer"};return{success:!0,data:result}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to create transfer"}}}),app.get("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listTransfers({destination:url.searchParams.get("destination")??void 0,transferGroup:url.searchParams.get("transferGroup")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list transfers"};return{success:!0,data:{transfers:result.transfers,hasMore:result.hasMore}}}catch(error3){return ctx.set.status=500,{success:!1,error:"Failed to list transfers"}}}),app.options("/callback",()=>{return new Response(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,POST,OPTIONS","Access-Control-Allow-Headers":"Content-Type"}})}),app};var init_payment=()=>{};import{batch,createStore}from"h-state";import{useEffectEvent}from"react";function createInitialState(endpoints){let state={};for(let key of Object.keys(endpoints))state[key]={isPending:!1,data:null,error:null,code:null};return state}function createApiHook(endpoints,factory){let{useStore}=createStore(createInitialState(endpoints),{_callEndpoint:(store)=>async(endpointKey,options)=>{if(!store[endpointKey])return;batch(()=>{store[endpointKey].isPending=!0,store[endpointKey].error=null});try{let response=await factory(endpointKey,options.payload);if(batch(()=>{if(store[endpointKey].isPending=!1,store[endpointKey].code=response.code??null,response.isSuccess&&response.data!==void 0)store[endpointKey].data=response.data,store[endpointKey].error=null;else store[endpointKey].error=response.errors??null}),response.isSuccess)options.onAfterHandle?.(response.data??response);else options.onErrorHandle?.(response.errors??{message:"Request failed"},response.code)}catch(err){batch(()=>{store[endpointKey].isPending=!1,store[endpointKey].error={message:err instanceof Error?err.message:"Unknown error"}}),options.onErrorHandle?.({message:err instanceof Error?err.message:"Unknown error"},null)}}});return function(){let store=useStore(),callEndpoint=useEffectEvent((endpointKey,options)=>{store._callEndpoint(endpointKey,options)}),actions={};for(let key of Object.keys(endpoints)){let startFn=(options)=>{callEndpoint(key,options)};actions[key]={state:store[key],start:startFn}}return actions}}var system_tables_default={$schema:"../schemas/nucleus.tables.schema.json",tables:[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]}]};var AUTH_ENDPOINT_CONFIGS={login:{key:"LOGIN",method:"POST",defaultRoute:"/auth/login",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},register:{key:"REGISTER",method:"POST",defaultRoute:"/auth/register",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},logout:{key:"LOGOUT",method:"POST",defaultRoute:"/auth/logout",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},refresh:{key:"REFRESH",method:"POST",defaultRoute:"/auth/refresh",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},me:{key:"ME",method:"GET",defaultRoute:"/auth/me",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordChange:{key:"PASSWORD_CHANGE",method:"POST",defaultRoute:"/auth/password-change",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordSet:{key:"PASSWORD_SET",method:"POST",defaultRoute:"/auth/password-set",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordReset:{key:"PASSWORD_RESET_REQUEST",method:"POST",defaultRoute:"/auth/password-reset",defaultIsPublic:!0,subEndpoints:[{key:"PASSWORD_RESET_REQUEST",method:"POST",suffix:"/request",_payload:void 0,_success:void 0,_error:void 0},{key:"PASSWORD_RESET_CONFIRM",method:"POST",suffix:"/confirm",_payload:void 0,_success:void 0,_error:void 0}]},sessions:{key:"SESSIONS",method:"GET",defaultRoute:"/auth/sessions",defaultIsPublic:!1,subEndpoints:[{key:"SESSIONS",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_CURRENT",method:"GET",suffix:"/current",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_STATS",method:"GET",suffix:"/stats",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_PENDING",method:"GET",suffix:"/pending",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE",method:"DELETE",suffix:"/:sessionId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE_ALL",method:"DELETE",suffix:"/all",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_APPROVE",method:"POST",suffix:"/approve",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REJECT",method:"POST",suffix:"/reject",_payload:void 0,_success:void 0,_error:void 0}]},magicLink:{key:"MAGIC_LINK",method:"POST",defaultRoute:"/auth/magic-link",defaultIsPublic:!0,subEndpoints:[{key:"MAGIC_LINK",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"MAGIC_LINK_VERIFY",method:"GET",suffix:"/verify",routeKey:"verifyRoute",_payload:void 0,_success:void 0,_error:void 0}]},invite:{key:"INVITE",method:"POST",defaultRoute:"/auth/invite",defaultIsPublic:!1,subEndpoints:[{key:"INVITE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"INVITE_VERIFY",method:"POST",suffix:"/verify",_payload:void 0,_success:void 0,_error:void 0}]},emailVerification:{key:"VERIFY_EMAIL",method:"GET",defaultRoute:"/verify-email",defaultIsPublic:!0,subEndpoints:[{key:"VERIFY_EMAIL",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"RESEND_VERIFICATION",method:"POST",suffix:"",routeKey:"resendRoute",defaultRoute:"/resend-verification",_payload:void 0,_success:void 0,_error:void 0}]},captcha:{key:"CAPTCHA",method:"GET",defaultRoute:"/auth/captcha",defaultIsPublic:!0,subEndpoints:[{key:"CAPTCHA_GENERATE",method:"GET",suffix:"/generate",_payload:void 0,_success:void 0,_error:void 0},{key:"CAPTCHA_VALIDATE",method:"POST",suffix:"/validate",_payload:void 0,_success:void 0,_error:void 0}]},oauth:{key:"OAUTH_PROVIDERS",method:"GET",defaultRoute:"/auth/oauth/providers",defaultIsPublic:!0,subEndpoints:[{key:"OAUTH_PROVIDERS",method:"GET",suffix:"/providers",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_REDIRECT",method:"GET",suffix:"/:provider",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_ACCOUNTS",method:"GET",suffix:"/accounts",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_UNLINK",method:"DELETE",suffix:"/unlink/:provider",_payload:void 0,_success:void 0,_error:void 0}]},apiKeys:{key:"API_KEYS",method:"GET",defaultRoute:"/auth/api-keys",defaultIsPublic:!1,subEndpoints:[{key:"API_KEYS_CREATE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_LIST",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_DETAIL",method:"GET",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_UPDATE",method:"PATCH",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_REVOKE",method:"DELETE",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0}]}};var TENANT_ENDPOINT_CONFIGS={checkSubdomain:{key:"TENANT_CHECK_SUBDOMAIN",method:"GET",suffix:"/check-subdomain/:subdomain",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},provision:{key:"TENANT_PROVISION",method:"POST",suffix:"/provision",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},list:{key:"TENANT_LIST",method:"GET",suffix:"",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},detail:{key:"TENANT_DETAIL",method:"GET",suffix:"/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},suspend:{key:"TENANT_SUSPEND",method:"POST",suffix:"/:id/suspend",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},reactivate:{key:"TENANT_REACTIVATE",method:"POST",suffix:"/:id/reactivate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},selfSignup:{key:"TENANT_SELF_SIGNUP",method:"POST",suffix:"/self-signup",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0}},MONITORING_ENDPOINT_CONFIGS={healthCheck:{key:"MONITORING_HEALTH_CHECK",method:"GET",suffix:"/health",_payload:void 0,_success:void 0,_error:void 0},getSettings:{key:"MONITORING_GET_SETTINGS",method:"GET",suffix:"/settings",_payload:void 0,_success:void 0,_error:void 0},changeSettings:{key:"MONITORING_CHANGE_SETTINGS",method:"PATCH",suffix:"/settings",_payload:void 0,_success:void 0,_error:void 0},getLogs:{key:"MONITORING_GET_LOGS",method:"GET",suffix:"/logs",_payload:void 0,_success:void 0,_error:void 0}};var SYSTEM_TABLE_NAMES=["profiles","addresses","phones","files","users","roles","claims","user_roles","role_claims","audit_logs"],systemTables=system_tables_default.tables.filter((t)=>SYSTEM_TABLE_NAMES.includes(t.table_name));function toUpperSnakeCase(str){return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toUpperCase()}function snakeToCamelCase(str){return str.replace(/_([a-z])/g,(_,letter)=>letter.toUpperCase())}function singularize(str){if(str.endsWith("ies"))return`${str.slice(0,-3)}y`;if(str.endsWith("ses"))return`${str.slice(0,-2)}`;if(str.endsWith("s"))return str.slice(0,-1);return str}function generateEntityEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName),singularName=toUpperSnakeCase(singularize(tableName));switch(method){case"GET":return`GET_${upperName}`;case"POST":return`ADD_${singularName}`;case"PUT":return`UPDATE_${singularName}`;case"PATCH":return`PATCH_${singularName}`;case"DELETE":return`DELETE_${singularName}`}}function generateBulkEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName);switch(method){case"POST":return`BULK_ADD_${upperName}`;case"PUT":return`BULK_UPDATE_${upperName}`;case"DELETE":return`BULK_DELETE_${upperName}`}}function isMethodExcluded(table,method){if(!table.excluded_methods)return!1;let methodMap={GET:"GET",POST:"POST",PUT:"PUT",PATCH:"PATCH",DELETE:"DELETE"};return table.excluded_methods.includes(methodMap[method])}function generateEndpointsFromConfig(config){let endpoints={};for(let table of config.entities){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,sid=table.serviceId;if(!isMethodExcluded(table,"GET")){endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0},endpoints[`GET_${toUpperSnakeCase(tableName)}_DISTINCT`]={method:"GET",path:`${basePath}/distinct/:field`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}if(!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:table.is_public?.POST??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:table.is_public?.PUT??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:table.is_public?.PATCH??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled){if(!isMethodExcluded(table,"POST"))endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:table.is_public?.POST??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:table.is_public?.PUT??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}}return endpoints}function generateAuthEndpoints(config){let endpoints={},auth=config.authentication;if(!auth?.enabled)return endpoints;for(let[featureKey,endpointConfig]of Object.entries(AUTH_ENDPOINT_CONFIGS)){let feature=auth[featureKey];if(!feature?.enabled)continue;let feat=feature,baseRoute=feat.route||endpointConfig.defaultRoute,isPublic=feat.isPublic??endpointConfig.defaultIsPublic;if("subEndpoints"in endpointConfig&&endpointConfig.subEndpoints)for(let sub of endpointConfig.subEndpoints){let subRoute="routeKey"in sub&&sub.routeKey&&feature[sub.routeKey]?String(feature[sub.routeKey]):("defaultRoute"in sub)&&sub.defaultRoute?String(sub.defaultRoute):`${baseRoute}${sub.suffix}`;endpoints[sub.key]={method:sub.method,path:subRoute,isPublic:sub.key==="MAGIC_LINK_VERIFY"?!0:isPublic,_payload:sub._payload,_success:sub._success,_error:sub._error}}else if("_payload"in endpointConfig)endpoints[endpointConfig.key]={method:endpointConfig.method,path:baseRoute,isPublic,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error}}return endpoints}function generateSystemTableEndpoints(){let endpoints={};for(let table of systemTables){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,isFormData=tableName==="files";endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));if(endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},table.bulk_endpoints_enabled)endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}}return endpoints}function generateMonitoringEndpoints(config){let endpoints={},monitoring=config.liveMonitoring;if(!monitoring?.enabled)return endpoints;let basePath=monitoring.basePath||"/monitoring";for(let endpointConfig of Object.values(MONITORING_ENDPOINT_CONFIGS))endpoints[endpointConfig.key]={method:endpointConfig.method,path:`${basePath}${endpointConfig.suffix}`,isPublic:!1,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error};return endpoints}function generateAdminEndpoints(config){let endpoints={};if(!config.authentication?.enabled)return endpoints;return endpoints.ADMIN_IMPERSONATE={method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_IMPERSONATE_STOP={method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CHANGE_USER_ID={method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints}function generateVerificationEndpoints(config){let endpoints={},verification=config.verification,notification=config.notification;if(!verification?.enabled)return endpoints;let basePath=verification.endpoints?.basePath||"/verifications",flowBasePath=verification.flowEndpoints?.basePath||"/verification-flows",notifBasePath=notification?.endpoints?.basePath||"/notifications";if(endpoints.VERIFICATION_STATUS={method:"GET",path:`${basePath}/status/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_DECIDE={method:"POST",path:`${basePath}/:entity_name/:entity_id/decide`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_PENDING={method:"GET",path:`${basePath}/pending`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_HISTORY={method:"GET",path:`${basePath}/history/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START={method:"POST",path:`${basePath}/start`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START_FOR_ENTITY={method:"POST",path:`${basePath}/start-for-entity`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_ENTITY_STATUSES={method:"GET",path:`${basePath}/statuses/:entity_name`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},verification.flowEndpoints?.enabled)endpoints.FLOW_LIST={method:"GET",path:flowBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_GET={method:"GET",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_SAVE={method:"POST",path:flowBasePath,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_PUBLISH={method:"POST",path:`${flowBasePath}/:flow_id/publish`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_DELETE={method:"DELETE",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(notification?.enabled&¬ification.endpoints?.enabled)endpoints.NOTIFICATION_LIST={method:"GET",path:notifBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_UNSEEN_COUNT={method:"GET",path:`${notifBasePath}/unseen-count`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_SEEN={method:"POST",path:`${notifBasePath}/:notification_id/seen`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_ALL_SEEN={method:"POST",path:`${notifBasePath}/seen-all`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};return endpoints}function generateTenantEndpoints(config){let endpoints={};if(!config.database?.isMultiTenant)return endpoints;let basePath="/tenants";for(let endpointConfig of Object.values(TENANT_ENDPOINT_CONFIGS))endpoints[endpointConfig.key]={method:endpointConfig.method,path:`${basePath}${endpointConfig.suffix}`,isPublic:"isPublic"in endpointConfig?endpointConfig.isPublic:!1,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error};return endpoints}function generateAllEndpoints(config,extraEndpoints){let entityEndpoints=generateEndpointsFromConfig(config),authEndpoints=generateAuthEndpoints(config),adminEndpoints=generateAdminEndpoints(config),systemEndpoints=generateSystemTableEndpoints(),monitoringEndpoints=generateMonitoringEndpoints(config),verificationEndpoints=generateVerificationEndpoints(config),tenantEndpoints=generateTenantEndpoints(config);return{...entityEndpoints,...authEndpoints,...adminEndpoints,...systemEndpoints,...monitoringEndpoints,...verificationEndpoints,...tenantEndpoints,...extraEndpoints??{}}}init_Logger();import{randomUUID as randomUUID2}from"crypto";var DEFAULT_CONFIG2={timeout:30000,retries:0,retryDelay:1000,debug:!1};class ServerFetch{config;logger;constructor(config={}){this.config={...DEFAULT_CONFIG2,...config},this.logger=new Logger({service:"ServerFetch",prettyPrint:this.config.debug,colorize:this.config.debug,auditEnabled:!1})}buildUrl(url){if(url.startsWith("http://")||url.startsWith("https://"))return url;return this.config.baseUrl?`${this.config.baseUrl}${url}`:url}buildHeaders(customHeaders){let headers=new Headers;if(this.config.defaultHeaders)for(let[key,value]of Object.entries(this.config.defaultHeaders))headers.set(key,value);if(customHeaders)if(customHeaders instanceof Headers)customHeaders.forEach((value,key)=>{headers.set(key,value)});else if(Array.isArray(customHeaders))for(let[key,value]of customHeaders)headers.set(key,value);else for(let[key,value]of Object.entries(customHeaders))headers.set(key,value);return headers}parseResponseHeaders(headers){let result={};if(headers.forEach((value,key)=>{if(key.toLowerCase()==="set-cookie"){let existing=result[key];result[key]=existing?`${existing}, ${value}`:value}else result[key]=value}),typeof headers.getSetCookie==="function"){let setCookies=headers.getSetCookie();if(setCookies.length>0)result["set-cookie"]=setCookies.join(", ")}return result}async executeWithTimeout(promise,timeoutMs,_requestId){let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),timeoutMs);try{return await Promise.race([promise,new Promise((_,reject)=>{controller.signal.addEventListener("abort",()=>{reject(Error(`Request timeout after ${timeoutMs}ms`))})})])}finally{clearTimeout(timeoutId)}}async fetch(options){let requestId=randomUUID2(),startTime=performance.now(),url=this.buildUrl(options.url),headers=this.buildHeaders(options.headers),timeout=options.timeout??this.config.timeout??30000,retries=options.retries??this.config.retries??0,retryDelay=options.retryDelay??this.config.retryDelay??1000,body;if(options.body)if(typeof options.body==="object"&&!(options.body instanceof FormData)&&!(options.body instanceof URLSearchParams)&&!(options.body instanceof Blob)&&!(options.body instanceof ArrayBuffer)){if(body=JSON.stringify(options.body),!headers.has("content-type"))headers.set("content-type","application/json")}else body=options.body;this.logger.debug(`[${requestId}] ${options.method} ${url}`,{method:options.method,url,hasBody:!!body});let lastError=null,attempt=0;while(attempt<=retries)try{let response=await this.executeWithTimeout(fetch(url,{method:options.method,headers,body}),timeout,requestId),durationMs2=performance.now()-startTime,responseHeaders=this.parseResponseHeaders(response.headers),rawSetCookies=typeof response.headers.getSetCookie==="function"?response.headers.getSetCookie():[],responseData,errorData,rawText=await response.text();if(rawText)try{let json=JSON.parse(rawText);if(response.ok)responseData=json;else errorData=json}catch{if(!response.ok)errorData={message:rawText||response.statusText}}else if(!response.ok)errorData={message:response.statusText};let result={isSuccess:response.ok,response:responseData,errors:errorData,code:response.status,headers:responseHeaders,rawSetCookies,durationMs:durationMs2,requestId,createdAt:new Date};if(response.ok)this.logger.info(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2)});else this.logger.warn(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2),error:errorData});return result}catch(error){if(lastError=error instanceof Error?error:Error(String(error)),attempt++,attempt<=retries)this.logger.warn(`[${requestId}] Retry ${attempt}/${retries} after error`,{method:options.method,url,error:lastError.message,attempt,retries}),await new Promise((resolve)=>setTimeout(resolve,retryDelay))}let durationMs=performance.now()-startTime;return this.logger.error(`[${requestId}] ${options.method} ${url} failed`,lastError,{method:options.method,url,durationMs:Math.round(durationMs),attempts:attempt}),{isSuccess:!1,response:void 0,errors:{message:lastError?.message||"Unknown error"},code:null,headers:{},rawSetCookies:[],durationMs,requestId,createdAt:new Date}}async get(url,options){return this.fetch({...options,url,method:"GET"})}async post(url,body,options){return this.fetch({...options,url,method:"POST",body})}async put(url,body,options){return this.fetch({...options,url,method:"PUT",body})}async patch(url,body,options){return this.fetch({...options,url,method:"PATCH",body})}async delete(url,options){return this.fetch({...options,url,method:"DELETE"})}}var serverFetch=new ServerFetch;var DEFAULT_TOKEN_NAMES={accessToken:"access_token",refreshToken:"refresh_token",sessionToken:"session_token"};function splitSetCookieHeader(header){let cookies=[],current="";for(let i=0;i<header.length;i++){let char=header[i];if(char===","){let next=header.slice(i+1).trimStart();if(/^[a-zA-Z0-9_-]+=/.test(next)){cookies.push(current.trim()),current="";continue}}current+=char}if(current.trim())cookies.push(current.trim());return cookies}function buildRequestHeaders(headersStore,tokenNames){let headers={},forwardHeaders=["x-forwarded-for","x-real-ip","user-agent","accept-language","x-request-id","x-client-ip","cf-connecting-ip","true-client-ip"];for(let header of forwardHeaders){let value=headersStore.get(header);if(value)headers[header]=value}if(!headers["user-agent"])headers["user-agent"]="Nucleus-ServerAction/1.0";let accessToken=headersStore.get(`x-${tokenNames.accessToken}`),refreshToken=headersStore.get(`x-${tokenNames.refreshToken}`),sessionToken=headersStore.get(`x-${tokenNames.sessionToken}`);if(accessToken)headers[`x-${tokenNames.accessToken}`]=accessToken;if(refreshToken)headers[`x-${tokenNames.refreshToken}`]=refreshToken;if(sessionToken)headers[`x-${tokenNames.sessionToken}`]=sessionToken;let cookieHeader=headersStore.get("cookie");if(cookieHeader)headers.cookie=cookieHeader;return headers}function toCamelCase(str){return str.replace(/_([a-z])/g,(_,c)=>c.toUpperCase())}function convertKeysToCamelCase(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.startsWith("_")?key:toCamelCase(key);if(value instanceof Date)result[camelKey]=value.toISOString();else if(value&&typeof value==="object"&&!Array.isArray(value))result[camelKey]=convertKeysToCamelCase(value);else result[camelKey]=value}return result}var JSON_STRINGIFY_KEYS=new Set(["filters","sort","with","searchFields","select","distinctOn"]);function appendQueryParams(url,params){let searchParams=new URLSearchParams;for(let[key,value]of Object.entries(params)){if(value===void 0||value===null)continue;if(JSON_STRINGIFY_KEYS.has(key)&&typeof value==="object"){searchParams.append(key,JSON.stringify(value));continue}if(value instanceof Date)searchParams.append(key,value.toISOString());else if(Array.isArray(value))searchParams.append(key,value.filter((v)=>v!=null).map(String).join(","));else if(typeof value==="object")searchParams.append(key,JSON.stringify(value));else searchParams.append(key,String(value))}let queryString=searchParams.toString();if(!queryString)return url;return url.includes("?")?`${url}&${queryString}`:`${url}?${queryString}`}function createServerFactory(endpoints,config,getCookies,getHeaders){let tokenNames={...DEFAULT_TOKEN_NAMES,...config.tokenNames},serverFetch2=new ServerFetch({baseUrl:config.baseUrl,debug:config.debug,timeout:30000,retries:0});return async function(endpointKey,payload){let endpoint=endpoints[endpointKey];if(!endpoint)return{isSuccess:!1,errors:{message:`Endpoint "${endpointKey}" not found`},code:404};let cookieStore=await getCookies(),headersStore=await getHeaders(),allHeaders={};if(headersStore.forEach((value,key)=>{allHeaders[key]=value}),(endpoint.path.includes("/auth/login")||endpoint.path.includes("/auth/oauth"))&&endpoint.method==="POST")try{cookieStore.delete(tokenNames.accessToken),cookieStore.delete(tokenNames.refreshToken),cookieStore.delete(tokenNames.sessionToken)}catch(_){}let headers=buildRequestHeaders(headersStore,tokenNames),url=endpoint.path,body,pathParamNames=new Set,pathParamRegex=/:([a-zA-Z_][a-zA-Z0-9_]*)/g,paramMatch=pathParamRegex.exec(url);while(paramMatch!==null){if(paramMatch[1])pathParamNames.add(paramMatch[1]);paramMatch=pathParamRegex.exec(url)}if(payload&&typeof payload==="object"&&!(payload instanceof FormData)){let payloadObj=payload;for(let[key,value]of Object.entries(payloadObj))if(value!=null){if(pathParamNames.has(key))url=url.replace(`:${key}`,String(value));else if(key.startsWith("_")&&pathParamNames.has(key.substring(1)))url=url.replace(`:${key.substring(1)}`,String(value));else if(key==="id"&&pathParamNames.has("id"))url=url.replace(":id",String(value))}}if(endpoint.method==="GET"&&payload&&typeof payload==="object"){let queryPayload={...payload};for(let paramName of pathParamNames)delete queryPayload[paramName],delete queryPayload[`_${paramName}`];url=appendQueryParams(url,queryPayload)}else if(payload!==void 0){if(endpoint.isFormData&&payload instanceof FormData)body=payload;else if(Array.isArray(payload)){if(body=payload.map((item)=>item&&typeof item==="object"?convertKeysToCamelCase(item):item),!headers["content-type"])headers["content-type"]="application/json"}else if(body=endpoint.skipCamelCase?payload:convertKeysToCamelCase(payload),!headers["content-type"])headers["content-type"]="application/json"}let response=await serverFetch2.fetch({url,method:endpoint.method,headers,body}),setCookiesToProcess=response.rawSetCookies.length>0?response.rawSetCookies:response.headers["set-cookie"]?splitSetCookieHeader(response.headers["set-cookie"]):[];if(setCookiesToProcess.length>0)try{for(let cookie of setCookiesToProcess){let[nameValue,...options]=cookie.split(";");if(!nameValue)continue;let eqIdx=nameValue.indexOf("=");if(eqIdx===-1)continue;let name=nameValue.substring(0,eqIdx).trim(),value=nameValue.substring(eqIdx+1).trim();if(name&&value){let cookieOptions={};for(let opt of options){let trimmed=opt.trim(),optEqIdx=trimmed.indexOf("="),optName=optEqIdx===-1?trimmed:trimmed.substring(0,optEqIdx),optValue=optEqIdx===-1?void 0:trimmed.substring(optEqIdx+1);if(!optName)continue;let optNameLower=optName.toLowerCase();if(optNameLower==="path")cookieOptions.path=optValue;else if(optNameLower==="domain")cookieOptions.domain=optValue;else if(optNameLower==="max-age")cookieOptions.maxAge=Number(optValue);else if(optNameLower==="expires"&&optValue)cookieOptions.expires=new Date(optValue);else if(optNameLower==="httponly")cookieOptions.httpOnly=!0;else if(optNameLower==="secure")cookieOptions.secure=!0;else if(optNameLower==="samesite")cookieOptions.sameSite=optValue}cookieStore.set(name,value,cookieOptions)}}}catch(cookieError){console.warn("[ServerFactory] Failed to process Set-Cookie headers:",cookieError instanceof Error?cookieError.message:String(cookieError))}let normalizedResponse=response.response;if(response.isSuccess&&normalizedResponse&&typeof normalizedResponse==="object"&&!Array.isArray(normalizedResponse)){let raw=normalizedResponse;if("success"in raw&&!("data"in raw)){let{success,message,error,...rest}=raw;normalizedResponse={success,...message!==void 0?{message}:{},...error!==void 0?{error}:{},...Object.keys(rest).length>0?{data:rest}:{}}}}return{isSuccess:response.isSuccess,data:normalizedResponse,errors:response.errors,code:response.code,message:response.isSuccess?void 0:response.errors?.message}}}import{batch as batch2,createStore as createStore2}from"h-state";var initialState={connection:{status:"disconnected",clientId:null,subscribedTopics:[],error:null,reconnectAttempt:0},events:[],maxEvents:100},{useStore:usePubSubStore}=createStore2(initialState,{setConnectionStatus:(store)=>(status)=>{store.connection.status=status},setClientId:(store)=>(clientId)=>{store.connection.clientId=clientId},setSubscribedTopics:(store)=>(topics)=>{store.connection.subscribedTopics=topics},setError:(store)=>(error)=>{store.connection.error=error},setReconnectAttempt:(store)=>(attempt)=>{store.connection.reconnectAttempt=attempt},addEvent:(store)=>(event)=>{let updated=[event,...store.events];store.events=updated.slice(0,store.maxEvents)},clearEvents:(store)=>()=>{store.events=[]},reset:(store)=>()=>{batch2(()=>{store.connection.status="disconnected",store.connection.clientId=null,store.connection.subscribedTopics=[],store.connection.error=null,store.connection.reconnectAttempt=0,store.events=[]})}});import{useEffect,useEffectEvent as useEffectEvent2,useRef}from"react";function buildWsUrl(config){if(config.wsUrl){let base=config.wsUrl.replace(/\/$/,""),path2=config.wsPath||"/api/events/subscribe",topics2=(config.topics||["*"]).join(",");return`${base}${path2}?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics2)}`}if(typeof window>"u")return"";let protocol=window.location.protocol==="https:"?"wss:":"ws:",host=window.location.host,path=config.wsPath||"/api/events/subscribe",topics=(config.topics||["*"]).join(",");return`${protocol}//${host}${path}?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics)}`}var eventIdCounter=0;function usePubSub(config){let store=usePubSubStore(),wsRef=useRef(null),heartbeatRef=useRef(null),reconnectTimeoutRef=useRef(null),isDestroyedRef=useRef(!1),configRef=useRef(config);configRef.current=config;let autoReconnect=config.autoReconnect??!0,maxReconnectAttempts=config.maxReconnectAttempts??10,reconnectBaseDelay=config.reconnectBaseDelay??1000,reconnectMaxDelay=config.reconnectMaxDelay??30000,heartbeatInterval=config.heartbeatInterval??30000,debug=config.debug??!1,log=(...args)=>{if(debug)console.log("[usePubSub]",...args)},clearHeartbeat=()=>{if(heartbeatRef.current)clearInterval(heartbeatRef.current),heartbeatRef.current=null},clearReconnectTimeout=()=>{if(reconnectTimeoutRef.current)clearTimeout(reconnectTimeoutRef.current),reconnectTimeoutRef.current=null},startHeartbeat=(ws)=>{clearHeartbeat(),heartbeatRef.current=setInterval(()=>{if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({type:"ping"}))},heartbeatInterval)},handleMessage=useEffectEvent2((event)=>{try{let message=JSON.parse(event.data);switch(message.type){case"connected":store.setConnectionStatus("connected"),store.setClientId(message.clientId),store.setSubscribedTopics(message.subscribedTopics),store.setReconnectAttempt(0),store.setError(null),log("Connected, clientId:",message.clientId);break;case"subscribed":store.setSubscribedTopics(message.topics),log("Subscribed to:",message.topics);break;case"event":{let pubsubEvent={id:`evt_${Date.now()}_${eventIdCounter++}`,topic:message.topic,data:message.data,timestamp:message.timestamp,receivedAt:Date.now(),messageId:message.messageId,isRedelivery:message.isRedelivery};if(store.addEvent(pubsubEvent),message.messageId&&wsRef.current?.readyState===WebSocket.OPEN)wsRef.current.send(JSON.stringify({type:"ack",messageId:message.messageId}));break}case"pong":break;case"error":store.setError(Error(message.error)),log("Server error:",message.error);break}}catch{log("Failed to parse message")}}),scheduleReconnect=useEffectEvent2((attempt)=>{if(isDestroyedRef.current)return;if(!autoReconnect)return;if(attempt>=maxReconnectAttempts){store.setConnectionStatus("disconnected"),store.setError(Error("Max reconnection attempts reached")),log("Max reconnect attempts reached");return}let delay=Math.min(reconnectBaseDelay*2**attempt,reconnectMaxDelay);log(`Reconnecting in ${delay}ms (attempt ${attempt+1}/${maxReconnectAttempts})`),store.setConnectionStatus("reconnecting"),store.setReconnectAttempt(attempt+1),clearReconnectTimeout(),reconnectTimeoutRef.current=setTimeout(()=>{if(!isDestroyedRef.current)connectWs()},delay)}),connectWs=useEffectEvent2(()=>{if(isDestroyedRef.current)return;if(wsRef.current?.readyState===WebSocket.OPEN)return;if(!configRef.current.userId)return;if(wsRef.current){if(wsRef.current.onopen=null,wsRef.current.onmessage=null,wsRef.current.onerror=null,wsRef.current.onclose=null,wsRef.current.readyState===WebSocket.OPEN||wsRef.current.readyState===WebSocket.CONNECTING)wsRef.current.close();wsRef.current=null}let url=buildWsUrl(configRef.current);if(!url)return;store.setConnectionStatus("connecting"),store.setError(null),log("Connecting to:",url);let ws=new WebSocket(url);wsRef.current=ws,ws.onopen=()=>{log("WebSocket opened"),startHeartbeat(ws)},ws.onmessage=handleMessage,ws.onerror=()=>{log("WebSocket error"),store.setError(Error("WebSocket connection error"))},ws.onclose=(event)=>{if(log("WebSocket closed",event.code,event.reason),clearHeartbeat(),store.setConnectionStatus("disconnected"),store.setClientId(null),!isDestroyedRef.current&&event.code!==4001){let currentAttempt=store.connection.reconnectAttempt;scheduleReconnect(currentAttempt)}}}),disconnect=useEffectEvent2(()=>{if(clearHeartbeat(),clearReconnectTimeout(),wsRef.current){if(wsRef.current.onopen=null,wsRef.current.onmessage=null,wsRef.current.onerror=null,wsRef.current.onclose=null,wsRef.current.readyState===WebSocket.OPEN||wsRef.current.readyState===WebSocket.CONNECTING)wsRef.current.close();wsRef.current=null}store.setConnectionStatus("disconnected"),store.setClientId(null)}),subscribe=useEffectEvent2((topics)=>{if(wsRef.current?.readyState!==WebSocket.OPEN)return;wsRef.current.send(JSON.stringify({type:"subscribe",topics}))}),unsubscribe=useEffectEvent2((topics)=>{if(wsRef.current?.readyState!==WebSocket.OPEN)return;wsRef.current.send(JSON.stringify({type:"unsubscribe",topics}))}),getEventsByTopic=useEffectEvent2((topic)=>{return store.events.filter((e)=>e.topic===topic)});return useEffect(()=>{if(isDestroyedRef.current=!1,config.userId)connectWs();return()=>{isDestroyedRef.current=!0,disconnect()}},[config.userId]),useEffect(()=>{if(store.connection.status==="connected"&&config.topics)subscribe(config.topics)},[config.topics?.join(",")]),{isConnected:store.connection.status==="connected",isConnecting:store.connection.status==="connecting"||store.connection.status==="reconnecting",clientId:store.connection.clientId,subscribedTopics:store.connection.subscribedTopics,events:store.events,error:store.connection.error,reconnectAttempt:store.connection.reconnectAttempt,connect:connectWs,disconnect,subscribe,unsubscribe,clearEvents:store.clearEvents,getEventsByTopic}}import{randomUUID as randomUUID5}from"crypto";var import_fast_decode_uri_component=__toESM(require_fast_decode_uri_component(),1);import{Elysia,NotFoundError}from"elysia";var fs,path,isBun=typeof Bun<"u"&&!!Bun.file;function getBuiltinModule(){if(fs||(fs=process.getBuiltinModule("fs/promises")),path||(path=process.getBuiltinModule("path")),!path){console.warn("@elysiajs/static require path to be available.");return}return[fs,path]}async function listHTMLFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*.html"),files=[];for await(let file of glob.scan(dir))files.push(path.join(dir,file));return files}return[]}async function listFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*"),files2=[];for await(let file of glob.scan(dir))files2.push(path.join(dir,file));return files2}let files=await fs.readdir(dir).catch(()=>[]);return(await Promise.all(files.map(async(name)=>{let file=dir+path.sep+name,stats=await fs.stat(file).catch(()=>null);return stats?stats.isDirectory()?await listFiles(file):[path.resolve(dir,file)]:[]}))).flat()}function fileExists(path2){return fs||getBuiltinModule(),fs.stat(path2).then(()=>!0,()=>!1)}class LRUCache{constructor(max=250,ttl=10800){this.max=max,this.ttl=ttl,this.map=new Map}get(key){let entry=this.map.get(key);if(entry)return entry[1]<=Date.now()?void this.delete(key):(this.map.delete(key),this.map.set(key,entry),entry[0])}set(key,value){if(this.interval||(this.interval=setInterval(()=>{let now=Date.now();for(let[key2,entry]of this.map)entry[1]<=now&&this.map.delete(key2)},this.ttl)),this.map.has(key))this.map.delete(key);else if(this.map.size>=this.max){let oldestKey=this.map.keys().next().value;oldestKey!==void 0&&this.delete(oldestKey)}this.map.set(key,[value,Date.now()+this.ttl*1000])}delete(key){this.map.get(key)&&this.map.delete(key)}clear(){this.map.clear()}size(){return this.map.size}[Symbol.dispose](){this.interval&&clearInterval(this.interval)}}function isCached(headers,etag,filePath){if(headers["cache-control"]&&/no-cache|no-store/.test(headers["cache-control"]))return!1;if("if-none-match"in headers){let ifNoneMatch=headers["if-none-match"];return ifNoneMatch==="*"?!0:ifNoneMatch===null||typeof etag!="string"?!1:ifNoneMatch===etag}if(headers["if-modified-since"]){let ifModifiedSince=headers["if-modified-since"];try{return fs.stat(filePath).then((stat)=>{if(stat.mtime!==void 0&&stat.mtime.getTime()<=Date.parse(ifModifiedSince))return!0})}catch{}}return!1}var Crypto;function getFile(path2){return isBun?Bun.file(path2):(fs||getBuiltinModule(),fs.readFile(path2))}async function generateETag(file){return isBun?new Bun.CryptoHasher("md5").update(await file.arrayBuffer()).digest("base64"):(Crypto||(Crypto=process.getBuiltinModule("crypto")),Crypto?Crypto.createHash("md5").update(file).digest("base64"):void console.warn("[@elysiajs/static] crypto is required to generate etag."))}var isNotEmpty=(obj)=>{if(!obj)return!1;for(let _ in obj)return!0;return!1};async function staticPlugin({assets="public",prefix="/public",staticLimit=1024,alwaysStatic=!1,ignorePatterns=[".DS_Store",".git",".env"],headers:initialHeaders,maxAge=86400,directive="public",etag:useETag=!0,extension=!0,indexHTML=!0,decodeURI,silent}={}){if(typeof process>"u"||typeof process.getBuiltinModule>"u")return silent||console.warn("[@elysiajs/static] require process.getBuiltinModule. Static plugin is disabled"),new Elysia;let builtinModule=getBuiltinModule();if(!builtinModule)return new Elysia;let[fs2,path2]=builtinModule,normalizePath=path2.sep!=="/"?(p)=>p.replace(/\\/g,"/"):(p)=>p,fileCache=new LRUCache;prefix===path2.sep&&(prefix="");let assetsDir=path2.resolve(assets),shouldIgnore=ignorePatterns.length?(file)=>ignorePatterns.find((pattern)=>typeof pattern=="string"?pattern.includes(file):pattern.test(file)):()=>!1,app=new Elysia({name:"static",seed:prefix});if(alwaysStatic){let files=await listFiles(path2.resolve(assets));if(files.length<=staticLimit)for(let absolutePath of files){let handleCache2=function({headers:requestHeaders}){if(etag){let cached=isCached(requestHeaders,etag,absolutePath);if(cached===!0)return new Response(null,{status:304,headers:isNotEmpty(initialHeaders)?initialHeaders:void 0});if(cached!==!1){let cache2=fileCache.get(pathName);return cache2?cache2.clone():cached.then((cached2)=>{if(cached2)return new Response(null,{status:304,headers:initialHeaders||void 0});let response2=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(prefix,response2),response2.clone()})}}let cache=fileCache.get(pathName);if(cache)return cache.clone();let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()};var handleCache=handleCache2;if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,"");decodeURI&&(relativePath=import_fast_decode_uri_component.default(relativePath)??relativePath);let pathName=normalizePath(path2.join(prefix,relativePath));if(isBun&&absolutePath.endsWith(".html")){let htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default);continue}extension||(pathName=normalizePath(pathName.slice(0,pathName.lastIndexOf("."))));let file=isBun?getFile(absolutePath):await getFile(absolutePath);if(!file)return silent||console.warn(`[@elysiajs/static] Failed to load file: ${absolutePath}`),new Elysia;let etag=await generateETag(file);app.get(pathName,useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0)),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0))}return app}if(!(`GET_${prefix}/*`in app.routeTree)){if(isBun){let htmls=await listHTMLFiles(path2.resolve(assets));for(let absolutePath of htmls){if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,""),pathName=normalizePath(path2.join(prefix,relativePath)),htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default)}}app.onError(()=>{}).get(`${prefix.endsWith("/")?prefix.slice(0,-1):prefix}/*`,async({params,headers:requestHeaders})=>{let pathName=normalizePath(path2.join(assets,decodeURI?import_fast_decode_uri_component.default(params["*"])??params["*"]:params["*"]));if(shouldIgnore(pathName))throw new NotFoundError;let cache=fileCache.get(pathName);if(cache)return cache.clone();try{let fileStat=await fs2.stat(pathName).catch(()=>null);if(!fileStat)throw new NotFoundError;if(!indexHTML&&fileStat.isDirectory())throw new NotFoundError;let file;if(!isBun&&indexHTML){let htmlPath=path2.join(pathName,"index.html"),cache2=fileCache.get(htmlPath);if(cache2)return cache2.clone();await fileExists(htmlPath)&&(file=await getFile(htmlPath))}if(!file&&!fileStat.isDirectory()&&await fileExists(pathName))file=await getFile(pathName);else throw new NotFoundError;if(!useETag)return new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0);let etag=await generateETag(file);if(etag&&await isCached(requestHeaders,etag,pathName))return new Response(null,{status:304});let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()}catch(error){throw error instanceof NotFoundError?error:(silent||console.error("[@elysiajs/static]",error),new NotFoundError)}})}return app}init_Services();init_ApiKey();init_Captcha();import{pushSchema}from"drizzle-kit/api";import{and as and10,eq as eq29}from"drizzle-orm";import{drizzle as drizzle2}from"drizzle-orm/node-postgres";import{pgSchema as pgSchema2}from"drizzle-orm/pg-core";import Elysia31 from"elysia";var SYSTEM_TABLES=[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]}];var METHOD_MAP={GET:["GET"],POST:["POST"],PUT:["PUT"],DELETE:["DELETE"],PATCH:["PATCH"],TOGGLE:["PATCH"],VERIFICATION:["POST"]};function buildAuthPublicRoutes(config,basePath){let routes=[],auth=config.authentication;if(!auth)return routes;if(auth.login?.enabled&&auth.login?.isPublic)routes.push({path:auth.login.route||`${basePath}/auth/login`,method:"POST",source:"auth"});if(auth.register?.enabled&&auth.register?.isPublic)routes.push({path:auth.register.route||`${basePath}/auth/register`,method:"POST",source:"auth"});if(auth.logout?.enabled&&auth.logout?.isPublic)routes.push({path:auth.logout.route||`${basePath}/auth/logout`,method:"POST",source:"auth"});if(auth.refresh?.enabled&&auth.refresh?.isPublic)routes.push({path:auth.refresh.route||`${basePath}/auth/refresh`,method:"POST",source:"auth"});if(auth.passwordReset?.enabled&&auth.passwordReset?.isPublic){let baseRoute=auth.passwordReset.route||`${basePath}/auth/password-reset`;routes.push({path:`${baseRoute}/request`,method:"POST",source:"auth"},{path:`${baseRoute}/confirm`,method:"POST",source:"auth"})}if(auth.passwordChange?.enabled&&auth.passwordChange?.isPublic)routes.push({path:auth.passwordChange.route||`${basePath}/auth/password-change`,method:"POST",source:"auth"});if(auth.magicLink?.enabled&&auth.magicLink?.isPublic)routes.push({path:auth.magicLink.route||`${basePath}/auth/magic-link`,method:"POST",source:"auth"},{path:auth.magicLink.verifyRoute||`${basePath}/auth/magic-link/verify`,method:"GET",source:"auth"});if(auth.register?.enabled&&auth.register?.emailVerification?.enabled)routes.push({path:`${basePath}/verify-email`,method:"GET",source:"auth"},{path:`${basePath}/resend-verification`,method:"POST",source:"auth"});if(auth.invite?.enabled&&auth.invite?.isPublic)routes.push({path:auth.invite.route||`${basePath}/auth/invite`,method:"POST",source:"auth"});if(auth.invite?.enabled){let inviteRoute=auth.invite.route||`${basePath}/auth/invite`;routes.push({path:`${inviteRoute}/verify`,method:"POST",source:"auth"})}if(auth.passwordSet?.enabled)routes.push({path:auth.passwordSet.route||`${basePath}/auth/password-set`,method:"POST",source:"auth"});if(auth.captcha?.enabled&&auth.captcha?.isPublic){let baseRoute=auth.captcha.route||`${basePath}/auth/captcha`;routes.push({path:`${baseRoute}/generate`,method:"GET",source:"auth"},{path:`${baseRoute}/validate`,method:"POST",source:"auth"})}if(auth.sessions?.enabled){let sessionsRoute=auth.sessions.route||`${basePath}/auth/sessions`;routes.push({path:`${sessionsRoute}/approve`,method:"POST",source:"auth"},{path:`${sessionsRoute}/reject`,method:"POST",source:"auth"},{path:`${sessionsRoute}/approve-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/reject-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/approval-status`,method:"GET",source:"auth"})}if(auth.oauth?.enabled){let oauthBase=auth.oauth.basePath||`${basePath}/auth/oauth`,knownProviders=["google","github","microsoft","discord","facebook","twitter","apple","custom"];routes.push({path:`${oauthBase}/providers`,method:"GET",source:"auth"});for(let provider of knownProviders)routes.push({path:`${oauthBase}/${provider}`,method:"GET",source:"auth"},{path:`${oauthBase}/${provider}/callback`,method:"GET",source:"auth"})}return routes}function buildEntityPublicRoutes(entities,basePath,_schema){let routes=[];for(let entity of entities){if(!entity.is_public)continue;let camelName=entity.table_name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase()),entityPath=`${basePath}/${camelName}`;for(let[nucleusMethod,isPublic]of Object.entries(entity.is_public)){if(!isPublic)continue;let httpMethods=METHOD_MAP[nucleusMethod];if(!httpMethods)continue;for(let method of httpMethods)if(method==="GET")routes.push({path:entityPath,method:"GET",source:"entity"}),routes.push({path:`${entityPath}/:id`,method:"GET",source:"entity"});else if(method==="POST")routes.push({path:entityPath,method:"POST",source:"entity"});else if(method==="PUT"||method==="PATCH")routes.push({path:`${entityPath}/:id`,method,source:"entity"});else if(method==="DELETE")routes.push({path:`${entityPath}/:id`,method:"DELETE",source:"entity"})}}return routes}function buildSystemTablePublicRoutes(systemTables2,basePath,schema){return buildEntityPublicRoutes(systemTables2,basePath,schema)}function buildPublicRoutes(config,systemTables2,basePath="",schema="public"){let authRoutes=buildAuthPublicRoutes(config,basePath),entityRoutes=buildEntityPublicRoutes(config.entities||[],basePath,schema),systemRoutes=buildSystemTablePublicRoutes(systemTables2,basePath,schema),pubsubRoutes=[];if(config.pubsub?.enabled){let pubsubBasePath=config.pubsub.basePath||"/subs",wsPath=config.pubsub.wsPath||"/api/events/subscribe";pubsubRoutes.push({path:`${pubsubBasePath}/:topic`,method:"POST",source:"system"},{path:wsPath,method:"GET",source:"system"})}let paymentRoutes=[];if(config.payment?.enabled){let paymentBasePath=config.payment.basePath||"/payment";paymentRoutes.push({path:`${paymentBasePath}/callback`,method:"POST",source:"system"},{path:`${paymentBasePath}/callback`,method:"OPTIONS",source:"system"},{path:`${paymentBasePath}/bin-query`,method:"POST",source:"system"})}let tenantRoutes=[];if(config.database?.isMultiTenant)tenantRoutes.push({path:`${basePath}/tenants`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/check-subdomain/:subdomain`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/self-signup`,method:"POST",source:"system"});let customRoutes=[{path:"/nucleus-core",method:"GET",source:"custom"},{path:"/public",method:"GET",source:"custom"},{path:"/docs",method:"GET",source:"custom"},{path:"/docs/json",method:"GET",source:"custom"},{path:"/swagger",method:"GET",source:"custom"},{path:"/swagger/json",method:"GET",source:"custom"}];return[...authRoutes,...entityRoutes,...systemRoutes,...pubsubRoutes,...paymentRoutes,...tenantRoutes,...customRoutes]}function isPublicRoute(publicRoutes,path2,method){let normalizedPath=path2.replace(/\/$/,""),normalizedMethod=method.toUpperCase();for(let route of publicRoutes){if(route.method!==normalizedMethod)continue;if(matchPath(route.path,normalizedPath))return!0}return!1}function matchPath(pattern,path2){if(pattern===path2)return!0;let patternParts=pattern.split("/").filter(Boolean),pathParts=path2.split("/").filter(Boolean);if(patternParts.length!==pathParts.length)return!1;for(let i=0;i<patternParts.length;i++){let patternPart=patternParts[i],pathPart=pathParts[i];if(patternPart?.startsWith(":"))continue;if(patternPart!==pathPart)return!1}return!0}import{and as and5,asc,desc as desc3,eq as eq10,ilike,inArray as inArray3,notInArray,or}from"drizzle-orm";import{drizzle}from"drizzle-orm/node-postgres";import{Elysia as Elysia3,t as t3}from"elysia";init_Authorization();init_utils5();init_storage();import{t as t2}from"elysia";function buildBodySchemaFromEntityColumns(entityColumns){let properties={};if(!entityColumns||entityColumns.length===0)return t2.Object({},{additionalProperties:!0});for(let col2 of entityColumns)switch(col2.type?.toLowerCase()||"string"){case"integer":case"int":case"serial":case"bigserial":case"numeric":case"decimal":properties[col2.name]=col2.notNull?t2.Number():t2.Optional(t2.Number());break;case"boolean":properties[col2.name]=col2.notNull?t2.Boolean():t2.Optional(t2.Boolean());break;case"timestamp":case"timestamptz":case"date":properties[col2.name]=col2.notNull?t2.String({format:"date-time"}):t2.Optional(t2.String({format:"date-time"}));break;case"json":case"jsonb":properties[col2.name]=t2.Optional(t2.Unknown());break;case"uuid":properties[col2.name]=col2.notNull?t2.String({format:"uuid"}):t2.Optional(t2.String({format:"uuid"}));break;default:properties[col2.name]=col2.notNull?t2.String():t2.Optional(t2.String())}return t2.Object(properties,{additionalProperties:!0})}function createBulkUpdateSchema(entityColumns){return t2.Array(t2.Object({id:t2.String(),data:buildBodySchemaFromEntityColumns(entityColumns)}))}function createEntityRoutes(app,config){let{db,schemaTables,schemaRelations,entities,logger:logger2,databaseUrl,dbPool,storage,authorization,authMode,idpUrl,tenantRegistry}=config,getReqSchema=(request)=>{if(!tenantRegistry)return{tables:schemaTables,relations:schemaRelations};let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return{tables:schemaTables,relations:schemaRelations};let ctx=tenantRegistry.getSchemaContext(schemaName);return ctx?{tables:ctx.schemaTables,relations:ctx.schemaRelations}:{tables:schemaTables,relations:schemaRelations}},storageConfig=mergeStorageConfig(storage),authEnabled=authorization?.enabled??!1,isConsumerMode=authMode==="consumer";if(!db)return app;function snakeToCamel(s){return s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase())}let allTables=Object.keys(schemaTables),entityTableNames=entities.map((e)=>snakeToCamel(e.table_name)),systemTableNames=allTables.filter((tbl)=>!entityTableNames.includes(tbl)),AUTH_TABLES=["userSessions","passwordResetTokens","magicLinkTokens"],EMAIL_REQUIRED_TABLES=["passwordResetTokens","magicLinkTokens"],FORM_DATA_TABLES=["files"],systemTableDefMap=new Map(SYSTEM_TABLES.map((t4)=>[snakeToCamel(t4.table_name),t4])),systemTables2=systemTableNames.filter((name)=>{if(EMAIL_REQUIRED_TABLES.includes(name)&&!config.emailServiceAvailable)return logger2.info(`Skipping ${name} routes - email service not available`),!1;return!0}).map((name)=>{let def=systemTableDefMap.get(name);return{table_name:def?.table_name??name,group_name:AUTH_TABLES.includes(name)?"Authentication":name,is_form_data:FORM_DATA_TABLES.includes(name),bulk_endpoints_enabled:def?.bulk_endpoints_enabled??!1,excluded_methods:def?.excluded_methods?[...def.excluded_methods]:[],columns:def?.columns?[...def.columns]:void 0}}),allEntities=[...entities,...systemTables2];logger2.info(`All entities: ${allEntities.map((e)=>e.table_name).join(", ")}`);for(let table of allEntities){let rawTableName=table.table_name,tableName=snakeToCamel(rawTableName),swaggerTag=table.group_name||rawTableName,defaultDrizzleTable=schemaTables[tableName];if(!defaultDrizzleTable)continue;let tableRelations=schemaRelations[`${tableName}Relations`];logger2.info(`Creating routes for table: ${tableName}`);let defaultTableColumns=defaultDrizzleTable,defaultIdCol=defaultTableColumns.id,database=db,drizzleTable=defaultDrizzleTable,tableColumns=defaultTableColumns,idCol=defaultIdCol,resolveCol=(field)=>tableColumns[field]??tableColumns[snakeToCamel(field)],getTableForRequest=(request)=>{if(!tenantRegistry)return{drizzleTable,tableColumns,idCol,resolveCol,schemaTables,schemaRelations};let reqSchema=getReqSchema(request),reqTable=reqSchema.tables[tableName]||drizzleTable,reqCols=reqTable,reqIdCol=reqCols.id;return{drizzleTable:reqTable,tableColumns:reqCols,idCol:reqIdCol,resolveCol:(field)=>reqCols[field]??reqCols[snakeToCamel(field)],schemaTables:reqSchema.tables,schemaRelations:reqSchema.relations}},bulkUpdateSchema=createBulkUpdateSchema(table.columns),bulkDeleteSchema=t3.Array(t3.String()),performAuthCheck=async(request,method,reqFields,reqRelations)=>{let userId=request.headers.get("x-user-id");if(!authEnabled||!userId)return null;if(isConsumerMode){let userClaims=(request.headers.get("x-user-claims")||"").split(",").filter(Boolean),userRoles=(request.headers.get("x-user-roles")||"").split(",").filter(Boolean);if(idpUrl){let accessToken=request.headers.get("x-access-token")||(request.headers.get("cookie")||"").match(/access_token=([^;]+)/)?.[1]||"";return checkAuthorizationViaIDP({idpUrl,accessToken,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2})}return checkAuthorizationFromJWT({userClaims,userRoles,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2})}let reqCtx=getTableForRequest(request);return checkAuthorization({userId,method,entity:table.table_name,requestedFields:reqFields,requestedRelations:reqRelations,db:database,schemaTables:reqCtx.schemaTables,logger:logger2})},entityRoutes=new Elysia3({prefix:`/${tableName}`});if(!table.excluded_methods?.includes("GET"))entityRoutes.get("/",async(ctx)=>{if(!database)return{success:!1,message:"DB not initialized"};let{drizzleTable:drizzleTable2,resolveCol:resolveCol2,schemaRelations:schemaRelations2}=getTableForRequest(ctx.request),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=Object.keys(schemaRelations2).filter((k)=>k.startsWith(`${tableName}Relations`)).map((k)=>k.replace("Relations","")),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};let q=parseQueryParams(ctx.query),conditions=[];if(authEnabled&&authResult?.scopeFilters)for(let[field,value]of Object.entries(authResult.scopeFilters)){let col2=resolveCol2(field);if(col2)conditions.push(eq10(col2,value))}if(q.search&&q.searchFields){let searchConditions=q.searchFields.map((f)=>{let trimmed=f.trim(),col2=resolveCol2(trimmed);return col2?ilike(col2,`%${q.search}%`):null}).filter((c)=>c!==null);if(searchConditions.length>0){let orCondition=or(...searchConditions);if(orCondition)conditions.push(orCondition)}}if(q.filters){let{ne,gt,gte,lt,lte,like,isNull,isNotNull}=await import("drizzle-orm");for(let filter of q.filters){let col2=resolveCol2(filter.field);if(!col2)continue;switch(filter.operator){case"eq":conditions.push(eq10(col2,filter.value));break;case"neq":conditions.push(ne(col2,filter.value));break;case"gt":conditions.push(gt(col2,filter.value));break;case"gte":conditions.push(gte(col2,filter.value));break;case"lt":conditions.push(lt(col2,filter.value));break;case"lte":conditions.push(lte(col2,filter.value));break;case"like":conditions.push(like(col2,filter.value));break;case"ilike":conditions.push(ilike(col2,filter.value));break;case"in":conditions.push(inArray3(col2,filter.value));break;case"notIn":conditions.push(notInArray(col2,filter.value));break;case"isNull":conditions.push(isNull(col2));break;case"isNotNull":conditions.push(isNotNull(col2));break}}}let baseQuery=database.select().from(drizzleTable2);if(conditions.length>0){let{and:and6}=await import("drizzle-orm"),combined=and6(...conditions);if(combined)baseQuery=baseQuery.where(combined)}if(q.sort&&q.sort.length>0){let orderClauses=q.sort.map((s)=>{let col2=resolveCol2(s.field);if(!col2)return null;return s.direction==="desc"?desc3(col2):asc(col2)}).filter((o)=>o!==null);if(orderClauses.length>0)baseQuery=baseQuery.orderBy(...orderClauses)}let page=q.page??1,limit=q.limit??20,offset=q.offset??(page-1)*limit,countQuery=database.select().from(drizzleTable2);if(conditions.length>0){let{and:and6}=await import("drizzle-orm"),combined=and6(...conditions);if(combined)countQuery.where(combined)}let totalItems=(await countQuery).length;baseQuery=baseQuery.limit(limit).offset(offset);let items=await baseQuery,meta=buildPaginationMeta(page,limit,offset,totalItems);if(authEnabled&&authResult?.allowedFields)items=filterResponseFields(items,authResult.allowedFields);return{success:!0,data:{items,meta}}},{detail:{tags:[swaggerTag],summary:`List ${tableName}`,description:`Get paginated list of ${tableName} records with filtering, sorting, and search`}}),entityRoutes.get("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2,schemaRelations:schemaRelations2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,q=parseQueryParams(ctx.query),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=q.with?.map((w)=>w.name),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};if(q.with&&q.with.length>0&&tableRelations&&(databaseUrl||dbPool)){let allowedWith=authEnabled&&authResult?.allowedRelations?q.with.filter((w)=>authResult.allowedRelations?.includes(w.name)??!1):q.with,result2=await(dbPool?drizzle(dbPool,{schema:{...schemaTables2,...schemaRelations2}}):drizzle(databaseUrl,{schema:{...schemaTables2,...schemaRelations2}})).query[tableName]?.findFirst({where:eq10(idCol2,params.id),with:allowedWith.reduce((acc,rel)=>{return acc[rel.name]=rel.limit?{limit:rel.limit}:!0,acc},{})});if(authEnabled&&authResult?.allowedFields&&result2)result2=filterResponseFields(result2,authResult.allowedFields);if(authEnabled&&authResult?.allowedRelations&&result2)result2=filterResponseRelations(result2,authResult.allowedRelations);return{success:!0,data:result2||null}}let result=(await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)))[0]||null;if(authEnabled&&authResult?.allowedFields&&result)result=filterResponseFields(result,authResult.allowedFields);return{success:!0,data:result}},{detail:{tags:[swaggerTag],summary:`Get ${tableName} by ID`,description:`Get a single ${tableName} record by its ID with optional relations`}}),entityRoutes.get("/distinct/:field",async(ctx)=>{let{drizzleTable:drizzleTable2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let params=ctx.params,col2=resolveCol2(params.field);if(!col2)return{success:!1,message:"Field not found"};return{success:!0,data:await database.selectDistinct({value:col2}).from(drizzleTable2)}},{detail:{tags:[swaggerTag],summary:`Get distinct ${tableName} values`,description:`Get distinct values for a specific field in ${tableName}`}});if(!table.excluded_methods?.includes("POST"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let userId=ctx.request.headers.get("x-user-id"),postFormAuthResult=await performAuthCheck(ctx.request,"POST");if(postFormAuthResult&&!postFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postFormAuthResult.reason||"Forbidden"};let{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}let uploadedFiles=null;if(files.length>0){if(uploadedFiles=await uploadFiles(files,storageConfig,table.table_name),uploadedFiles.failed.length>0&&uploadedFiles.success.length===0)return{success:!1,message:"File upload failed",errors:uploadedFiles.failed};if(uploadedFiles.success.length>0){let firstFile=uploadedFiles.success[0];if(firstFile){let ext=firstFile.originalName.split(".").pop()||"";payload={...payload,id:firstFile.id,name:firstFile.name,originalName:firstFile.originalName,path:firstFile.path,mimeType:firstFile.mimeType,size:firstFile.size,extension:ext,uploadedBy:userId}}}}if(userId)payload.createdBy=userId;let result=await database.insert(drizzleTable2).values(payload).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",userId:userId||void 0,summary:`Created ${table.table_name}`,newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{type:"formdata",body:t3.Object({[storageConfig.formData.dataField]:t3.Optional(t3.Union([t3.String(),t3.Any()])),[storageConfig.formData.filesField]:t3.Optional(t3.Union([t3.File(),t3.Array(t3.File())]))}),detail:{tags:[swaggerTag],summary:`Create ${tableName} with files`,description:`Create a new ${tableName} record with file upload support`}});else entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2,schemaTables:schemaTables2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let payload=ctx.body,userId=ctx.request.headers.get("x-user-id"),postAuthResult=await performAuthCheck(ctx.request,"POST");if(postAuthResult&&!postAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postAuthResult.reason||"Forbidden"};if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(userId)payload.createdBy=userId;if(tableName==="userRoles"&&payload.userId&&payload.roleId){let cols=drizzleTable2,existing=await database.select().from(drizzleTable2).where(and5(eq10(cols.userId,payload.userId),eq10(cols.roleId,payload.roleId))).limit(1);if(existing.length>0)return{success:!0,data:existing[0]}}let result=await database.insert(drizzleTable2).values(payload).returning();if(tableName==="roleClaims"&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName==="userRoles"&&payload.roleId&&payload.userId)try{let{roles:rolesTable,users:usersTable}=schemaTables2;if(rolesTable&&usersTable){if((await database.select().from(rolesTable).where(eq10(rolesTable.id,payload.roleId)).limit(1))[0]?.name==="godmin")await database.update(usersTable).set({isGod:!0}).where(eq10(usersTable.id,payload.userId))}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole create")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",userId:userId||void 0,summary:`Created ${table.table_name}`,newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Create ${tableName}`,description:`Create a new ${tableName} record`}});if(!table.excluded_methods?.includes("PUT"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),putFormAuthResult=await performAuthCheck(ctx.request,"PUT");if(putFormAuthResult&&!putFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putFormAuthResult.reason||"Forbidden"};let{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data,oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}let uploadedFiles=null;if(files.length>0)uploadedFiles=await uploadFiles(files,storageConfig,table.table_name);let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:{record:result[0],files:uploadedFiles?.success||[],fileErrors:uploadedFiles?.failed||[]}}},{type:"formdata",body:t3.Object({[storageConfig.formData.dataField]:t3.Optional(t3.Union([t3.String(),t3.Any()])),[storageConfig.formData.filesField]:t3.Optional(t3.Union([t3.File(),t3.Array(t3.File())]))}),detail:{tags:[swaggerTag],summary:`Update ${tableName} with files`,description:`Full update of ${tableName} record with file upload support`}});else entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),putAuthResult=await performAuthCheck(ctx.request,"PUT");if(putAuthResult&&!putAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Update ${tableName}`,description:`Full update of ${tableName} record`}});if(!table.excluded_methods?.includes("PATCH"))entityRoutes.patch("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),patchAuthResult=await performAuthCheck(ctx.request,"PATCH");if(patchAuthResult&&!patchAuthResult.authorized)return ctx.set.status=403,{success:!1,message:patchAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(eq10(idCol2,params.id)).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"PATCH",userId:userId||void 0,summary:`Patched ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:result[0]}},{body:t3.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Patch ${tableName}`,description:`Partial update of ${tableName} record`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),deleteAuthResult=await performAuthCheck(ctx.request,"DELETE");if(deleteAuthResult&&!deleteAuthResult.authorized)return ctx.set.status=403,{success:!1,message:deleteAuthResult.reason||"Forbidden"};let oldRecord=await database.select().from(drizzleTable2).where(eq10(idCol2,params.id)).limit(1);if(await database.delete(drizzleTable2).where(eq10(idCol2,params.id)),tableName==="roleClaims"&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName==="userRoles"&&oldRecord[0])try{let deletedUserRole=oldRecord[0],rolesTable=schemaTables2.roles,usersTable=schemaTables2.users;if(rolesTable&&usersTable&&deletedUserRole.roleId&&deletedUserRole.userId){if((await database.select().from(rolesTable).where(eq10(rolesTable.id,deletedUserRole.roleId)).limit(1))[0]?.name==="godmin")await database.update(usersTable).set({isGod:!1}).where(eq10(usersTable.id,deletedUserRole.userId))}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole delete")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"DELETE",userId:userId||void 0,summary:`Deleted ${table.table_name} (${params.id})`,oldValues:oldRecord[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:null}},{detail:{tags:[swaggerTag],summary:`Delete ${tableName}`,description:`Delete a ${tableName} record`}});if(table.bulk_endpoints_enabled){if(!table.excluded_methods?.includes("POST"))entityRoutes.post("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};let userId=ctx.request.headers.get("x-user-id"),bulkPostAuth=await performAuthCheck(ctx.request,"POST");if(bulkPostAuth&&!bulkPostAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPostAuth.reason||"Forbidden"};try{let sanitizedItems=[];for(let raw of items){let payload=raw;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(userId)payload.createdBy=userId;sanitizedItems.push(payload)}return{success:!0,data:await database.transaction(async(tx)=>{let results=[];for(let payload of sanitizedItems){let result=await tx.insert(drizzleTable2).values(payload).returning();results.push(result[0])}return results})}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:t3.Array(t3.Object({},{additionalProperties:!0})),detail:{tags:[swaggerTag],summary:`Bulk create ${tableName}`,description:`Create multiple ${tableName} records`}});if(!table.excluded_methods?.includes("PUT"))entityRoutes.put("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};let userId=ctx.request.headers.get("x-user-id"),bulkPutAuth=await performAuthCheck(ctx.request,"PUT");if(bulkPutAuth&&!bulkPutAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPutAuth.reason||"Forbidden"};try{return{success:!0,data:await database.transaction(async(tx)=>{let results=[];for(let item of items){let payload=item.data;if(table.columns){payload=sanitizePayload(payload,table.columns);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await tx.update(drizzleTable2).set(payload).where(eq10(idCol2,item.id)).returning();results.push(result[0])}return results})}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:bulkUpdateSchema,detail:{tags:[swaggerTag],summary:`Bulk update ${tableName}`,description:`Update multiple ${tableName} records`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let ids=ctx.body;if(!Array.isArray(ids))return{success:!1,message:"Body must be an array of ids"};let bulkDeleteAuth=await performAuthCheck(ctx.request,"DELETE");if(bulkDeleteAuth&&!bulkDeleteAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkDeleteAuth.reason||"Forbidden"};try{return await database.transaction(async(tx)=>{for(let id of ids)await tx.delete(drizzleTable2).where(eq10(idCol2,id))}),{success:!0,data:{deleted:ids.length}}}catch(error){return{success:!1,message:error instanceof Error?error.message:"Transaction failed"}}},{body:bulkDeleteSchema,detail:{tags:[swaggerTag],summary:`Bulk delete ${tableName}`,description:`Delete multiple ${tableName} records`}})}app.use(entityRoutes)}return app}import Elysia4,{t as t4}from"elysia";function parseTimeToMs(time){let match=time.match(/^(\d+)(ms|s|m|h)$/);if(!match||!match[1]||!match[2])return 5000;let value=parseInt(match[1],10);switch(match[2]){case"ms":return value;case"s":return value*1000;case"m":return value*60*1000;case"h":return value*60*60*1000;default:return 5000}}function createMonitoringRoutes(config){let{monitoringService,logger:logger2,endpoints}=config,plugin=new Elysia4({prefix:endpoints.basePath});if(!endpoints.enabled)return plugin;if(endpoints.stream.enabled)plugin.get(endpoints.stream.path,async function*({request}){logger2.info("[Monitoring] SSE stream connected");let intervalMs=parseTimeToMs(endpoints.stream.interval),isConnected=!0;request.signal.addEventListener("abort",()=>{isConnected=!1,logger2.info("[Monitoring] SSE stream disconnected")});let initialSnapshot=await monitoringService.getLatestSnapshot();if(initialSnapshot)yield{event:"snapshot",data:JSON.stringify(initialSnapshot)};while(isConnected){if(await new Promise((resolve2)=>setTimeout(resolve2,intervalMs)),!isConnected)break;let snapshot=await monitoringService.getLatestSnapshot();if(snapshot)yield{event:"snapshot",data:JSON.stringify(snapshot)};let alerts=monitoringService.getActiveAlerts();if(alerts.length>0)yield{event:"alerts",data:JSON.stringify(alerts)}}},{detail:{tags:["Monitoring"],summary:"Stream real-time monitoring data",description:"Server-Sent Events stream for real-time monitoring metrics"}});if(endpoints.snapshot.enabled)plugin.get(endpoints.snapshot.path,async()=>{let snapshot=await monitoringService.getLatestSnapshot();if(!snapshot)return{isSuccess:!1,message:"No monitoring data available",data:null};return{isSuccess:!0,message:"Current monitoring snapshot",data:snapshot}},{detail:{tags:["Monitoring"],summary:"Get current monitoring snapshot",description:"Returns the latest monitoring metrics snapshot"}});if(endpoints.history.enabled)plugin.get(endpoints.history.path,async({query})=>{let minutes=Math.min(query.minutes?parseInt(String(query.minutes),10):60,endpoints.history.maxMinutes),history=await monitoringService.getHistory(minutes);return{isSuccess:!0,message:`Monitoring history for last ${minutes} minutes`,data:{minutes,count:history.length,snapshots:history}}},{query:t4.Object({minutes:t4.Optional(t4.Numeric())}),detail:{tags:["Monitoring"],summary:"Get monitoring history",description:"Returns historical monitoring data for the specified time range"}});if(endpoints.alerts.enabled)plugin.get(endpoints.alerts.path,()=>{let alerts=monitoringService.getActiveAlerts();return{isSuccess:!0,message:"Active alerts",data:{count:alerts.length,alerts}}},{detail:{tags:["Monitoring"],summary:"Get active alerts",description:"Returns all currently active monitoring alerts"}}),plugin.post(`${endpoints.alerts.path}/:alertId/acknowledge`,({params})=>{if(!monitoringService.acknowledgeAlert(params.alertId))return{isSuccess:!1,message:"Alert not found",data:null};return{isSuccess:!0,message:"Alert acknowledged",data:{alertId:params.alertId}}},{params:t4.Object({alertId:t4.String()}),detail:{tags:["Monitoring"],summary:"Acknowledge an alert",description:"Mark an alert as acknowledged"}});return logger2.info(`[Monitoring] Routes enabled at ${endpoints.basePath} (stream: ${endpoints.stream.enabled}, snapshot: ${endpoints.snapshot.enabled}, history: ${endpoints.history.enabled}, alerts: ${endpoints.alerts.enabled})`),plugin}import{eq as eq11}from"drizzle-orm";import{Elysia as Elysia5,t as t5}from"elysia";var RESERVED_SUBDOMAINS=["www","api","app","admin","dashboard","mail","ftp","cdn","static","assets","docs","help","support","status","blog","dev","staging","test","demo","localhost"],DEFAULT_SELF_SIGNUP_LIMITS={maxSignupsPerIpPerWindow:3,ipWindowMs:3600000,maxTenantsPerEmail:1};var col2=(table,name)=>table[name];function createCheckSubdomainRoute(config){let checkRoute=new Elysia5;return checkRoute.get("/tenants/check-subdomain/:subdomain",async(ctx)=>{let{subdomain}=ctx.params,normalized=subdomain.toLowerCase().trim();if(!/^[a-z][a-z0-9-]*$/.test(normalized)||normalized.length<2||normalized.length>63)return ctx.set.status=400,{isSuccess:!1,message:"Invalid subdomain format. Must start with a letter, contain only lowercase letters, numbers, and hyphens, and be 2-63 characters.",data:{available:!1,subdomain:normalized}};if(RESERVED_SUBDOMAINS.includes(normalized))return{isSuccess:!0,message:"Subdomain is reserved",data:{available:!1,subdomain:normalized}};let tenantRegistry=config.getTenantRegistry(),db=config.getDb();if(tenantRegistry){if(tenantRegistry.getActiveTenants().find((t6)=>t6.subdomain===normalized))return{isSuccess:!0,message:"Subdomain is already taken",data:{available:!1,subdomain:normalized}}}if(db&&tenantRegistry){let tenantsTable=tenantRegistry.getMainContext().schemaTables.tenants;if(tenantsTable)try{if((await db.select().from(tenantsTable).where(eq11(col2(tenantsTable,"subdomain"),normalized)).limit(1)).length>0)return{isSuccess:!0,message:"Subdomain is already taken",data:{available:!1,subdomain:normalized}}}catch{}}return{isSuccess:!0,message:"Subdomain is available",data:{available:!0,subdomain:normalized}}},{params:t5.Object({subdomain:t5.String({minLength:2,maxLength:63})}),detail:{tags:["Tenants"],summary:"Check subdomain availability",description:"Public endpoint to check if a subdomain is available for registration. No authentication required."}}),checkRoute}init_Logger2();import{eq as eq12}from"drizzle-orm";import{Elysia as Elysia6,t as t6}from"elysia";var col3=(table,name)=>table[name];function createManageRoutes(config){let log=config.logger.scoped(TENANT_SUSPEND),manageRoutes=new Elysia6;return manageRoutes.get("/tenants",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available",data:null};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required",data:null};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required",data:null};let allTenants=[...tenantRegistry.getActiveTenants(),...Array.from(getAllTenants(tenantRegistry)).filter((t7)=>t7.status!=="active")];return{success:!0,message:`Found ${allTenants.length} tenants`,data:{items:allTenants.map((t7)=>({id:t7.id,subdomain:t7.subdomain,schemaName:t7.schemaName,companyId:t7.companyId,companyName:t7.companyName,godAdminEmail:t7.godAdminEmail,status:t7.status,plan:t7.plan,domain:t7.domain,maxUsers:t7.maxUsers,provisionedAt:t7.provisionedAt,suspendedAt:t7.suspendedAt})),totalCount:allTenants.length}}},{detail:{tags:["Tenants"],summary:"List tenants",description:"List all tenants in the platform. Requires godmin privileges."}}),manageRoutes.get("/tenants/:id",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available",data:null};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required",data:null};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required",data:null};let{id}=ctx.params,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found",data:null};let features=tenantRegistry.getTenantFeatures(id);return{success:!0,message:"Tenant found",data:{...tenant,features:features.map((f)=>({featureName:f.featureName,enabled:f.enabled}))}}},{detail:{tags:["Tenants"],summary:"Get tenant details",description:"Get detailed information about a specific tenant. Requires godmin privileges."}}),manageRoutes.post("/tenants/:id/suspend",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let{id}=ctx.params,body=ctx.body,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found"};if(tenant.status==="suspended")return ctx.set.status=400,{success:!1,message:"Tenant is already suspended"};let mainContext=tenantRegistry.getMainContext(),tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available"};let now=new Date;await db.update(tenantsTable).set({status:"suspended",suspendedAt:now,suspendedReason:body.reason||"Suspended by godmin",updatedAt:now}).where(eq12(col3(tenantsTable,"id"),id));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId:id,eventType:"suspended",eventData:JSON.stringify({reason:body.reason||"Suspended by godmin"}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record suspend event")}return await tenantRegistry.refreshTenant(id),log.info("Tenant suspended",{tenantId:id,reason:body.reason}),{success:!0,message:`Tenant "${tenant.subdomain}" suspended`}},{body:t6.Object({reason:t6.Optional(t6.String())}),detail:{tags:["Tenants"],summary:"Suspend tenant",description:"Suspend a tenant, preventing all access. Requires godmin privileges."}}),manageRoutes.post("/tenants/:id/reactivate",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant management not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};if(!await verifyGodmin(db,tenantRegistry,requestingUserId))return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let{id}=ctx.params,tenant=tenantRegistry.getTenantById(id);if(!tenant)return ctx.set.status=404,{success:!1,message:"Tenant not found"};if(tenant.status!=="suspended")return ctx.set.status=400,{success:!1,message:`Tenant is not suspended (current: ${tenant.status})`};let mainContext=tenantRegistry.getMainContext(),tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available"};let now=new Date;await db.update(tenantsTable).set({status:"active",suspendedAt:null,suspendedReason:null,updatedAt:now}).where(eq12(col3(tenantsTable,"id"),id));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId:id,eventType:"reactivated",eventData:JSON.stringify({previousReason:tenant.suspendedReason}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record reactivate event")}return await tenantRegistry.refreshTenant(id),log.info("Tenant reactivated",{tenantId:id}),{success:!0,message:`Tenant "${tenant.subdomain}" reactivated`}},{detail:{tags:["Tenants"],summary:"Reactivate tenant",description:"Reactivate a suspended tenant. Requires godmin privileges."}}),manageRoutes}var verifyGodmin=async(db,tenantRegistry,userId)=>{let usersTable=tenantRegistry.getMainContext().schemaTables.users;if(!usersTable)return!1;return(await db.select().from(usersTable).where(eq12(col3(usersTable,"id"),userId)).limit(1))[0]?.isGod===!0},getAllTenants=(registry)=>{let schemaNames=registry.getAllSchemaNames(),tenants=[];for(let name of schemaNames){let ctx=registry.getSchemaContext(name);if(ctx?.tenant)tenants.push(ctx.tenant)}return tenants};init_Logger2();init_utils6();import{eq as eq13}from"drizzle-orm";import{Elysia as Elysia7,t as t7}from"elysia";var col4=(table,name)=>table[name],ProvisionBodySchema=t7.Object({subdomain:t7.String({minLength:2,maxLength:63,pattern:"^[a-z][a-z0-9-]*$"}),companyId:t7.String({minLength:1}),companyName:t7.Optional(t7.String()),godAdminEmail:t7.String({format:"email"}),plan:t7.Optional(t7.String()),domain:t7.Optional(t7.String())});function createProvisionRoute(config){let log=config.logger.scoped(TENANT_PROVISION),provisionRoutes=new Elysia7;return provisionRoutes.post("/tenants/provision",async(ctx)=>{let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant provisioning not available"};let requestingUserId=ctx.request.headers.get("x-user-id");if(!requestingUserId)return ctx.set.status=401,{success:!1,message:"Authentication required"};let mainContext=tenantRegistry.getMainContext(),usersTable=mainContext.schemaTables.users;if(!usersTable)return ctx.set.status=503,{success:!1,message:"Users table not available"};let requestingUser=(await db.select().from(usersTable).where(eq13(col4(usersTable,"id"),requestingUserId)).limit(1))[0];if(!requestingUser||!requestingUser.isGod)return ctx.set.status=403,{success:!1,message:"Godmin privileges required"};let body=ctx.body,tenantSchemaName=`tenant_${body.subdomain.replace(/-/g,"_")}`;if(tenantRegistry.getActiveTenants().find((t8)=>t8.subdomain===body.subdomain))return ctx.set.status=409,{success:!1,message:`Subdomain "${body.subdomain}" is already taken`};let tenantsTable=mainContext.schemaTables.tenants;if(!tenantsTable)return ctx.set.status=503,{success:!1,message:"Tenants table not available in main schema"};let tenantId=crypto.randomUUID(),now=new Date;try{await db.insert(tenantsTable).values({id:tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName,companyId:body.companyId,companyName:body.companyName||null,godAdminEmail:body.godAdminEmail,status:"provisioning",plan:body.plan||null,domain:body.domain||null,createdAt:now,updatedAt:now}),log.info("Tenant record created",{tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Failed to insert tenant record",{error:msg}),ctx.set.status=500,{success:!1,message:`Failed to create tenant record: ${msg}`}}try{let tenantRecord={id:tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName,companyId:body.companyId,companyName:body.companyName||null,godAdminEmail:body.godAdminEmail,status:"provisioning",plan:body.plan||null,domain:body.domain||null,settings:{},trustedSources:[],maxUsers:null,provisionedAt:null,suspendedAt:null,suspendedReason:null},tenantContext=await tenantRegistry.provisionTenant(tenantRecord);log.info("Schema provisioned",{tenantId,schemaName:tenantSchemaName,tableCount:Object.keys(tenantContext.schemaTables).length});let tenantUsersTable=tenantContext.schemaTables.users;if(tenantUsersTable){let godminId=crypto.randomUUID(),tempPassword=crypto.randomUUID().slice(0,16),hashedPassword=await hashPassword(tempPassword);await db.insert(tenantUsersTable).values({id:godminId,email:body.godAdminEmail,password:hashedPassword,isGod:!0,isActive:!0,createdAt:now,updatedAt:now}),log.info("Godmin user seeded",{tenantId,godminEmail:body.godAdminEmail,godminId})}await db.update(tenantsTable).set({status:"active",provisionedAt:now,updatedAt:now}).where(eq13(col4(tenantsTable,"id"),tenantId));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId,eventType:"provisioned",eventData:JSON.stringify({schemaName:tenantSchemaName,godAdminEmail:body.godAdminEmail,plan:body.plan||null}),performedBy:requestingUserId,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",createdAt:now,updatedAt:now})}catch{log.warn("Failed to record tenant_event, continuing")}return await tenantRegistry.refreshTenant(tenantId),log.info("Provisioning complete",{tenantId,subdomain:body.subdomain,schemaName:tenantSchemaName}),await config.logger.audit({entityName:"tenants",entityId:tenantId,operation:"PROVISION",userId:requestingUserId,summary:`Tenant "${body.subdomain}" provisioned by godmin`,ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:new URL(ctx.request.url).pathname,query:""}),{success:!0,message:"Tenant provisioned successfully",data:{tenantId,schemaName:tenantSchemaName,subdomain:body.subdomain,godAdminEmail:body.godAdminEmail,status:"active"}}}catch(err){let msg=err instanceof Error?err.message:String(err);log.error("Provisioning failed",{error:msg,tenantId});try{await db.update(tenantsTable).set({status:"provisioning",updatedAt:now}).where(eq13(col4(tenantsTable,"id"),tenantId))}catch{}return ctx.set.status=500,{success:!1,message:`Provisioning failed: ${msg}`}}},{body:ProvisionBodySchema,detail:{tags:["Tenants"],summary:"Provision new tenant",description:"Create a new tenant with its own schema, tables, and godmin user. Requires godmin privileges."}}),provisionRoutes}init_Logger2();init_utils6();import{eq as eq14}from"drizzle-orm";import{Elysia as Elysia8,t as t8}from"elysia";var col5=(table,name)=>table[name],ipRateMap=new Map,lastCleanup=Date.now();function cleanupRateMap(windowMs){let now=Date.now();if(now-lastCleanup<600000)return;lastCleanup=now;for(let[key,entry]of ipRateMap.entries())if(now-entry.windowStart>windowMs)ipRateMap.delete(key)}function isIpRateLimited(ip,maxPerWindow,windowMs){let now=Date.now(),entry=ipRateMap.get(ip);if(!entry||now-entry.windowStart>windowMs)return ipRateMap.set(ip,{count:1,windowStart:now}),!1;return entry.count++,entry.count>maxPerWindow}var SelfSignupBodySchema=t8.Object({email:t8.String({format:"email"}),password:t8.String({minLength:8}),subdomain:t8.String({minLength:2,maxLength:63,pattern:"^[a-z][a-z0-9-]*$"}),plan:t8.Optional(t8.String()),companyName:t8.Optional(t8.String())});function createSelfSignupRoute(config){let log=config.logger.scoped(TENANT_SELF_SIGNUP),limits={...DEFAULT_SELF_SIGNUP_LIMITS,...config.selfSignupLimits},selfSignupRoutes=new Elysia8;return selfSignupRoutes.post("/tenants/self-signup",async(ctx)=>{cleanupRateMap(limits.ipWindowMs);let db=config.getDb(),tenantRegistry=config.getTenantRegistry();if(!db||!tenantRegistry)return ctx.set.status=503,{success:!1,message:"Tenant provisioning not available"};let ip=ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown";if(isIpRateLimited(ip,limits.maxSignupsPerIpPerWindow,limits.ipWindowMs))return log.warn("Self-signup rate limited",{ip}),ctx.set.status=429,{success:!1,message:"Too many signup attempts. Please try again later."};let body=ctx.body,email=body.email.toLowerCase().trim(),subdomain=body.subdomain.toLowerCase().trim();if(RESERVED_SUBDOMAINS.includes(subdomain))return ctx.set.status=400,{success:!1,message:"This subdomain is reserved."};let mainContext=tenantRegistry.getMainContext(),usersTable=mainContext.schemaTables.users,tenantsTable=mainContext.schemaTables.tenants;if(!usersTable||!tenantsTable)return ctx.set.status=503,{success:!1,message:"Required tables not available."};if(tenantRegistry.getActiveTenants().find((t9)=>t9.subdomain===subdomain))return ctx.set.status=409,{success:!1,message:"This subdomain is already taken."};try{if((await db.select().from(tenantsTable).where(eq14(col5(tenantsTable,"subdomain"),subdomain)).limit(1)).length>0)return ctx.set.status=409,{success:!1,message:"This subdomain is already taken."}}catch{}try{if((await db.select().from(tenantsTable).where(eq14(col5(tenantsTable,"godAdminEmail"),email))).length>=limits.maxTenantsPerEmail)return ctx.set.status=409,{success:!1,message:`Tenant limit reached. Maximum ${limits.maxTenantsPerEmail} tenant(s) per account.`}}catch{}let userId,hashedPassword=await hashPassword(body.password),now=new Date,existingUsers=await db.select().from(usersTable).where(eq14(col5(usersTable,"email"),email)).limit(1);if(existingUsers.length>0)userId=existingUsers[0].id,log.info("Self-signup: existing user resolved",{userId,email});else{userId=crypto.randomUUID();try{await db.insert(usersTable).values({id:userId,email,password:hashedPassword,isActive:!0,createdAt:now,updatedAt:now}),log.info("Self-signup: user created",{userId,email})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Self-signup: user creation failed",{error:msg}),ctx.set.status=500,{success:!1,message:"Failed to create account."}}}let tenantId=crypto.randomUUID(),tenantSchemaName=`tenant_${subdomain.replace(/-/g,"_")}`;try{await db.insert(tenantsTable).values({id:tenantId,subdomain,schemaName:tenantSchemaName,companyId:userId,companyName:body.companyName||subdomain,godAdminEmail:email,status:"provisioning",plan:body.plan||null,createdAt:now,updatedAt:now}),log.info("Tenant record created",{tenantId,subdomain})}catch(err){let msg=err instanceof Error?err.message:String(err);return log.error("Tenant record creation failed",{error:msg}),ctx.set.status=500,{success:!1,message:"Failed to create tenant."}}try{let tenantRecord={id:tenantId,subdomain,schemaName:tenantSchemaName,companyId:userId,companyName:body.companyName||subdomain,godAdminEmail:email,status:"provisioning",plan:body.plan||null,domain:null,settings:{},trustedSources:[],maxUsers:null,provisionedAt:null,suspendedAt:null,suspendedReason:null},tenantContext=await tenantRegistry.provisionTenant(tenantRecord);log.info("Schema provisioned",{tenantId,schemaName:tenantSchemaName,tableCount:Object.keys(tenantContext.schemaTables).length});let tenantUsersTable=tenantContext.schemaTables.users;if(tenantUsersTable)await db.insert(tenantUsersTable).values({id:userId,email,password:hashedPassword,isGod:!0,isActive:!0,createdAt:now,updatedAt:now}),log.info("Godmin seeded in tenant schema",{tenantId,email,userId});await db.update(tenantsTable).set({status:"active",provisionedAt:now,updatedAt:now}).where(eq14(col5(tenantsTable,"id"),tenantId));let tenantEventsTable=mainContext.schemaTables.tenantEvents;if(tenantEventsTable)try{await db.insert(tenantEventsTable).values({id:crypto.randomUUID(),tenantId,eventType:"self_signup",eventData:JSON.stringify({email,subdomain,plan:body.plan||null}),performedBy:userId,ipAddress:ip,createdAt:now,updatedAt:now})}catch{}return await tenantRegistry.refreshTenant(tenantId),log.info("Self-signup complete",{tenantId,subdomain,email}),await config.logger.audit({entityName:"tenants",entityId:tenantId,operation:"SELF_SIGNUP",userId,summary:`Self-signup: tenant "${subdomain}" provisioned by ${email}`,ipAddress:ip,userAgent:ctx.request.headers.get("user-agent")||"unknown",path:new URL(ctx.request.url).pathname,query:""}),{success:!0,message:"Tenant created successfully",data:{tenantId,subdomain,schemaName:tenantSchemaName,userId,email,status:"active"}}}catch(err){let msg=err instanceof Error?err.message:String(err);log.error("Self-signup provisioning failed",{error:msg,tenantId});try{await db.update(tenantsTable).set({status:"provisioning",updatedAt:now}).where(eq14(col5(tenantsTable,"id"),tenantId))}catch{}return ctx.set.status=500,{success:!1,message:"Provisioning failed. Please try again."}}},{body:SelfSignupBodySchema,detail:{tags:["Tenants"],summary:"Self-service tenant signup",description:"Public endpoint for self-service signup. Creates user account, provisions tenant schema, and seeds godmin. Rate-limited by IP with configurable max tenants per email."}}),selfSignupRoutes}function createTenantRoutes(app,config){return app.use(createCheckSubdomainRoute(config)),app.use(createProvisionRoute(config)),app.use(createSelfSignupRoute(config)),app.use(createManageRoutes(config)),app}import Elysia9,{t as t9}from"elysia";var STREAM_HEADERS={"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"},textEncoder=new TextEncoder,encodeEvent=(event,data)=>{let payload=typeof data==="string"?data:JSON.stringify(data);return textEncoder.encode(`event: ${event}
|
|
189
189
|
data: ${payload}
|
|
190
190
|
|
|
191
191
|
`)};function createLiveMonitoringRoutes(config){let{getService,logger:logger2,basePath,streamInterval}=config,plugin=new Elysia9({prefix:basePath}),requireService=()=>{let svc=getService();if(!svc)throw Error("Live monitoring service not initialized");return svc};return plugin.get("/health",()=>{let svc=getService();return{status:svc?"ok":"initializing",timestamp:Date.now(),monitoring:svc?.isEnabled()??!1}},{detail:{tags:["Live Monitoring"],summary:"Health check for live monitoring"}}),plugin.get("/settings",()=>{return requireService().getSettings()},{detail:{tags:["Live Monitoring"],summary:"Get live monitoring settings"}}),plugin.patch("/settings",({body})=>{return requireService().changeSettings(body)},{body:t9.Partial(t9.Object({logMemory:t9.Boolean(),logCpu:t9.Boolean(),logDapr:t9.Boolean(),logWebSocket:t9.Boolean(),memoryLogInterval:t9.Number(),cpuLogInterval:t9.Number(),memoryLogLimit:t9.Number(),cpuLogLimit:t9.Number(),daprLogLimit:t9.Number(),wsLogLimit:t9.Number(),requestLogLimit:t9.Number()})),detail:{tags:["Live Monitoring"],summary:"Change live monitoring settings"}}),plugin.get("/logs",()=>{return requireService().getLogs()},{detail:{tags:["Live Monitoring"],summary:"Get all live monitoring logs"}}),plugin.get("/logs/stream",({request})=>{let abortSignal=request.signal,cleanup,svc=requireService(),snapshot=svc.getSnapshot(),lastTimestamps={memory:snapshot.memory.length?snapshot.memory[snapshot.memory.length-1]?.timestamp??0:0,cpu:snapshot.cpu.length?snapshot.cpu[snapshot.cpu.length-1]?.timestamp??0:0,request:snapshot.requests.length?snapshot.requests[snapshot.requests.length-1]?.timestamp??0:0,dapr:snapshot.dapr.length?snapshot.dapr[snapshot.dapr.length-1]?.timestamp??0:0,ws:snapshot.ws.length?snapshot.ws[snapshot.ws.length-1]?.timestamp??0:0},stream=new ReadableStream({start(controller){let closed=!1;controller.enqueue(encodeEvent("snapshot",snapshot));let interval=setInterval(()=>{if(closed)return;let update=svc.getUpdatesSince(lastTimestamps);if(!update){controller.enqueue(encodeEvent("heartbeat",{timestamp:Date.now()}));return}if(update.memory.length)lastTimestamps.memory=update.memory[update.memory.length-1]?.timestamp??lastTimestamps.memory;if(update.cpu.length)lastTimestamps.cpu=update.cpu[update.cpu.length-1]?.timestamp??lastTimestamps.cpu;if(update.requests.length)lastTimestamps.request=update.requests[update.requests.length-1]?.timestamp??lastTimestamps.request;if(update.dapr.length)lastTimestamps.dapr=update.dapr[update.dapr.length-1]?.timestamp??lastTimestamps.dapr;if(update.ws.length)lastTimestamps.ws=update.ws[update.ws.length-1]?.timestamp??lastTimestamps.ws;controller.enqueue(encodeEvent("update",update))},streamInterval),cleanupHandler=()=>{if(closed)return;closed=!0,clearInterval(interval),abortSignal?.removeEventListener("abort",cleanupHandler);try{controller.close()}catch{}};cleanup=cleanupHandler,abortSignal?.addEventListener("abort",cleanupHandler)},cancel(){cleanup?.()}});return new Response(stream,{headers:STREAM_HEADERS})},{detail:{tags:["Live Monitoring"],summary:"Stream real-time live monitoring data via SSE"}}),logger2.info(`[LiveMonitoring] Routes enabled at ${basePath} (stream interval: ${streamInterval}ms)`),plugin}import Elysia10 from"elysia";var recentAcks=new Map;var cleanupInterval=null;function cleanupRecentAcks(){let now=Date.now();for(let[key,timestamp]of recentAcks)if(now-timestamp>1e4)recentAcks.delete(key)}var stats={totalSent:0,totalAcked:0,totalFailed:0,averageLatencyMs:0};function initAckCleanup(){if(cleanupInterval)return;cleanupInterval=setInterval(cleanupRecentAcks,30000)}function generateMessageId(){return`msg_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}async function storePendingMessage(redis,message,ttlSeconds){if(!message.userId)return;let key=`pubsub:pending:user:${message.userId}:${message.messageId}`,setKey=`pubsub:user:pending-set:${message.userId}`;await redis.create(key,message,ttlSeconds);let existingResult=await redis.read(setKey),existingSet=existingResult.success&&existingResult.data?existingResult.data:[];if(!existingSet.includes(message.messageId))existingSet.push(message.messageId),await redis.create(setKey,existingSet,ttlSeconds)}async function acknowledgeMessage(redis,userId,messageId,ttlSeconds){let dedupKey=`${userId}:${messageId}`;if(recentAcks.has(dedupKey))return!1;let pendingKey=`pubsub:pending:user:${userId}:${messageId}`,setKey=`pubsub:user:pending-set:${userId}`,ackKey=`pubsub:ack:${userId}:${messageId}`,pendingResult=await redis.read(pendingKey);if(!pendingResult.success||!pendingResult.data)return recentAcks.set(dedupKey,Date.now()),!1;recentAcks.set(dedupKey,Date.now());let pending=pendingResult.data,ack={messageId,clientId:pending.clientId,ackedAt:Date.now()};await redis.create(ackKey,ack,60),await redis.remove(pendingKey);let setResult=await redis.read(setKey),updatedSet=(setResult.success&&setResult.data?setResult.data:[]).filter((id)=>id!==messageId);if(updatedSet.length>0)await redis.create(setKey,updatedSet,ttlSeconds);else await redis.remove(setKey);let latencyMs=Date.now()-pending.sentAt;return recordAcked(latencyMs),!0}async function getPendingMessagesForUser(redis,userId){if(!userId)return[];let setKey=`pubsub:user:pending-set:${userId}`,setResult=await redis.read(setKey),messageIds=setResult.success&&setResult.data?setResult.data:[],messages=[];for(let messageId of messageIds){let key=`pubsub:pending:user:${userId}:${messageId}`,msgResult=await redis.read(key);if(msgResult.success&&msgResult.data)messages.push(msgResult.data)}return messages.sort((a,b)=>a.sentAt-b.sentAt),messages}async function getPendingMessageCount(redis,userId){if(!userId)return 0;let setKey=`pubsub:user:pending-set:${userId}`,setResult=await redis.read(setKey);return(setResult.success&&setResult.data?setResult.data:[]).length}async function incrementRetryCount(redis,userId,messageId,ttlSeconds,maxRetries){let key=`pubsub:pending:user:${userId}:${messageId}`,msgResult=await redis.read(key);if(!msgResult.success||!msgResult.data)return!1;let message={...msgResult.data,retryCount:msgResult.data.retryCount+1};if(message.retryCount>=maxRetries)return await removePendingMessage(redis,userId,messageId),recordFailed(),!1;return await redis.create(key,message,ttlSeconds),!0}async function removePendingMessage(redis,userId,messageId){let key=`pubsub:pending:user:${userId}:${messageId}`,setKey=`pubsub:user:pending-set:${userId}`;await redis.remove(key);let setResult=await redis.read(setKey),updatedSet=(setResult.success&&setResult.data?setResult.data:[]).filter((id)=>id!==messageId);if(updatedSet.length>0)await redis.create(setKey,updatedSet,300);else await redis.remove(setKey)}function recordSent(){stats.totalSent++}function recordAcked(latencyMs){stats.totalAcked++,stats.averageLatencyMs=(stats.averageLatencyMs*(stats.totalAcked-1)+latencyMs)/stats.totalAcked}function recordFailed(){stats.totalFailed++}var clients=new Map,presenceBroadcastDebounce=new Map;function createClientManager(config){let{redis,logger:logger2}=config,ackTtl=config.ack.ttlSeconds,ackEnabled=config.ack.enabled,maxRetries=config.ack.maxRetries,presenceEnabled=config.presence.enabled,presenceDebounceMs=config.presence.debounceMs,maxClientsPerUser=config.maxClientsPerUser;function generateClientId(){return`client_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}function registerClient(clientId,ws,userId,topics){let existingClients=getClientsByUser(userId);if(existingClients.length>=maxClientsPerUser){let oldestClientId=existingClients[0];if(oldestClientId)logger2.info("[PubSub] Max clients reached, closing oldest",{userId,oldestClientId}),unregisterClient(oldestClientId)}clients.set(clientId,{ws,userId,subscribedTopics:new Set(topics),connectedAt:Date.now(),pendingAcks:new Map}),logger2.info("[PubSub] Client registered",{clientId,userId,topics,totalClients:clients.size})}function unregisterClient(clientId){let client=clients.get(clientId);if(!client)return;let userId=client.userId;if(clients.delete(clientId),logger2.info("[PubSub] Client unregistered",{clientId,userId,totalClients:clients.size}),presenceEnabled&&userId){if(getClientsByUser(userId).length===0)broadcastPresenceToOthers(userId,"offline")}}function updateClientTopics(clientId,topics){let client=clients.get(clientId);if(client)client.subscribedTopics=new Set(topics)}function getClientsByUser(userId){let result=[];for(let[clientId,client]of clients)if(client.userId===userId)result.push(clientId);return result}function getConnectedUserIds(){let userIds=new Set;for(let[,client]of clients)if(client.userId)userIds.add(client.userId);return userIds}function getClientCount(){return clients.size}function sendToClient(clientId,message){let client=clients.get(clientId);if(!client)return!1;try{return client.ws.send(JSON.stringify(message)),!0}catch{return clients.delete(clientId),!1}}function broadcastEvent(topic,event){let messageId=generateMessageId(),timestamp=Date.now(),payload=JSON.stringify({type:"event",messageId:ackEnabled?messageId:void 0,topic,data:event,timestamp}),sentCount=0;for(let[clientId,client]of clients)if(client.subscribedTopics.has("*")||client.subscribedTopics.has(topic))try{if(client.ws.send(payload),sentCount++,ackEnabled){if(client.pendingAcks.set(messageId,{sentAt:timestamp,retryCount:0}),recordSent(),client.userId)storePendingMessage(redis,{messageId,topic,clientId,userId:client.userId,data:event,sentAt:timestamp,retryCount:0,maxRetries},ackTtl).catch(()=>{})}}catch{clients.delete(clientId)}logger2.info("[PubSub] Broadcasted event",{topic,messageId,sentCount})}function broadcastToUser(userId,topic,event){let messageId=generateMessageId(),timestamp=Date.now(),payload=JSON.stringify({type:"event",messageId:ackEnabled?messageId:void 0,topic,data:event,timestamp}),sentCount=0,sentToAnyClient=!1;for(let[clientId,client]of clients){if(client.userId!==userId)continue;if(!client.subscribedTopics.has("*")&&!client.subscribedTopics.has(topic))continue;try{if(client.ws.send(payload),sentCount++,sentToAnyClient=!0,ackEnabled)client.pendingAcks.set(messageId,{sentAt:timestamp,retryCount:0}),recordSent()}catch{clients.delete(clientId)}}if(ackEnabled)storePendingMessage(redis,{messageId,topic,clientId:sentToAnyClient?"delivered":"pending",userId,data:event,sentAt:timestamp,retryCount:0,maxRetries},ackTtl).catch(()=>{});logger2.info("[PubSub] Broadcasted to user",{userId,topic,messageId,sentCount,storedForOffline:!sentToAnyClient})}function broadcastToUserNoAck(userId,topic,event){let timestamp=Date.now(),payload=JSON.stringify({type:"event",topic,data:event,timestamp});for(let[clientId,client]of clients){if(client.userId!==userId)continue;if(!client.subscribedTopics.has("*")&&!client.subscribedTopics.has(topic))continue;try{client.ws.send(payload)}catch{clients.delete(clientId)}}}function broadcastPresenceToOthers(userId,status){let debounceKey=`${userId}:${status}`,now=Date.now(),lastBroadcast=presenceBroadcastDebounce.get(debounceKey);if(lastBroadcast&&now-lastBroadcast<presenceDebounceMs)return;if(presenceBroadcastDebounce.set(debounceKey,now),presenceBroadcastDebounce.size>1000){let cutoff=now-presenceDebounceMs*2;for(let[key,timestamp]of presenceBroadcastDebounce)if(timestamp<cutoff)presenceBroadcastDebounce.delete(key)}let connectedUserIds=getConnectedUserIds();for(let targetUserId of connectedUserIds)if(targetUserId!==userId)broadcastToUserNoAck(targetUserId,"user-presence",{type:"user-presence",data:{userId,status}})}async function handleClientAck(clientId,messageId){if(!ackEnabled)return!0;let client=clients.get(clientId);if(!client)return!1;if(client.pendingAcks.get(messageId))client.pendingAcks.delete(messageId);if(client.userId)return acknowledgeMessage(redis,client.userId,messageId,ackTtl);return!0}async function deliverPendingMessages(userId,clientId){if(!ackEnabled)return 0;let client=clients.get(clientId);if(!client||client.userId!==userId)return 0;let pendingMessages=await getPendingMessagesForUser(redis,userId);if(pendingMessages.length===0)return 0;logger2.info("[PubSub] Delivering pending messages",{userId,count:pendingMessages.length});let deliveredCount=0;for(let message of pendingMessages){if(!client.subscribedTopics.has("*")&&!client.subscribedTopics.has(message.topic))continue;let payload=JSON.stringify({type:"event",messageId:message.messageId,topic:message.topic,data:message.data,timestamp:message.sentAt,isRedelivery:!0});try{client.ws.send(payload),client.pendingAcks.set(message.messageId,{sentAt:Date.now(),retryCount:message.retryCount+1}),await incrementRetryCount(redis,userId,message.messageId,ackTtl,maxRetries),deliveredCount++}catch{break}}return deliveredCount}return{generateClientId,registerClient,unregisterClient,updateClientTopics,getClientsByUser,getConnectedUserIds,getClientCount,sendToClient,broadcastEvent,broadcastToUser,broadcastToUserNoAck,broadcastPresenceToOthers,handleClientAck,deliverPendingMessages,getPendingMessageCount:(userId)=>getPendingMessageCount(redis,userId)}}function createPubSubRoutes(config){let{logger:logger2,getLiveMonitoringService}=config,clientManager=createClientManager(config);if(config.ack.enabled)initAckCleanup();let cleanupTimer=null,plugin=new Elysia10;return plugin.onStart(()=>{if(config.cleanupIntervalMs>0)cleanupTimer=setInterval(()=>{logger2.info("[PubSub] Periodic cleanup running",{totalClients:clientManager.getClientCount()})},config.cleanupIntervalMs);logger2.info("[PubSub] Routes initialized",{basePath:config.basePath,wsPath:config.wsPath,ackEnabled:config.ack.enabled,presenceEnabled:config.presence.enabled})}),plugin.onStop(()=>{if(cleanupTimer)clearInterval(cleanupTimer),cleanupTimer=null}),plugin.post(`${config.basePath}/:topic`,async({params,body,request,set})=>{let topic=params.topic,eventData;try{if(!body){let text=await request.text();eventData=JSON.parse(text)}else eventData=body}catch{return set.status=200,{status:"DROP"}}logger2.info("[PubSub] Dapr event received",{topic,eventId:eventData.id,source:eventData.source});let userId=eventData.data?.user_id;if(userId)clientManager.broadcastToUser(userId,topic,eventData);else clientManager.broadcastEvent(topic,eventData);return getLiveMonitoringService?.()?.recordDaprEvent("pubsub_subscribe",{topic,success:!0,metadata:{eventId:eventData.id,source:eventData.source,userId:userId||null}}),set.status=200,{status:"SUCCESS"}}),plugin.ws(config.wsPath,{idleTimeout:config.wsIdleTimeout,open(ws){let query=ws.data?.query||{};if(!query.userId){ws.send(JSON.stringify({type:"error",error:"userId is required for WebSocket connection",timestamp:Date.now()})),ws.close(4001,"userId is required"),getLiveMonitoringService?.()?.recordWsEvent("error",{success:!1,error:"userId is required"});return}let clientId=clientManager.generateClientId(),topics=query.topics?.split(",").map((t10)=>t10.trim())||["*"];if(ws.data.clientId=clientId,clientManager.registerClient(clientId,ws,query.userId,topics),ws.send(JSON.stringify({type:"connected",clientId,subscribedTopics:topics,timestamp:Date.now()})),getLiveMonitoringService?.()?.recordWsEvent("connection",{clientId,userId:query.userId,topic:topics.join(","),success:!0}),config.presence.enabled)clientManager.broadcastPresenceToOthers(query.userId,"online");let connectedUserId=query.userId;if(config.ack.enabled&&connectedUserId)clientManager.getPendingMessageCount(connectedUserId).then((count)=>{if(count>0)logger2.info("[PubSub] Delivering pending messages",{userId:connectedUserId,count}),clientManager.deliverPendingMessages(connectedUserId,clientId).catch(()=>{})}).catch(()=>{})},message(ws,message){let clientId=ws.data.clientId;try{let parsed=null;if(typeof message==="string")parsed=JSON.parse(message);else if(message&&typeof message==="object"){if(parsed="type"in message?message:null,typeof parsed==="string")parsed=JSON.parse(parsed)}if(!parsed?.type)return;switch(getLiveMonitoringService?.()?.recordWsEvent("message",{clientId,messageType:parsed.type,success:!0,dataSize:typeof message==="string"?message.length:0}),parsed.type){case"subscribe":if(Array.isArray(parsed.topics))clientManager.updateClientTopics(clientId,parsed.topics),clientManager.sendToClient(clientId,{type:"subscribed",topics:parsed.topics,timestamp:Date.now()});break;case"unsubscribe":logger2.info("[PubSub] Unsubscribe request",{clientId,topics:parsed.topics});break;case"ping":clientManager.sendToClient(clientId,{type:"pong",timestamp:Date.now()});break;case"ack":if(parsed.messageId)clientManager.handleClientAck(clientId,parsed.messageId).catch(()=>{});break}}catch{logger2.warn("[PubSub] Failed to parse client message",{clientId})}},close(ws,code,reason){let clientId=ws.data.clientId;if(clientId)clientManager.unregisterClient(clientId);getLiveMonitoringService?.()?.recordWsEvent("close",{clientId,success:!0,metadata:{code,reason:reason||""}}),logger2.info("[PubSub] Client disconnected",{clientId,code,reason})}}),{plugin,clientManager}}init_Notification();init_Verification();import{Elysia as Elysia11,t as t10}from"elysia";function createVerificationRoutes(routeConfig){let{db,schemaTables,config,logger:logger2,tenantRegistry}=routeConfig,defaultVerificationService=new VerificationService({db,schemaTables,config,logger:logger2}),defaultNotificationService=new NotificationService({db,schemaTables,config:routeConfig.notificationConfig||{enabled:!1},logger:logger2,emailService:routeConfig.emailService}),wireNotificationHandler=(verSvc,notifSvc)=>{verSvc.setNotificationHandler(async(params)=>{if(!routeConfig.notificationConfig?.enabled)return;await notifSvc.triggerNotifications({trigger:params.trigger,flow_id:params.flow_id,entity_name:params.entity_name,entity_id:params.entity_id,node_id:params.node_id,verifier_id:params.verifier_id,decision:params.decision,context:params.context})})};wireNotificationHandler(defaultVerificationService,defaultNotificationService);let getServicesForRequest=(request)=>{if(!tenantRegistry)return{verificationService:defaultVerificationService,notificationService:defaultNotificationService};let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return{verificationService:defaultVerificationService,notificationService:defaultNotificationService};let ctx=tenantRegistry.getSchemaContext(schemaName);if(!ctx)return{verificationService:defaultVerificationService,notificationService:defaultNotificationService};let reqVerSvc=new VerificationService({db,schemaTables:ctx.schemaTables,config,logger:logger2}),reqNotifSvc=new NotificationService({db,schemaTables:ctx.schemaTables,config:routeConfig.notificationConfig||{enabled:!1},logger:logger2,emailService:routeConfig.emailService});return wireNotificationHandler(reqVerSvc,reqNotifSvc),{verificationService:reqVerSvc,notificationService:reqNotifSvc}},basePath=config.endpoints?.basePath||"/verifications",flowBasePath=config.flowEndpoints?.basePath||"/verification-flows",notifBasePath=routeConfig.notificationConfig?.endpoints?.basePath||"/notifications",routes=new Elysia11,verificationRoutes=new Elysia11({prefix:basePath});if(verificationRoutes.get("/status/:entity_name/:entity_id",async({params,request})=>{let{verificationService}=getServicesForRequest(request);return{success:!0,data:await verificationService.getStatus(params.entity_name,params.entity_id)}},{params:t10.Object({entity_name:t10.String(),entity_id:t10.String()})}),verificationRoutes.post("/:entity_name/:entity_id/decide",async({params,body,request})=>{let{verificationService}=getServicesForRequest(request),userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required",status:401};return await verificationService.decide({entity_name:params.entity_name,entity_id:params.entity_id,user_id:userId,decision:body.decision,reason:body.reason,signature_id:body.signature_id,diff:body.diff})},{params:t10.Object({entity_name:t10.String(),entity_id:t10.String()}),body:t10.Object({decision:t10.Union([t10.Literal("approved"),t10.Literal("rejected")]),reason:t10.Optional(t10.String()),signature_id:t10.Optional(t10.String()),diff:t10.Optional(t10.Record(t10.String(),t10.Unknown()))})}),verificationRoutes.get("/pending",async({request})=>{let{verificationService}=getServicesForRequest(request),userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required",status:401};return{success:!0,data:await verificationService.getPending(userId)}}),verificationRoutes.get("/history/:entity_name/:entity_id",async({params,request})=>{let{verificationService}=getServicesForRequest(request),status=await verificationService.getStatus(params.entity_name,params.entity_id);return{success:!0,data:{verifications:status.verifications,current_step:status.current_step,total_steps:status.total_steps,is_completed:status.is_completed,is_rejected:status.is_rejected}}},{params:t10.Object({entity_name:t10.String(),entity_id:t10.String()})}),verificationRoutes.post("/start",async({body,request})=>{let{verificationService}=getServicesForRequest(request),userId=request.headers.get("x-user-id");return await verificationService.startFlow({flow_id:body.flow_id,entity_name:body.entity_name,entity_id:body.entity_id,started_by:userId||void 0})},{body:t10.Object({flow_id:t10.String(),entity_name:t10.String(),entity_id:t10.String()})}),verificationRoutes.post("/start-for-entity",async({body,request})=>{let{verificationService}=getServicesForRequest(request),userId=request.headers.get("x-user-id");return await verificationService.startFlowForEntity({entity_name:body.entity_name,entity_id:body.entity_id,started_by:userId||void 0})},{body:t10.Object({entity_name:t10.String(),entity_id:t10.String()})}),verificationRoutes.get("/statuses/:entity_name",async({params,query,request})=>{let{verificationService}=getServicesForRequest(request);return{success:!0,data:await verificationService.listEntityStatuses({entity_name:params.entity_name,status:query.status||void 0,page:query.page?Number(query.page):void 0,limit:query.limit?Number(query.limit):void 0})}},{params:t10.Object({entity_name:t10.String()}),query:t10.Object({status:t10.Optional(t10.String()),page:t10.Optional(t10.String()),limit:t10.Optional(t10.String())})}),routes.use(verificationRoutes),logger2.info(`[Verification] Routes registered at ${basePath}`),config.flowEndpoints?.enabled!==!1){let flowRoutes=new Elysia11({prefix:flowBasePath});flowRoutes.get("/",async({query,request})=>{let{verificationService:vs}=getServicesForRequest(request);return{success:!0,data:await vs.listFlows(query.entity_name||void 0)}},{query:t10.Object({entity_name:t10.Optional(t10.String())})}),flowRoutes.get("/:flow_id",async({params,request})=>{let{verificationService:vs}=getServicesForRequest(request),result=await vs.getFlow(params.flow_id);if(!result)return{success:!1,message:"Flow not found"};return{success:!0,data:result}},{params:t10.Object({flow_id:t10.String()})}),flowRoutes.post("/",async({body,request})=>{let{verificationService:vs}=getServicesForRequest(request);return await vs.saveFlow(body)},{body:t10.Object({flow_id:t10.String(),entity_name:t10.String(),name:t10.String(),description:t10.Optional(t10.String()),trigger_on:t10.Union([t10.Literal("create"),t10.Literal("update"),t10.Literal("delete"),t10.Literal("manual")]),trigger_fields:t10.Optional(t10.Array(t10.String())),is_draft:t10.Boolean(),viewport:t10.Optional(t10.Object({x:t10.Number(),y:t10.Number(),zoom:t10.Number()})),graph:t10.Object({steps:t10.Array(t10.Any()),edges:t10.Array(t10.Any()),verifier_configs:t10.Array(t10.Any()),notification_rules:t10.Array(t10.Any()),notification_recipients:t10.Array(t10.Any()),notification_channels:t10.Array(t10.Any())})})}),flowRoutes.post("/:flow_id/publish",async({params,request})=>{let{verificationService:vs}=getServicesForRequest(request);return await vs.publishFlow(params.flow_id)},{params:t10.Object({flow_id:t10.String()})}),flowRoutes.delete("/:flow_id",async({params,request})=>{let{verificationService:vs}=getServicesForRequest(request);return await vs.deleteFlow(params.flow_id)},{params:t10.Object({flow_id:t10.String()})}),routes.use(flowRoutes),logger2.info(`[Verification] Flow routes registered at ${flowBasePath}`)}if(routeConfig.notificationConfig?.enabled&&routeConfig.notificationConfig?.endpoints?.enabled!==!1){let notifRoutes=new Elysia11({prefix:notifBasePath});notifRoutes.get("/",async({request,query})=>{let userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required"};let{notificationService:ns}=getServicesForRequest(request);return{success:!0,data:await ns.getNotifications(userId,{limit:query.limit?Number(query.limit):void 0,offset:query.offset?Number(query.offset):void 0,type:query.type||void 0})}},{query:t10.Object({limit:t10.Optional(t10.String()),offset:t10.Optional(t10.String()),type:t10.Optional(t10.String())})}),notifRoutes.get("/unseen-count",async({request})=>{let userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required"};let{notificationService:ns}=getServicesForRequest(request);return{success:!0,data:{count:await ns.getUnseenCount(userId)}}}),notifRoutes.post("/:notification_id/seen",async({params,request})=>{let userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required"};let{notificationService:ns}=getServicesForRequest(request),result=await ns.markAsSeen(params.notification_id,userId);return{success:result,message:result?"Marked as seen":"Failed"}},{params:t10.Object({notification_id:t10.String()})}),notifRoutes.post("/seen-all",async({request})=>{let userId=request.headers.get("x-user-id");if(!userId)return{success:!1,message:"User ID required"};let{notificationService:ns}=getServicesForRequest(request);return{success:!0,data:{count:await ns.markAllAsSeen(userId)}}}),routes.use(notifRoutes),logger2.info(`[Notification] Routes registered at ${notifBasePath}`)}return{routes,verificationService:defaultVerificationService,notificationService:defaultNotificationService}}import{Elysia as Elysia12}from"elysia";var a=`/* basic theme */
|