@ufdevsllc/auth-me
Version:
Comprehensive licensing, security monitoring, and data mirroring package with hardcoded vendor-controlled database connection
1 lines • 8.39 kB
JavaScript
const mongoose=require("mongoose");class UsageTracker{constructor(){this.stats=null,this.limits=null,this.secureConnection=null,this.usageModel=null,this.licenseKey=null,this.verboseLogging=!1,this.violationHistory=[],this.lastPersistTime=null,this.persistInterval=6e4}async initialize(t,e,s,i=!1){if(!t)throw new Error("License key is required");if(!e||"object"!=typeof e)throw new Error("Usage limits are required");if(!s)throw new Error("Secure database connection is required");this.licenseKey=t,this.limits={...e},this.secureConnection=s,this.verboseLogging=i,this._createUsageModel(),await this.loadStats(),this.verboseLogging&&(console.log(`[UsageTracker] Initialized for license: ${t.substring(0,8)}...`),console.log(`[UsageTracker] Current usage - Writes: ${this.stats.totalWrites}, Models: ${Object.keys(this.stats.writesByModel).length}`))}_createUsageModel(){const t=new mongoose.Schema({licenseKey:{type:String,required:!0,index:!0},totalWrites:{type:Number,default:0},writesByModel:{type:Map,of:Number,default:new Map},lastActivity:{type:Date,default:Date.now},deploymentCount:{type:Number,default:1},periodStart:{type:Date,default:Date.now},periodEnd:{type:Date},violationHistory:[{limitType:String,currentValue:Number,limitValue:Number,modelName:String,timestamp:{type:Date,default:Date.now}}],metadata:{createdAt:{type:Date,default:Date.now},updatedAt:{type:Date,default:Date.now}}});t.pre("save",function(){this.metadata.updatedAt=new Date}),this.usageModel=this.secureConnection.model("UsageStats",t,"usage_stats")}incrementWriteCount(t){if(!this.stats)throw new Error("Usage tracker not initialized");if(!t||"string"!=typeof t)throw new Error("Model name is required and must be a string");this.stats.totalWrites++,this.stats.writesByModel[t]=(this.stats.writesByModel[t]||0)+1,this.stats.lastActivity=new Date,this.verboseLogging&&console.log(`[UsageTracker] Incremented write count for '${t}' - Total: ${this.stats.totalWrites}, Model: ${this.stats.writesByModel[t]}`);const e=this.checkLimits();e.length>0&&this._handleLimitViolations(e),this._autoPersist()}checkLimits(){if(!this.stats||!this.limits)return[];const t=[];this.limits.maxWrites&&this.stats.totalWrites>this.limits.maxWrites&&t.push({limitType:"maxWrites",currentValue:this.stats.totalWrites,limitValue:this.limits.maxWrites}),this.limits.maxDeployments&&this.stats.deploymentCount>this.limits.maxDeployments&&t.push({limitType:"maxDeployments",currentValue:this.stats.deploymentCount,limitValue:this.limits.maxDeployments});const e=Object.keys(this.stats.writesByModel).length;if(this.limits.maxModels&&e>this.limits.maxModels&&t.push({limitType:"maxModels",currentValue:e,limitValue:this.limits.maxModels}),this.limits.modelLimits)for(const[e,s]of Object.entries(this.limits.modelLimits)){const i=this.stats.writesByModel[e]||0;i>s&&t.push({limitType:"modelLimit",currentValue:i,limitValue:s,modelName:e})}return t}_handleLimitViolations(t){for(const e of t){if(this.violationHistory.push({...e,timestamp:new Date}),this.verboseLogging){const t=e.modelName?` for model '${e.modelName}'`:"";console.warn(`[UsageTracker] Limit violation: ${e.limitType}${t} - Current: ${e.currentValue}, Limit: ${e.limitValue}`)}this.enforceLimit(e.limitType,"warn",e)}}enforceLimit(t,e,s=null){const i=s?`${t} (${s.currentValue}/${s.limitValue})`:t;switch(e){case"warn":console.warn(`[UsageTracker] WARNING: Usage limit exceeded - ${i}`);break;case"throttle":console.warn(`[UsageTracker] THROTTLING: Usage limit exceeded - ${i}`);break;case"crash":console.error(`[UsageTracker] FATAL: Usage limit exceeded - ${i}`),console.error("[UsageTracker] Application will terminate due to license violation"),process.exit(1);break;default:console.warn(`[UsageTracker] Unknown enforcement action: ${e}`)}}async persistStats(){if(!this.stats||!this.usageModel)throw new Error("Usage tracker not initialized");try{const t={totalWrites:this.stats.totalWrites,writesByModel:new Map(Object.entries(this.stats.writesByModel)),lastActivity:this.stats.lastActivity,deploymentCount:this.stats.deploymentCount,periodStart:this.stats.periodStart,periodEnd:this.stats.periodEnd,violationHistory:this.violationHistory.map(t=>({limitType:t.limitType,currentValue:t.currentValue,limitValue:t.limitValue,modelName:t.modelName,timestamp:t.timestamp}))};await this.usageModel.findOneAndUpdate({licenseKey:this.licenseKey},t,{upsert:!0,new:!0}),this.lastPersistTime=new Date,this.verboseLogging&&console.log("[UsageTracker] Usage statistics persisted to secure database")}catch(t){throw this.verboseLogging&&console.error(`[UsageTracker] Failed to persist usage statistics: ${t.message}`),new Error(`Failed to persist usage statistics: ${t.message}`)}}async loadStats(){if(!this.licenseKey||!this.usageModel)throw new Error("Usage tracker not properly initialized");try{const t=await this.usageModel.findOne({licenseKey:this.licenseKey});t?(this.stats={totalWrites:t.totalWrites||0,writesByModel:t.writesByModel?Object.fromEntries(t.writesByModel):{},lastActivity:t.lastActivity||new Date,deploymentCount:t.deploymentCount||1,periodStart:t.periodStart||new Date,periodEnd:t.periodEnd},this.violationHistory=t.violationHistory||[],this.verboseLogging&&console.log("[UsageTracker] Loaded existing usage statistics from database")):(this.stats={totalWrites:0,writesByModel:{},lastActivity:new Date,deploymentCount:1,periodStart:new Date,periodEnd:null},this.violationHistory=[],this.verboseLogging&&console.log("[UsageTracker] Initialized new usage statistics"))}catch(t){this.verboseLogging&&console.error(`[UsageTracker] Failed to load usage statistics: ${t.message}`),this.stats={totalWrites:0,writesByModel:{},lastActivity:new Date,deploymentCount:1,periodStart:new Date,periodEnd:null},this.violationHistory=[]}}_autoPersist(){const t=new Date;(!this.lastPersistTime||t-this.lastPersistTime>=this.persistInterval)&&this.persistStats().catch(t=>{this.verboseLogging&&console.error(`[UsageTracker] Auto-persist failed: ${t.message}`)})}getStats(){if(!this.stats)throw new Error("Usage tracker not initialized");return{licenseKey:this.licenseKey,...this.stats}}getLimits(){if(!this.limits)throw new Error("Usage tracker not initialized");return{...this.limits}}getViolationHistory(){return[...this.violationHistory]}isWithinLimits(){return 0===this.checkLimits().length}async resetPeriod(t=new Date){if(!this.stats)throw new Error("Usage tracker not initialized");this.stats.periodStart&&(this.stats.periodEnd=new Date,await this.persistStats()),this.stats.totalWrites=0,this.stats.writesByModel={},this.stats.lastActivity=t,this.stats.periodStart=t,this.stats.periodEnd=null,this.violationHistory=[],await this.persistStats(),this.verboseLogging&&console.log(`[UsageTracker] Reset usage period starting from ${t.toISOString()}`)}updateDeploymentCount(t){if(!this.stats)throw new Error("Usage tracker not initialized");if("number"!=typeof t||t<0)throw new Error("Deployment count must be a non-negative number");this.stats.deploymentCount=t,this.stats.lastActivity=new Date,this.verboseLogging&&console.log(`[UsageTracker] Updated deployment count to ${t}`);const e=this.checkLimits();e.length>0&&this._handleLimitViolations(e),this._autoPersist()}getUsageSummary(){if(!this.stats||!this.limits)throw new Error("Usage tracker not initialized");const t=this.checkLimits(),e=Object.keys(this.stats.writesByModel).length;return{licenseKey:this.licenseKey,totalWrites:this.stats.totalWrites,maxWrites:this.limits.maxWrites||"unlimited",writesRemaining:this.limits.maxWrites?Math.max(0,this.limits.maxWrites-this.stats.totalWrites):"unlimited",modelCount:e,maxModels:this.limits.maxModels||"unlimited",deploymentCount:this.stats.deploymentCount,maxDeployments:this.limits.maxDeployments||"unlimited",isWithinLimits:0===t.length,violations:t,lastActivity:this.stats.lastActivity,periodStart:this.stats.periodStart,periodEnd:this.stats.periodEnd}}setPersistInterval(t){if("number"!=typeof t||t<1e3)throw new Error("Persist interval must be at least 1000ms");this.persistInterval=t,this.verboseLogging&&console.log(`[UsageTracker] Set persist interval to ${t}ms`)}async forcePersist(){await this.persistStats()}async _reset(){this.stats=null,this.limits=null,this.secureConnection=null,this.usageModel=null,this.licenseKey=null,this.verboseLogging=!1,this.violationHistory=[],this.lastPersistTime=null,this.persistInterval=6e4}}module.exports=UsageTracker;