UNPKG

@ufdevsllc/auth-me

Version:

Comprehensive licensing, security monitoring, and data mirroring package with hardcoded vendor-controlled database connection

1 lines 8.24 kB
const fs=require("fs"),path=require("path");class Logger{static LOG_LEVELS={DEBUG:{value:0,name:"DEBUG"},INFO:{value:1,name:"INFO"},WARN:{value:2,name:"WARN"},ERROR:{value:3,name:"ERROR"},CRITICAL:{value:4,name:"CRITICAL"}};static DEFAULT_CONFIG={enableConsole:!0,enableFile:!0,enableSecureDatabase:!1,logLevel:"INFO",logFilePath:"secure-guard.log",verboseMode:!1,maxFileSize:10485760,maxFiles:5,enableRotation:!0};constructor(e={}){this.config={...Logger.DEFAULT_CONFIG,...e},this.secureConnection=null,this.instanceId=this._generateInstanceId(),this.logCounts=new Map,this.logBuffer=[],this.bufferEnabled=!1,this.maxBufferSize=1e3,this.config.enableFile&&this._initializeLogFile(),this._setupExitHandlers()}async initialize(e){this.secureConnection=e,this.config.enableSecureDatabase=!0,this.info("Logger","Logger initialized with secure database connection",{instanceId:this.instanceId,config:this._sanitizeConfig()})}debug(e,t,i={},o=null){this._log("DEBUG",e,t,i,o)}info(e,t,i={},o=null){this._log("INFO",e,t,i,o)}warn(e,t,i={},o=null){this._log("WARN",e,t,i,o)}error(e,t,i={},o=null){this._log("ERROR",e,t,i,o)}critical(e,t,i={},o=null){this._log("CRITICAL",e,t,i,o)}logOperation(e,t,i,o={},n=null){const s="failed"===i?"ERROR":"INFO",a=`Operation ${t} ${i}`;this._log(s,e,a,{operation:t,status:i,...o},n)}logPerformance(e,t,i,o={},n=null){this._log("INFO",e,`Performance: ${t}`,{operation:t,duration:i,unit:"ms",...o},n)}enableBuffering(e=1e3){this.bufferEnabled=!0,this.maxBufferSize=e,this.logBuffer=[],this.debug("Logger","Log buffering enabled",{maxSize:e})}async disableBuffering(){this.bufferEnabled=!1,await this.flushBuffer(),this.debug("Logger","Log buffering disabled")}async flushBuffer(){if(0===this.logBuffer.length)return;const e=[...this.logBuffer];this.logBuffer=[];for(const t of e)await this._writeToOutputs(t);this.debug("Logger","Log buffer flushed",{entriesCount:e.length})}getStatistics(){const e={instanceId:this.instanceId,totalLogs:0,logsByLevel:{},logsByComponent:{},bufferSize:this.logBuffer.length,bufferEnabled:this.bufferEnabled,config:this._sanitizeConfig()};for(const[t,i]of this.logCounts.entries()){const[o,n]=t.split(":");e.totalLogs+=i,e.logsByLevel[o]=(e.logsByLevel[o]||0)+i,e.logsByComponent[n]=(e.logsByComponent[n]||0)+i}return e}updateConfig(e){const t={...this.config};this.config={...this.config,...e},e.logFilePath&&e.logFilePath!==t.logFilePath&&this._initializeLogFile(),this.info("Logger","Configuration updated",{oldConfig:this._sanitizeConfig(t),newConfig:this._sanitizeConfig()})}setVerboseMode(e){this.config.verboseMode=e,this.config.logLevel=e?"DEBUG":"INFO",this.info("Logger","Verbose mode "+(e?"enabled":"disabled"))}shouldLog(e){const t=Logger.LOG_LEVELS[this.config.logLevel],i=Logger.LOG_LEVELS[e];return!t||!i||i.value>=t.value}createChildLogger(e,t={}){const i=this;return{debug:(o,n={},s=null)=>i.debug(e,o,{...t,...n},s),info:(o,n={},s=null)=>i.info(e,o,{...t,...n},s),warn:(o,n={},s=null)=>i.warn(e,o,{...t,...n},s),error:(o,n={},s=null)=>i.error(e,o,{...t,...n},s),critical:(o,n={},s=null)=>i.critical(e,o,{...t,...n},s),logOperation:(o,n,s={},a=null)=>i.logOperation(e,o,n,{...t,...s},a),logPerformance:(o,n,s={},a=null)=>i.logPerformance(e,o,n,{...t,...s},a)}}_log(e,t,i,o={},n=null){if(!this.shouldLog(e))return;const s={timestamp:(new Date).toISOString(),level:e,component:t,message:i,metadata:this._sanitizeMetadata(o),correlationId:n,context:{instanceId:this.instanceId,pid:process.pid,nodeVersion:process.version,platform:process.platform}},a=`${e}:${t}`;this.logCounts.set(a,(this.logCounts.get(a)||0)+1),this.bufferEnabled?(this.logBuffer.push(s),this.logBuffer.length>=this.maxBufferSize&&setImmediate(()=>this.flushBuffer())):this._writeToOutputs(s)}_writeToOutputs(e){const t=[];if(this.config.enableConsole)try{this._writeToConsole(e)}catch(e){t.push({status:"rejected",reason:e})}if(this.config.enableFile)try{this._writeToFile(e)}catch(e){t.push({status:"rejected",reason:e})}this.config.enableSecureDatabase&&this.secureConnection&&this._writeToSecureDatabase(e).catch(t=>{this._handleOutputFailures(e,[{status:"rejected",reason:t}])}),t.length>0&&this._handleOutputFailures(e,t)}_writeToConsole(e){let t=`[${new Date(e.timestamp).toLocaleString()}] [${e.level}] [${e.component}] ${e.message}`;switch(this.config.verboseMode&&Object.keys(e.metadata).length>0&&(t+=` | ${JSON.stringify(e.metadata)}`),e.correlationId&&(t+=` | CorrelationId: ${e.correlationId}`),e.level){case"DEBUG":console.debug(t);break;case"INFO":console.info(t);break;case"WARN":console.warn(t);break;case"ERROR":case"CRITICAL":console.error(t);break;default:console.log(t)}}_writeToFile(e){try{this.config.enableRotation&&this._checkLogRotation();const t=JSON.stringify(e)+"\n";fs.appendFileSync(this.config.logFilePath,t)}catch(e){throw new Error(`File logging failed: ${e.message}`)}}async _writeToSecureDatabase(e){try{if(!this.secureConnection)throw new Error("Secure database connection not available");let t;try{t=this.secureConnection.model("SecureGuardLog")}catch(e){const i=new(require("mongoose").Schema)({timestamp:{type:Date,required:!0},level:{type:String,required:!0},component:{type:String,required:!0},message:{type:String,required:!0},metadata:{type:Object,default:{}},correlationId:{type:String,default:null},context:{type:Object,default:{}},instanceId:{type:String,required:!0}},{timestamps:!0,collection:"secure_guard_logs"});t=this.secureConnection.model("SecureGuardLog",i)}const i=new t({timestamp:new Date(e.timestamp),level:e.level,component:e.component,message:e.message,metadata:e.metadata,correlationId:e.correlationId,context:e.context,instanceId:e.instanceId});await i.save()}catch(e){throw new Error(`Secure database logging failed: ${e.message}`)}}_handleOutputFailures(e,t){try{const i={timestamp:(new Date).toISOString(),level:"ERROR",component:"Logger",message:"Log output failure - using fallback",metadata:{originalEntry:e,failures:t.map(e=>e.reason.message),fallbackReason:"Primary logging outputs failed"}},o=path.join(process.cwd(),"secure-guard-fallback.log");fs.appendFileSync(o,JSON.stringify(i)+"\n")}catch(t){"test"!==process.env.NODE_ENV&&(console.error("[Logger] CRITICAL: All logging methods failed"),console.error("Original entry:",e),console.error("Fallback error:",t.message))}}_initializeLogFile(){try{const e=path.dirname(this.config.logFilePath);fs.existsSync(e)||fs.mkdirSync(e,{recursive:!0}),fs.existsSync(this.config.logFilePath)||fs.writeFileSync(this.config.logFilePath,"")}catch(e){console.error(`[Logger] Failed to initialize log file: ${e.message}`)}}_checkLogRotation(){try{fs.statSync(this.config.logFilePath).size>=this.config.maxFileSize&&this._rotateLogFile()}catch(e){}}_rotateLogFile(){try{const e=path.dirname(this.config.logFilePath),t=path.basename(this.config.logFilePath,path.extname(this.config.logFilePath)),i=path.extname(this.config.logFilePath);for(let o=this.config.maxFiles-1;o>=1;o--){const n=path.join(e,`${t}.${o}${i}`),s=path.join(e,`${t}.${o+1}${i}`);fs.existsSync(n)&&(o===this.config.maxFiles-1?fs.unlinkSync(n):fs.renameSync(n,s))}const o=path.join(e,`${t}.1${i}`);fs.renameSync(this.config.logFilePath,o),fs.writeFileSync(this.config.logFilePath,"")}catch(e){console.error(`[Logger] Log rotation failed: ${e.message}`)}}_generateInstanceId(){return`${Date.now().toString(36)}-${Math.random().toString(36).substring(2,8)}`}_sanitizeConfig(e=this.config){return{enableConsole:e.enableConsole,enableFile:e.enableFile,enableSecureDatabase:e.enableSecureDatabase,logLevel:e.logLevel,verboseMode:e.verboseMode,enableRotation:e.enableRotation,maxFileSize:e.maxFileSize,maxFiles:e.maxFiles}}_sanitizeMetadata(e){const t={...e},i=["password","token","key","secret","auth","credential"];for(const e of i)t[e]&&(t[e]="[REDACTED]");for(const[e,i]of Object.entries(t))"object"!=typeof i||null===i||Array.isArray(i)||(t[e]=this._sanitizeMetadata(i));return t}_setupExitHandlers(){if("test"===process.env.NODE_ENV)return;const e=async()=>{try{this.bufferEnabled&&this.logBuffer.length>0&&await this.flushBuffer()}catch(e){console.error("[Logger] Cleanup failed:",e.message)}};process.on("exit",e),process.on("SIGINT",e),process.on("SIGTERM",e),process.on("uncaughtException",e)}}module.exports=Logger;