diff --git a/packages/utils/src/logging.d.ts b/packages/utils/src/logging.d.ts new file mode 100644 index 0000000..0738078 --- /dev/null +++ b/packages/utils/src/logging.d.ts @@ -0,0 +1,47 @@ +/** + * Structured logging utilities + * Provides JSON logging with correlation IDs and log levels + */ +export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal'; +export interface LogEntry { + timestamp: string; + level: LogLevel; + message: string; + correlationId?: string; + transactionId?: string; + userId?: string; + context?: Record; + error?: { + name: string; + message: string; + stack?: string; + }; +} +declare class Logger { + private correlationId; + private minLevel; + private levels; + setCorrelationId(id: string): void; + clearCorrelationId(): void; + setMinLevel(level: LogLevel): void; + private shouldLog; + private log; + debug(message: string, context?: Record): void; + info(message: string, context?: Record): void; + warn(message: string, context?: Record): void; + error(message: string, error?: Error, context?: Record): void; + fatal(message: string, error?: Error, context?: Record): void; + logTransaction(transactionId: string, action: string, level?: LogLevel, context?: Record): void; + logAudit(action: string, userId?: string, context?: Record): void; +} +export declare function getLogger(): Logger; +/** + * Generate correlation ID + */ +export declare function generateCorrelationId(): string; +/** + * Create a scoped logger with correlation ID + */ +export declare function createScopedLogger(correlationId: string): Logger; +export {}; +//# sourceMappingURL=logging.d.ts.map \ No newline at end of file diff --git a/packages/utils/src/logging.d.ts.map b/packages/utils/src/logging.d.ts.map new file mode 100644 index 0000000..b282742 --- /dev/null +++ b/packages/utils/src/logging.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["logging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,cAAM,MAAM;IACV,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAA2G;IAE3H,OAAO,CAAC,MAAM,CAMZ;IAEF,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIlC,kBAAkB,IAAI,IAAI;IAI1B,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAIlC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;IAqCX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9E,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK9E,cAAc,CACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,QAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI;IAKP,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI;CAGR;AAKD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAIhE"} \ No newline at end of file diff --git a/packages/utils/src/logging.js b/packages/utils/src/logging.js new file mode 100644 index 0000000..24a9f86 --- /dev/null +++ b/packages/utils/src/logging.js @@ -0,0 +1,100 @@ +/** + * Structured logging utilities + * Provides JSON logging with correlation IDs and log levels + */ +class Logger { + correlationId = null; + minLevel = (typeof process !== 'undefined' ? process.env?.LOG_LEVEL : undefined) || 'info'; + levels = { + debug: 0, + info: 1, + warn: 2, + error: 3, + fatal: 4, + }; + setCorrelationId(id) { + this.correlationId = id; + } + clearCorrelationId() { + this.correlationId = null; + } + setMinLevel(level) { + this.minLevel = level; + } + shouldLog(level) { + return this.levels[level] >= this.levels[this.minLevel]; + } + log(level, message, context, error) { + if (!this.shouldLog(level)) { + return; + } + const entry = { + timestamp: new Date().toISOString(), + level, + message, + correlationId: this.correlationId || undefined, + context, + }; + if (error) { + entry.error = { + name: error.name, + message: error.message, + stack: error.stack, + }; + } + // In production, this would send to a log aggregation service + // For now, output as JSON to console + if (level === 'error' || level === 'fatal') { + console.error(JSON.stringify(entry)); + } + else if (level === 'warn') { + console.warn(JSON.stringify(entry)); + } + else { + console.log(JSON.stringify(entry)); + } + } + debug(message, context) { + this.log('debug', message, context); + } + info(message, context) { + this.log('info', message, context); + } + warn(message, context) { + this.log('warn', message, context); + } + error(message, error, context) { + this.log('error', message, context, error); + } + fatal(message, error, context) { + this.log('fatal', message, context, error); + } + // Transaction-specific logging + logTransaction(transactionId, action, level = 'info', context) { + this.log(level, `Transaction ${action}`, { ...context, transactionId }); + } + // Audit logging + logAudit(action, userId, context) { + this.log('info', `Audit: ${action}`, { ...context, userId }); + } +} +// Singleton instance +const logger = new Logger(); +export function getLogger() { + return logger; +} +/** + * Generate correlation ID + */ +export function generateCorrelationId() { + return `corr-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; +} +/** + * Create a scoped logger with correlation ID + */ +export function createScopedLogger(correlationId) { + const scopedLogger = new Logger(); + scopedLogger.setCorrelationId(correlationId); + return scopedLogger; +} +//# sourceMappingURL=logging.js.map \ No newline at end of file diff --git a/packages/utils/src/logging.js.map b/packages/utils/src/logging.js.map new file mode 100644 index 0000000..b92bbd6 --- /dev/null +++ b/packages/utils/src/logging.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logging.js","sourceRoot":"","sources":["logging.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/utils/src/logging.ts b/packages/utils/src/logging.ts new file mode 100644 index 0000000..2fd23b0 --- /dev/null +++ b/packages/utils/src/logging.ts @@ -0,0 +1,149 @@ +/** + * Structured logging utilities + * Provides JSON logging with correlation IDs and log levels + */ + +export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal'; + +export interface LogEntry { + timestamp: string; + level: LogLevel; + message: string; + correlationId?: string; + transactionId?: string; + userId?: string; + context?: Record; + error?: { + name: string; + message: string; + stack?: string; + }; +} + +class Logger { + private correlationId: string | null = null; + private minLevel: LogLevel = (typeof process !== 'undefined' ? (process.env?.LOG_LEVEL as LogLevel) : undefined) || 'info'; + + private levels: Record = { + debug: 0, + info: 1, + warn: 2, + error: 3, + fatal: 4, + }; + + setCorrelationId(id: string): void { + this.correlationId = id; + } + + clearCorrelationId(): void { + this.correlationId = null; + } + + setMinLevel(level: LogLevel): void { + this.minLevel = level; + } + + private shouldLog(level: LogLevel): boolean { + return this.levels[level] >= this.levels[this.minLevel]; + } + + private log( + level: LogLevel, + message: string, + context?: Record, + error?: Error + ): void { + if (!this.shouldLog(level)) { + return; + } + + const entry: LogEntry = { + timestamp: new Date().toISOString(), + level, + message, + correlationId: this.correlationId || undefined, + context, + }; + + if (error) { + entry.error = { + name: error.name, + message: error.message, + stack: error.stack, + }; + } + + // In production, this would send to a log aggregation service + // For now, output as JSON to console + if (level === 'error' || level === 'fatal') { + console.error(JSON.stringify(entry)); + } else if (level === 'warn') { + console.warn(JSON.stringify(entry)); + } else { + console.log(JSON.stringify(entry)); + } + } + + debug(message: string, context?: Record): void { + this.log('debug', message, context); + } + + info(message: string, context?: Record): void { + this.log('info', message, context); + } + + warn(message: string, context?: Record): void { + this.log('warn', message, context); + } + + error(message: string, error?: Error, context?: Record): void { + this.log('error', message, context, error); + } + + fatal(message: string, error?: Error, context?: Record): void { + this.log('fatal', message, context, error); + } + + // Transaction-specific logging + logTransaction( + transactionId: string, + action: string, + level: LogLevel = 'info', + context?: Record + ): void { + this.log(level, `Transaction ${action}`, { ...context, transactionId }); + } + + // Audit logging + logAudit( + action: string, + userId?: string, + context?: Record + ): void { + this.log('info', `Audit: ${action}`, { ...context, userId }); + } +} + +// Singleton instance +const logger = new Logger(); + +export function getLogger(): Logger { + return logger; +} + +/** + * Generate correlation ID + */ +export function generateCorrelationId(): string { + return `corr-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; +} + +/** + * Create a scoped logger with correlation ID + */ +export function createScopedLogger(correlationId: string): Logger { + const scopedLogger = new Logger(); + scopedLogger.setCorrelationId(correlationId); + return scopedLogger; +} diff --git a/packages/utils/src/version.d.ts b/packages/utils/src/version.d.ts new file mode 100644 index 0000000..00fa278 --- /dev/null +++ b/packages/utils/src/version.d.ts @@ -0,0 +1,33 @@ +/** + * Version management utilities + * Centralizes version information + */ +export interface VersionInfo { + version: string; + name: string; + buildDate: Date; + gitCommit?: string; + gitBranch?: string; +} +/** + * Get version information + */ +export declare function getVersion(): VersionInfo; +/** + * Get version string + */ +export declare function getVersionString(): string; +/** + * Compare two version strings + * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2 + */ +export declare function compareVersions(v1: string, v2: string): number; +/** + * Check if version is compatible + */ +export declare function isVersionCompatible(version: string, minVersion: string, maxVersion?: string): boolean; +/** + * Format version for display + */ +export declare function formatVersion(version: VersionInfo): string; +//# sourceMappingURL=version.d.ts.map \ No newline at end of file diff --git a/packages/utils/src/version.d.ts.map b/packages/utils/src/version.d.ts.map new file mode 100644 index 0000000..1476958 --- /dev/null +++ b/packages/utils/src/version.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;GAEG;AACH,wBAAgB,UAAU,IAAI,WAAW,CAcxC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAc9D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAUrG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAY1D"} \ No newline at end of file diff --git a/packages/utils/src/version.js b/packages/utils/src/version.js new file mode 100644 index 0000000..ac521a6 --- /dev/null +++ b/packages/utils/src/version.js @@ -0,0 +1,76 @@ +/** + * Version management utilities + * Centralizes version information + */ +// Note: In a real implementation, this would read from package.json +// For now, we'll use a hardcoded version to avoid build issues +const PACKAGE_VERSION = '1.0.0'; +const PACKAGE_NAME = '@brazil-swift-ops/utils'; +let cachedVersion = null; +/** + * Get version information + */ +export function getVersion() { + if (cachedVersion) { + return cachedVersion; + } + cachedVersion = { + version: PACKAGE_VERSION, + name: PACKAGE_NAME, + buildDate: new Date(), + gitCommit: typeof process !== 'undefined' ? (process.env?.GIT_COMMIT || process.env?.VERCEL_GIT_COMMIT_SHA) : undefined, + gitBranch: typeof process !== 'undefined' ? (process.env?.GIT_BRANCH || process.env?.VERCEL_GIT_COMMIT_REF) : undefined, + }; + return cachedVersion; +} +/** + * Get version string + */ +export function getVersionString() { + const v = getVersion(); + return `${v.name} v${v.version}`; +} +/** + * Compare two version strings + * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2 + */ +export function compareVersions(v1, v2) { + const parts1 = v1.split('.').map(Number); + const parts2 = v2.split('.').map(Number); + const maxLength = Math.max(parts1.length, parts2.length); + for (let i = 0; i < maxLength; i++) { + const part1 = parts1[i] || 0; + const part2 = parts2[i] || 0; + if (part1 < part2) + return -1; + if (part1 > part2) + return 1; + } + return 0; +} +/** + * Check if version is compatible + */ +export function isVersionCompatible(version, minVersion, maxVersion) { + if (compareVersions(version, minVersion) < 0) { + return false; + } + if (maxVersion && compareVersions(version, maxVersion) > 0) { + return false; + } + return true; +} +/** + * Format version for display + */ +export function formatVersion(version) { + const parts = [`v${version.version}`]; + if (version.gitCommit) { + parts.push(`(${version.gitCommit.substring(0, 7)})`); + } + if (version.gitBranch) { + parts.push(`[${version.gitBranch}]`); + } + return parts.join(' '); +} +//# sourceMappingURL=version.js.map \ No newline at end of file diff --git a/packages/utils/src/version.js.map b/packages/utils/src/version.js.map new file mode 100644 index 0000000..b4668e3 --- /dev/null +++ b/packages/utils/src/version.js.map @@ -0,0 +1 @@ +{"version":3,"file":"version.js","sourceRoot":"","sources":["version.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/utils/src/version.ts b/packages/utils/src/version.ts new file mode 100644 index 0000000..7775de2 --- /dev/null +++ b/packages/utils/src/version.ts @@ -0,0 +1,98 @@ +/** + * Version management utilities + * Centralizes version information + */ + +// Note: In a real implementation, this would read from package.json +// For now, we'll use a hardcoded version to avoid build issues +const PACKAGE_VERSION = '1.0.0'; +const PACKAGE_NAME = '@brazil-swift-ops/utils'; + +export interface VersionInfo { + version: string; + name: string; + buildDate: Date; + gitCommit?: string; + gitBranch?: string; +} + +let cachedVersion: VersionInfo | null = null; + +/** + * Get version information + */ +export function getVersion(): VersionInfo { + if (cachedVersion) { + return cachedVersion; + } + + cachedVersion = { + version: PACKAGE_VERSION, + name: PACKAGE_NAME, + buildDate: new Date(), + gitCommit: typeof process !== 'undefined' ? (process.env?.GIT_COMMIT || process.env?.VERCEL_GIT_COMMIT_SHA) : undefined, + gitBranch: typeof process !== 'undefined' ? (process.env?.GIT_BRANCH || process.env?.VERCEL_GIT_COMMIT_REF) : undefined, + }; + + return cachedVersion; +} + +/** + * Get version string + */ +export function getVersionString(): string { + const v = getVersion(); + return `${v.name} v${v.version}`; +} + +/** + * Compare two version strings + * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2 + */ +export function compareVersions(v1: string, v2: string): number { + const parts1 = v1.split('.').map(Number); + const parts2 = v2.split('.').map(Number); + const maxLength = Math.max(parts1.length, parts2.length); + + for (let i = 0; i < maxLength; i++) { + const part1 = parts1[i] || 0; + const part2 = parts2[i] || 0; + + if (part1 < part2) return -1; + if (part1 > part2) return 1; + } + + return 0; +} + +/** + * Check if version is compatible + */ +export function isVersionCompatible(version: string, minVersion: string, maxVersion?: string): boolean { + if (compareVersions(version, minVersion) < 0) { + return false; + } + + if (maxVersion && compareVersions(version, maxVersion) > 0) { + return false; + } + + return true; +} + +/** + * Format version for display + */ +export function formatVersion(version: VersionInfo): string { + const parts: string[] = [`v${version.version}`]; + + if (version.gitCommit) { + parts.push(`(${version.gitCommit.substring(0, 7)})`); + } + + if (version.gitBranch) { + parts.push(`[${version.gitBranch}]`); + } + + return parts.join(' '); +}