@nitrogenbuilder/client-php
Version:
Nitrogen Builder PHP Client
117 lines (94 loc) • 2.78 kB
text/typescript
type LogLevel = 'log' | 'warn' | 'error';
interface LogOptions {
context?: Record<string, any>;
prefix?: string;
}
class Logger {
private isDevelopment: boolean;
constructor() {
this.isDevelopment =
typeof process === 'undefined' ||
process?.env?.NODE_ENV === 'development' ||
process?.env?.NODE_ENV === 'nitrogen';
}
private getCallerInfo(): string | null {
try {
const stack = new Error().stack;
if (!stack) return null;
// Parse stack trace to find the actual caller (skip logger internals)
const lines = stack.split('\n');
// Skip: Error, getCallerInfo, formatMessage, log/warn/error method, actual caller
const callerLine = lines[5];
if (!callerLine) return null;
// Extract file:line:column from stack trace
// Browser format: " at functionName (file:line:column)"
const match =
callerLine.match(/\((.+):(\d+):(\d+)\)/) ||
callerLine.match(/at (.+):(\d+):(\d+)/);
if (!match) return null;
const [, file, line, column] = match;
// Get just the filename from the full path
const filename = file.split('/').pop()?.split('?')[0] || file;
return `${filename}:${line}:${column}`;
} catch {
return null;
}
}
private formatMessage(
level: LogLevel,
message: string,
options?: LogOptions
): void {
const prefix = options?.prefix || 'NitrogenClient';
const caller = this.getCallerInfo();
// Color schemes for different log levels
const colors = {
log: '#00bcd4', // Cyan
warn: '#ff9800', // Orange
error: '#f44336', // Red
};
const prefixStyle = `
color: white;
background-color: ${colors[level]};
border-radius: 4px;
padding: 2px 6px;
font-weight: bold;
`;
const callerStyle = `
color: #888;
font-size: 0.9em;
`;
if (this.isDevelopment) {
// Development: Show prefix, caller, and message inline
const callerInfo = caller ? `%c ${caller}` : '';
const styles = caller ? [prefixStyle, callerStyle] : [prefixStyle];
console[level](
`%c[${prefix}]${callerInfo} ${message}`,
...styles,
options?.context || ''
);
} else {
// Production: Collapsed group with context
console.groupCollapsed(`%c[${prefix}] ${message}`, prefixStyle);
if (caller) {
console.log(`Location: ${caller}`);
}
if (options?.context) {
console[level]('Context:', options.context);
} else {
console[level](message);
}
console.groupEnd();
}
}
log(message: string, options?: LogOptions): void {
this.formatMessage('log', message, options);
}
warn(message: string, options?: LogOptions): void {
this.formatMessage('warn', message, options);
}
error(message: string, options?: LogOptions): void {
this.formatMessage('error', message, options);
}
}
export const logger = new Logger();