| 
					
				 | 
			
			
				@@ -0,0 +1,155 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export type Log = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	timestamp: number; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	message: string; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	type?: "info" | "success" | "error" | "debug"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	category?: string; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	data?: Record<string, any>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export default class LogBook { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private logs: Log[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private filter: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		include: Partial<Omit<Log, "timestamp">>[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		exclude: Partial<Omit<Log, "timestamp">>[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		silence: Partial<Omit<Log, "timestamp">>[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private display: Record< 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		"timestamp" | "title" | "type" | "message" | "data", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		boolean 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Log Book 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public constructor() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.logs = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.filter = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			include: [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			exclude: [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			silence: [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					category: "jobs" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this.display = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			timestamp: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			title: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			type: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			message: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			data: false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * log - Add log 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param log - Log message or object 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public log(log: string | Omit<Log, "timestamp">) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		const logObject: Log = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			timestamp: Date.now(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			...(typeof log === "string" ? { message: log } : log) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		let exclude = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		let silence = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Object.entries(logObject).forEach(([key, value]) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				(this.filter.include.length > 0 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// @ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.filter.include.filter(filter => filter[key] === value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.length === 0) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// @ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.filter.exclude.filter(filter => filter[key] === value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					.length > 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				exclude = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// @ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.filter.silence.filter(filter => filter[key] === value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					.length > 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				silence = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!exclude) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.logs.push(logObject); // TODO: Replace with file storage 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (!silence) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.printMessage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					logObject, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					(logObject.data && logObject.data.jobName) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						logObject.category || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						undefined 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * printMessage - Output formatted log to stdout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param log - Log 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param title - Log title 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	private printMessage(log: Log, title?: string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		const centerString = (string: string, length: number) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			const spaces = Array( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Math.floor((length - Math.max(0, string.length)) / 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			).join(" "); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return `| ${spaces}${string}${spaces}${ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				string.length % 2 === 0 ? "" : " " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} `; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		let message = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch (log.type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case "success": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				message += "\x1b[32m"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case "error": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				message += "\x1b[31m"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case "debug": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				message += "\x1b[33m"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case "info": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				message += "\x1b[36m"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (this.display.timestamp) message += `| ${log.timestamp} `; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (this.display.title) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			message += centerString(title ? title.substring(0, 20) : "", 24); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (this.display.type) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			message += centerString( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				log.type ? log.type.toUpperCase() : "INFO", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				10 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (this.display.message) message += `| ${log.message} `; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (this.display.data) message += `| ${JSON.stringify(log.data)} `; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		message += "\x1b[0m"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		console.log(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * setFilter - Apply filters for current session 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param filter - Filter type 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param action - Action 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param filters - Filters 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public setFilter<T extends keyof LogBook["filter"]>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		filter: T, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		action: "set" | "add" | "reset", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		filters?: LogBook["filter"][T] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (action === "reset") this.filter[filter] = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (action === "set" || action === "add") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (!filters || filters.length === 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				throw new Error("No filters provided"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (action === "set") this.filter[filter] = filters; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (action === "add") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.filter[filter] = [...this.filter[filter], ...filters]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |