@bloomneo/appkit 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +902 -0
  3. package/bin/appkit.js +71 -0
  4. package/bin/commands/generate.js +1050 -0
  5. package/bin/templates/backend/README.md.template +39 -0
  6. package/bin/templates/backend/api.http.template +0 -0
  7. package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
  8. package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
  9. package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
  10. package/bin/templates/backend/package.json.template +34 -0
  11. package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
  12. package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
  13. package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
  14. package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
  15. package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
  16. package/bin/templates/backend/src/api/server.ts.template +188 -0
  17. package/bin/templates/backend/tsconfig.api.json.template +24 -0
  18. package/bin/templates/backend/tsconfig.json.template +40 -0
  19. package/bin/templates/feature/feature.http.template +63 -0
  20. package/bin/templates/feature/feature.route.ts.template +36 -0
  21. package/bin/templates/feature/feature.service.ts.template +81 -0
  22. package/bin/templates/feature/feature.types.ts.template +23 -0
  23. package/bin/templates/feature-db/feature.http.template +63 -0
  24. package/bin/templates/feature-db/feature.model.ts.template +74 -0
  25. package/bin/templates/feature-db/feature.route.ts.template +58 -0
  26. package/bin/templates/feature-db/feature.service.ts.template +231 -0
  27. package/bin/templates/feature-db/feature.types.ts.template +25 -0
  28. package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
  29. package/bin/templates/feature-db/seeding/README.md.template +57 -0
  30. package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
  31. package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
  32. package/bin/templates/feature-user/user.http.template +157 -0
  33. package/bin/templates/feature-user/user.model.ts.template +244 -0
  34. package/bin/templates/feature-user/user.route.ts.template +379 -0
  35. package/bin/templates/feature-user/user.seed.js.template +182 -0
  36. package/bin/templates/feature-user/user.service.ts.template +426 -0
  37. package/bin/templates/feature-user/user.types.ts.template +127 -0
  38. package/dist/auth/auth.d.ts +182 -0
  39. package/dist/auth/auth.d.ts.map +1 -0
  40. package/dist/auth/auth.js +477 -0
  41. package/dist/auth/auth.js.map +1 -0
  42. package/dist/auth/defaults.d.ts +104 -0
  43. package/dist/auth/defaults.d.ts.map +1 -0
  44. package/dist/auth/defaults.js +374 -0
  45. package/dist/auth/defaults.js.map +1 -0
  46. package/dist/auth/index.d.ts +70 -0
  47. package/dist/auth/index.d.ts.map +1 -0
  48. package/dist/auth/index.js +94 -0
  49. package/dist/auth/index.js.map +1 -0
  50. package/dist/cache/cache.d.ts +118 -0
  51. package/dist/cache/cache.d.ts.map +1 -0
  52. package/dist/cache/cache.js +249 -0
  53. package/dist/cache/cache.js.map +1 -0
  54. package/dist/cache/defaults.d.ts +63 -0
  55. package/dist/cache/defaults.d.ts.map +1 -0
  56. package/dist/cache/defaults.js +193 -0
  57. package/dist/cache/defaults.js.map +1 -0
  58. package/dist/cache/index.d.ts +101 -0
  59. package/dist/cache/index.d.ts.map +1 -0
  60. package/dist/cache/index.js +203 -0
  61. package/dist/cache/index.js.map +1 -0
  62. package/dist/cache/strategies/memory.d.ts +138 -0
  63. package/dist/cache/strategies/memory.d.ts.map +1 -0
  64. package/dist/cache/strategies/memory.js +348 -0
  65. package/dist/cache/strategies/memory.js.map +1 -0
  66. package/dist/cache/strategies/redis.d.ts +105 -0
  67. package/dist/cache/strategies/redis.d.ts.map +1 -0
  68. package/dist/cache/strategies/redis.js +318 -0
  69. package/dist/cache/strategies/redis.js.map +1 -0
  70. package/dist/config/config.d.ts +62 -0
  71. package/dist/config/config.d.ts.map +1 -0
  72. package/dist/config/config.js +107 -0
  73. package/dist/config/config.js.map +1 -0
  74. package/dist/config/defaults.d.ts +44 -0
  75. package/dist/config/defaults.d.ts.map +1 -0
  76. package/dist/config/defaults.js +217 -0
  77. package/dist/config/defaults.js.map +1 -0
  78. package/dist/config/index.d.ts +105 -0
  79. package/dist/config/index.d.ts.map +1 -0
  80. package/dist/config/index.js +163 -0
  81. package/dist/config/index.js.map +1 -0
  82. package/dist/database/adapters/mongoose.d.ts +106 -0
  83. package/dist/database/adapters/mongoose.d.ts.map +1 -0
  84. package/dist/database/adapters/mongoose.js +480 -0
  85. package/dist/database/adapters/mongoose.js.map +1 -0
  86. package/dist/database/adapters/prisma.d.ts +106 -0
  87. package/dist/database/adapters/prisma.d.ts.map +1 -0
  88. package/dist/database/adapters/prisma.js +494 -0
  89. package/dist/database/adapters/prisma.js.map +1 -0
  90. package/dist/database/defaults.d.ts +87 -0
  91. package/dist/database/defaults.d.ts.map +1 -0
  92. package/dist/database/defaults.js +271 -0
  93. package/dist/database/defaults.js.map +1 -0
  94. package/dist/database/index.d.ts +137 -0
  95. package/dist/database/index.d.ts.map +1 -0
  96. package/dist/database/index.js +490 -0
  97. package/dist/database/index.js.map +1 -0
  98. package/dist/email/defaults.d.ts +100 -0
  99. package/dist/email/defaults.d.ts.map +1 -0
  100. package/dist/email/defaults.js +400 -0
  101. package/dist/email/defaults.js.map +1 -0
  102. package/dist/email/email.d.ts +139 -0
  103. package/dist/email/email.d.ts.map +1 -0
  104. package/dist/email/email.js +316 -0
  105. package/dist/email/email.js.map +1 -0
  106. package/dist/email/index.d.ts +176 -0
  107. package/dist/email/index.d.ts.map +1 -0
  108. package/dist/email/index.js +251 -0
  109. package/dist/email/index.js.map +1 -0
  110. package/dist/email/strategies/console.d.ts +90 -0
  111. package/dist/email/strategies/console.d.ts.map +1 -0
  112. package/dist/email/strategies/console.js +268 -0
  113. package/dist/email/strategies/console.js.map +1 -0
  114. package/dist/email/strategies/resend.d.ts +84 -0
  115. package/dist/email/strategies/resend.d.ts.map +1 -0
  116. package/dist/email/strategies/resend.js +266 -0
  117. package/dist/email/strategies/resend.js.map +1 -0
  118. package/dist/email/strategies/smtp.d.ts +77 -0
  119. package/dist/email/strategies/smtp.d.ts.map +1 -0
  120. package/dist/email/strategies/smtp.js +286 -0
  121. package/dist/email/strategies/smtp.js.map +1 -0
  122. package/dist/error/defaults.d.ts +40 -0
  123. package/dist/error/defaults.d.ts.map +1 -0
  124. package/dist/error/defaults.js +75 -0
  125. package/dist/error/defaults.js.map +1 -0
  126. package/dist/error/error.d.ts +140 -0
  127. package/dist/error/error.d.ts.map +1 -0
  128. package/dist/error/error.js +200 -0
  129. package/dist/error/error.js.map +1 -0
  130. package/dist/error/index.d.ts +145 -0
  131. package/dist/error/index.d.ts.map +1 -0
  132. package/dist/error/index.js +145 -0
  133. package/dist/error/index.js.map +1 -0
  134. package/dist/event/defaults.d.ts +111 -0
  135. package/dist/event/defaults.d.ts.map +1 -0
  136. package/dist/event/defaults.js +378 -0
  137. package/dist/event/defaults.js.map +1 -0
  138. package/dist/event/event.d.ts +171 -0
  139. package/dist/event/event.d.ts.map +1 -0
  140. package/dist/event/event.js +391 -0
  141. package/dist/event/event.js.map +1 -0
  142. package/dist/event/index.d.ts +173 -0
  143. package/dist/event/index.d.ts.map +1 -0
  144. package/dist/event/index.js +302 -0
  145. package/dist/event/index.js.map +1 -0
  146. package/dist/event/strategies/memory.d.ts +122 -0
  147. package/dist/event/strategies/memory.d.ts.map +1 -0
  148. package/dist/event/strategies/memory.js +331 -0
  149. package/dist/event/strategies/memory.js.map +1 -0
  150. package/dist/event/strategies/redis.d.ts +115 -0
  151. package/dist/event/strategies/redis.d.ts.map +1 -0
  152. package/dist/event/strategies/redis.js +434 -0
  153. package/dist/event/strategies/redis.js.map +1 -0
  154. package/dist/index.d.ts +58 -0
  155. package/dist/index.d.ts.map +1 -0
  156. package/dist/index.js +72 -0
  157. package/dist/index.js.map +1 -0
  158. package/dist/logger/defaults.d.ts +67 -0
  159. package/dist/logger/defaults.d.ts.map +1 -0
  160. package/dist/logger/defaults.js +213 -0
  161. package/dist/logger/defaults.js.map +1 -0
  162. package/dist/logger/index.d.ts +84 -0
  163. package/dist/logger/index.d.ts.map +1 -0
  164. package/dist/logger/index.js +101 -0
  165. package/dist/logger/index.js.map +1 -0
  166. package/dist/logger/logger.d.ts +165 -0
  167. package/dist/logger/logger.d.ts.map +1 -0
  168. package/dist/logger/logger.js +843 -0
  169. package/dist/logger/logger.js.map +1 -0
  170. package/dist/logger/transports/console.d.ts +102 -0
  171. package/dist/logger/transports/console.d.ts.map +1 -0
  172. package/dist/logger/transports/console.js +276 -0
  173. package/dist/logger/transports/console.js.map +1 -0
  174. package/dist/logger/transports/database.d.ts +153 -0
  175. package/dist/logger/transports/database.d.ts.map +1 -0
  176. package/dist/logger/transports/database.js +539 -0
  177. package/dist/logger/transports/database.js.map +1 -0
  178. package/dist/logger/transports/file.d.ts +146 -0
  179. package/dist/logger/transports/file.d.ts.map +1 -0
  180. package/dist/logger/transports/file.js +464 -0
  181. package/dist/logger/transports/file.js.map +1 -0
  182. package/dist/logger/transports/http.d.ts +128 -0
  183. package/dist/logger/transports/http.d.ts.map +1 -0
  184. package/dist/logger/transports/http.js +401 -0
  185. package/dist/logger/transports/http.js.map +1 -0
  186. package/dist/logger/transports/webhook.d.ts +152 -0
  187. package/dist/logger/transports/webhook.d.ts.map +1 -0
  188. package/dist/logger/transports/webhook.js +485 -0
  189. package/dist/logger/transports/webhook.js.map +1 -0
  190. package/dist/queue/defaults.d.ts +66 -0
  191. package/dist/queue/defaults.d.ts.map +1 -0
  192. package/dist/queue/defaults.js +205 -0
  193. package/dist/queue/defaults.js.map +1 -0
  194. package/dist/queue/index.d.ts +124 -0
  195. package/dist/queue/index.d.ts.map +1 -0
  196. package/dist/queue/index.js +116 -0
  197. package/dist/queue/index.js.map +1 -0
  198. package/dist/queue/queue.d.ts +156 -0
  199. package/dist/queue/queue.d.ts.map +1 -0
  200. package/dist/queue/queue.js +387 -0
  201. package/dist/queue/queue.js.map +1 -0
  202. package/dist/queue/transports/database.d.ts +165 -0
  203. package/dist/queue/transports/database.d.ts.map +1 -0
  204. package/dist/queue/transports/database.js +595 -0
  205. package/dist/queue/transports/database.js.map +1 -0
  206. package/dist/queue/transports/memory.d.ts +143 -0
  207. package/dist/queue/transports/memory.d.ts.map +1 -0
  208. package/dist/queue/transports/memory.js +415 -0
  209. package/dist/queue/transports/memory.js.map +1 -0
  210. package/dist/queue/transports/redis.d.ts +203 -0
  211. package/dist/queue/transports/redis.d.ts.map +1 -0
  212. package/dist/queue/transports/redis.js +744 -0
  213. package/dist/queue/transports/redis.js.map +1 -0
  214. package/dist/security/defaults.d.ts +64 -0
  215. package/dist/security/defaults.d.ts.map +1 -0
  216. package/dist/security/defaults.js +159 -0
  217. package/dist/security/defaults.js.map +1 -0
  218. package/dist/security/index.d.ts +110 -0
  219. package/dist/security/index.d.ts.map +1 -0
  220. package/dist/security/index.js +160 -0
  221. package/dist/security/index.js.map +1 -0
  222. package/dist/security/security.d.ts +138 -0
  223. package/dist/security/security.d.ts.map +1 -0
  224. package/dist/security/security.js +419 -0
  225. package/dist/security/security.js.map +1 -0
  226. package/dist/storage/defaults.d.ts +79 -0
  227. package/dist/storage/defaults.d.ts.map +1 -0
  228. package/dist/storage/defaults.js +358 -0
  229. package/dist/storage/defaults.js.map +1 -0
  230. package/dist/storage/index.d.ts +153 -0
  231. package/dist/storage/index.d.ts.map +1 -0
  232. package/dist/storage/index.js +242 -0
  233. package/dist/storage/index.js.map +1 -0
  234. package/dist/storage/storage.d.ts +151 -0
  235. package/dist/storage/storage.d.ts.map +1 -0
  236. package/dist/storage/storage.js +439 -0
  237. package/dist/storage/storage.js.map +1 -0
  238. package/dist/storage/strategies/local.d.ts +117 -0
  239. package/dist/storage/strategies/local.d.ts.map +1 -0
  240. package/dist/storage/strategies/local.js +368 -0
  241. package/dist/storage/strategies/local.js.map +1 -0
  242. package/dist/storage/strategies/r2.d.ts +130 -0
  243. package/dist/storage/strategies/r2.d.ts.map +1 -0
  244. package/dist/storage/strategies/r2.js +470 -0
  245. package/dist/storage/strategies/r2.js.map +1 -0
  246. package/dist/storage/strategies/s3.d.ts +121 -0
  247. package/dist/storage/strategies/s3.d.ts.map +1 -0
  248. package/dist/storage/strategies/s3.js +461 -0
  249. package/dist/storage/strategies/s3.js.map +1 -0
  250. package/dist/util/defaults.d.ts +77 -0
  251. package/dist/util/defaults.d.ts.map +1 -0
  252. package/dist/util/defaults.js +193 -0
  253. package/dist/util/defaults.js.map +1 -0
  254. package/dist/util/index.d.ts +97 -0
  255. package/dist/util/index.d.ts.map +1 -0
  256. package/dist/util/index.js +165 -0
  257. package/dist/util/index.js.map +1 -0
  258. package/dist/util/util.d.ts +145 -0
  259. package/dist/util/util.d.ts.map +1 -0
  260. package/dist/util/util.js +481 -0
  261. package/dist/util/util.js.map +1 -0
  262. package/package.json +234 -0
@@ -0,0 +1,843 @@
1
+ /**
2
+ * Core logger class with visual error display and simplified transport management
3
+ * @module @bloomneo/appkit/logger
4
+ * @file src/logger/logger.ts
5
+ *
6
+ * @llm-rule WHEN: Building logger instances - called via loggerClass.get(), not directly
7
+ * @llm-rule AVOID: Creating LoggerClass directly - always use loggerClass.get() for proper setup
8
+ * @llm-rule NOTE: Enhanced error() method provides automatic visual formatting for better DX
9
+ */
10
+ import { ConsoleTransport } from './transports/console.js';
11
+ import { FileTransport } from './transports/file.js';
12
+ import { DatabaseTransport } from './transports/database.js';
13
+ import { HttpTransport } from './transports/http.js';
14
+ import { WebhookTransport } from './transports/webhook.js';
15
+ import { existsSync } from 'fs';
16
+ import { join } from 'path';
17
+ const LOG_LEVELS = {
18
+ error: 0,
19
+ warn: 1,
20
+ info: 2,
21
+ debug: 3,
22
+ };
23
+ /**
24
+ * Logger class with automatic transport management and enhanced error() method
25
+ */
26
+ export class LoggerClass {
27
+ level;
28
+ levelValue;
29
+ defaultMeta;
30
+ config;
31
+ transports = new Map();
32
+ pendingWrites = [];
33
+ constructor(config) {
34
+ this.config = config;
35
+ this.level = config.level;
36
+ this.levelValue = LOG_LEVELS[this.level];
37
+ this.defaultMeta = {
38
+ service: config.service.name,
39
+ version: config.service.version,
40
+ environment: config.service.environment,
41
+ };
42
+ this.initializeTransports();
43
+ }
44
+ initializeTransports() {
45
+ const { transports } = this.config;
46
+ if (transports.console) {
47
+ this.transports.set('console', new ConsoleTransport(this.config));
48
+ }
49
+ if (transports.file) {
50
+ try {
51
+ this.transports.set('file', new FileTransport(this.config));
52
+ }
53
+ catch (error) {
54
+ console.error('File transport initialization failed:', error.message);
55
+ }
56
+ }
57
+ if (transports.database && this.config.database.url) {
58
+ try {
59
+ this.transports.set('database', new DatabaseTransport(this.config));
60
+ }
61
+ catch (error) {
62
+ console.error('Database transport initialization failed:', error.message);
63
+ }
64
+ }
65
+ if (transports.http && this.config.http.url) {
66
+ try {
67
+ this.transports.set('http', new HttpTransport(this.config));
68
+ }
69
+ catch (error) {
70
+ console.error('HTTP transport initialization failed:', error.message);
71
+ }
72
+ }
73
+ if (transports.webhook && this.config.webhook.url) {
74
+ try {
75
+ this.transports.set('webhook', new WebhookTransport(this.config));
76
+ }
77
+ catch (error) {
78
+ console.error('Webhook transport initialization failed:', error.message);
79
+ }
80
+ }
81
+ if (this.transports.size === 0) {
82
+ console.warn('No transports initialized, falling back to console');
83
+ this.transports.set('console', new ConsoleTransport(this.config));
84
+ }
85
+ }
86
+ /**
87
+ * Log informational message
88
+ * @llm-rule WHEN: Normal application events, user actions, business logic flow
89
+ * @llm-rule AVOID: Sensitive data in meta - passwords, tokens, full card numbers
90
+ */
91
+ info(message, meta = {}) {
92
+ this.log('info', message, meta);
93
+ }
94
+ /**
95
+ * Enhanced error logging with automatic visual formatting
96
+ * @llm-rule WHEN: Exceptions, failures, critical issues requiring attention
97
+ * @llm-rule AVOID: Using for warnings - errors should indicate actual problems
98
+ * @llm-rule NOTE: Automatically provides visual formatting in development with smart diagnostics
99
+ */
100
+ error(message, meta = {}) {
101
+ const enhancedMeta = {
102
+ ...meta,
103
+ _location: this.getCaller()
104
+ };
105
+ // Detect error type and provide visual formatting if appropriate
106
+ if (this.shouldShowVisual()) {
107
+ this.renderVisualError(message, enhancedMeta);
108
+ }
109
+ // Always log structured data for production/debugging
110
+ this.log('error', message, enhancedMeta);
111
+ }
112
+ /**
113
+ * Log warning message
114
+ * @llm-rule WHEN: Potential issues, deprecated usage, performance concerns
115
+ * @llm-rule AVOID: Using for normal recoverable errors - use error() for those
116
+ */
117
+ warn(message, meta = {}) {
118
+ this.log('warn', message, meta);
119
+ }
120
+ /**
121
+ * Log debug message
122
+ * @llm-rule WHEN: Development debugging, detailed flow information
123
+ * @llm-rule AVOID: Production debug spam - automatically filtered in production
124
+ */
125
+ debug(message, meta = {}) {
126
+ this.log('debug', message, meta);
127
+ }
128
+ /**
129
+ * Create child logger with additional context
130
+ * @llm-rule WHEN: Adding component context or request-specific data
131
+ * @llm-rule AVOID: Creating many child loggers - reuse component loggers
132
+ */
133
+ child(bindings) {
134
+ const child = Object.create(this);
135
+ child.defaultMeta = { ...this.defaultMeta, ...bindings };
136
+ return child;
137
+ }
138
+ // ============================================================================
139
+ // VISUAL ERROR FORMATTING METHODS
140
+ // ============================================================================
141
+ shouldShowVisual() {
142
+ // Show visual output in development or when explicitly enabled
143
+ return this.config.service.environment === 'development' ||
144
+ this.config.minimal === false ||
145
+ process.env.VOILA_VISUAL_ERRORS === 'true';
146
+ }
147
+ renderVisualError(message, meta) {
148
+ const errorType = this.detectErrorType(message, meta);
149
+ const title = this.getErrorTitle(errorType);
150
+ const diagnostics = this.generateDiagnostics(message, meta, errorType);
151
+ const colors = {
152
+ reset: '\x1b[0m',
153
+ red: '\x1b[31m',
154
+ green: '\x1b[32m',
155
+ yellow: '\x1b[33m',
156
+ cyan: '\x1b[36m',
157
+ gray: '\x1b[90m'
158
+ };
159
+ console.log();
160
+ console.log(`${colors.red}╭─ ${title}${colors.reset}`);
161
+ if (meta.feature) {
162
+ console.log(`${colors.red}│${colors.reset} Feature: ${colors.cyan}${meta.feature}${colors.reset}`);
163
+ }
164
+ if (meta.file) {
165
+ console.log(`${colors.red}│${colors.reset} File: ${colors.yellow}${meta.file}${colors.reset}`);
166
+ }
167
+ console.log(`${colors.red}│${colors.reset}`);
168
+ // ✅ Enhanced error message with wrapping
169
+ const errorPrefix = `${colors.red}❌ ERROR:${colors.reset}`;
170
+ const wrappedMessage = this.wrapErrorMessage(message, errorPrefix);
171
+ wrappedMessage.forEach((line, index) => {
172
+ if (index === 0) {
173
+ console.log(`${colors.red}│${colors.reset} ${line}`);
174
+ }
175
+ else {
176
+ console.log(`${colors.red}│${colors.reset}${line}`); // Continuation lines
177
+ }
178
+ });
179
+ // Show location/position if available
180
+ if (meta._location) {
181
+ console.log(`${colors.red}│${colors.reset} ${colors.cyan}📍 FROM:${colors.reset} ${meta._location}`);
182
+ }
183
+ // Extract and show line/position for syntax errors with wrapping
184
+ const lineMatch = message.match(/at line (\d+):(\d+)/i) || message.match(/line (\d+)/i);
185
+ if (lineMatch) {
186
+ console.log(`${colors.red}│${colors.reset} ${colors.cyan}📍 LINE:${colors.reset} ${lineMatch[1]}${lineMatch[2] ? `:${lineMatch[2]}` : ''}`);
187
+ }
188
+ // Show code context for syntax errors if available
189
+ if (message.includes('Unexpected token') || message.includes('SyntaxError')) {
190
+ const tokenMatch = message.match(/'([^']+)'/);
191
+ if (tokenMatch) {
192
+ console.log(`${colors.red}│${colors.reset} ${colors.cyan}📍 NEAR:${colors.reset} ...${tokenMatch[1]}...`);
193
+ console.log(`${colors.red}│${colors.reset} ${colors.red}^${colors.reset}`);
194
+ }
195
+ }
196
+ console.log(`${colors.red}│${colors.reset}`);
197
+ // Show smart diagnostics
198
+ diagnostics.forEach(diagnostic => {
199
+ const icon = diagnostic.type === 'error' ? '✗' :
200
+ diagnostic.type === 'warning' ? '⚠' :
201
+ diagnostic.type === 'success' ? '✓' : 'ℹ';
202
+ const color = diagnostic.type === 'error' ? colors.red :
203
+ diagnostic.type === 'warning' ? colors.yellow :
204
+ diagnostic.type === 'success' ? colors.green : colors.cyan;
205
+ // Wrap diagnostic messages too
206
+ const diagnosticPrefix = `${color}${icon}${colors.reset}`;
207
+ const wrappedDiagnostic = this.wrapErrorMessage(diagnostic.message, diagnosticPrefix);
208
+ wrappedDiagnostic.forEach((line, index) => {
209
+ if (index === 0) {
210
+ console.log(`${colors.red}│${colors.reset} ${line}`);
211
+ }
212
+ else {
213
+ console.log(`${colors.red}│${colors.reset}${line}`);
214
+ }
215
+ });
216
+ if (diagnostic.fix) {
217
+ const fixPrefix = `${colors.green}✓${colors.reset}`;
218
+ const wrappedFix = this.wrapErrorMessage(diagnostic.fix, fixPrefix);
219
+ wrappedFix.forEach((line, index) => {
220
+ if (index === 0) {
221
+ console.log(`${colors.red}│${colors.reset} ${line}`);
222
+ }
223
+ else {
224
+ console.log(`${colors.red}│${colors.reset}${line}`);
225
+ }
226
+ });
227
+ }
228
+ });
229
+ const solutions = this.getSolutions(errorType, message);
230
+ if (solutions.length > 0) {
231
+ console.log(`${colors.red}│${colors.reset}`);
232
+ solutions.forEach(solution => {
233
+ const solutionPrefix = `${colors.green}✓${colors.reset}`;
234
+ const wrappedSolution = this.wrapErrorMessage(solution, solutionPrefix);
235
+ wrappedSolution.forEach((line, index) => {
236
+ if (index === 0) {
237
+ console.log(`${colors.red}│${colors.reset} ${line}`);
238
+ }
239
+ else {
240
+ console.log(`${colors.red}│${colors.reset}${line}`);
241
+ }
242
+ });
243
+ });
244
+ }
245
+ // Enhanced fix message based on error type
246
+ const fixMessage = this.getFixMessage(errorType, message);
247
+ console.log(`${colors.red}╰─ FIX: ${colors.green}${fixMessage}${colors.reset}`);
248
+ console.log();
249
+ }
250
+ /**
251
+ * Wrap long error messages with proper indentation and path handling
252
+ * @param message - The message to wrap
253
+ * @param prefix - The prefix (like "❌ ERROR:" or "✗") to account for in width
254
+ */
255
+ wrapErrorMessage(message, prefix = '') {
256
+ const maxWidth = 85; // Terminal width accounting for borders
257
+ const indent = ' '; // 9 spaces for continuation lines
258
+ const prefixLength = this.stripAnsiCodes(prefix).length; // Account for prefix in first line
259
+ const firstLineMaxWidth = maxWidth - prefixLength - 1; // -1 for space after prefix
260
+ const continuationMaxWidth = maxWidth - indent.length;
261
+ const lines = [];
262
+ let currentLine = '';
263
+ let isFirstLine = true;
264
+ // Handle very long paths/URLs by splitting them intelligently
265
+ const processedMessage = this.preprocessLongPaths(message);
266
+ const words = processedMessage.split(' ');
267
+ for (const word of words) {
268
+ const currentMaxWidth = isFirstLine ? firstLineMaxWidth : continuationMaxWidth;
269
+ const proposedLine = currentLine + (currentLine ? ' ' : '') + word;
270
+ if (proposedLine.length > currentMaxWidth) {
271
+ // Current line would be too long
272
+ if (currentLine) {
273
+ // Save current line
274
+ if (isFirstLine) {
275
+ lines.push(`${prefix}${currentLine ? ' ' + currentLine : ''}`);
276
+ isFirstLine = false;
277
+ }
278
+ else {
279
+ lines.push(`${indent}${currentLine}`);
280
+ }
281
+ currentLine = word;
282
+ }
283
+ else {
284
+ // Single word is too long, force it on its own line
285
+ if (isFirstLine) {
286
+ lines.push(`${prefix}${word ? ' ' + word : ''}`);
287
+ isFirstLine = false;
288
+ }
289
+ else {
290
+ lines.push(`${indent}${word}`);
291
+ }
292
+ currentLine = '';
293
+ }
294
+ }
295
+ else {
296
+ currentLine = proposedLine;
297
+ }
298
+ }
299
+ // Add remaining content
300
+ if (currentLine) {
301
+ if (isFirstLine) {
302
+ lines.push(`${prefix}${currentLine ? ' ' + currentLine : ''}`);
303
+ }
304
+ else {
305
+ lines.push(`${indent}${currentLine}`);
306
+ }
307
+ }
308
+ // Handle empty prefix case
309
+ if (lines.length === 0) {
310
+ lines.push(prefix);
311
+ }
312
+ return lines;
313
+ }
314
+ /**
315
+ * Preprocess message to handle very long paths and URLs intelligently
316
+ */
317
+ preprocessLongPaths(message) {
318
+ // Split very long file paths at natural breakpoints
319
+ return message.replace(/([\/\\][^\/\\:\s]{30,})/g, (match) => {
320
+ // Break long paths at directory separators
321
+ if (match.length > 60) {
322
+ const parts = match.split(/([\/\\])/);
323
+ let result = '';
324
+ let currentSegment = '';
325
+ for (const part of parts) {
326
+ if ((currentSegment + part).length > 50 && currentSegment) {
327
+ result += currentSegment + '\n' + part;
328
+ currentSegment = '';
329
+ }
330
+ else {
331
+ currentSegment += part;
332
+ }
333
+ }
334
+ result += currentSegment;
335
+ return result;
336
+ }
337
+ return match;
338
+ });
339
+ }
340
+ /**
341
+ * Strip ANSI color codes to get actual text length
342
+ */
343
+ stripAnsiCodes(text) {
344
+ return text.replace(/\x1b\[[0-9;]*m/g, '');
345
+ }
346
+ detectErrorType(message, meta) {
347
+ // Check meta for explicit category first
348
+ if (meta.category) {
349
+ return meta.category;
350
+ }
351
+ // Handle only the MAJOR ones we have smart diagnostics for
352
+ // Enhanced detection for import vs syntax errors
353
+ if (message.includes('Cannot find module')) {
354
+ return this.detectImportVsSyntax(message, meta);
355
+ }
356
+ // Direct syntax error detection
357
+ if (message.includes('SyntaxError') ||
358
+ message.includes('Unexpected token') ||
359
+ message.includes('Unexpected end of input')) {
360
+ return 'syntax';
361
+ }
362
+ // Startup/infrastructure errors
363
+ if (message.includes('EADDRINUSE') ||
364
+ message.includes('CONTRACT') ||
365
+ message.includes('port') ||
366
+ message.includes('startup')) {
367
+ return 'startup';
368
+ }
369
+ // Route registration errors
370
+ if (message.includes('ROUTE') || message.includes('registration')) {
371
+ return 'route';
372
+ }
373
+ // For everything else - just show the raw error with general handling
374
+ return 'general';
375
+ }
376
+ detectImportVsSyntax(message, meta) {
377
+ const modulePath = message.match(/Cannot find module '([^']+)'/)?.[1];
378
+ if (modulePath && meta.feature) {
379
+ // Try to resolve the actual file path
380
+ const basePath = process.cwd();
381
+ const featurePath = join(basePath, 'src', 'features', meta.feature);
382
+ // Build possible file paths
383
+ const possiblePaths = [
384
+ join(featurePath, modulePath + '.ts'),
385
+ join(featurePath, modulePath + '.js'),
386
+ join(featurePath, modulePath, 'index.ts'),
387
+ join(featurePath, modulePath, 'index.js'),
388
+ // Also try relative to the file that's importing
389
+ modulePath + '.ts',
390
+ modulePath + '.js'
391
+ ];
392
+ // Check if any of these files exist
393
+ for (const filePath of possiblePaths) {
394
+ try {
395
+ if (existsSync(filePath)) {
396
+ // File exists but import failed - likely syntax error preventing import
397
+ return 'syntax';
398
+ }
399
+ }
400
+ catch {
401
+ // Ignore file system errors, continue checking
402
+ }
403
+ }
404
+ }
405
+ // File doesn't exist - true import error
406
+ return 'import';
407
+ }
408
+ getErrorTitle(errorType) {
409
+ const titles = {
410
+ import: 'IMPORT ERROR',
411
+ syntax: 'SYNTAX ERROR',
412
+ startup: 'STARTUP ERROR',
413
+ contract: 'CONTRACT ERROR',
414
+ route: 'ROUTE ERROR',
415
+ filesystem: 'FILE SYSTEM ERROR',
416
+ general: 'ERROR'
417
+ };
418
+ return titles[errorType] || 'ERROR';
419
+ }
420
+ generateDiagnostics(message, meta, errorType) {
421
+ const diagnostics = [];
422
+ // Only provide smart diagnostics for errors we understand well
423
+ switch (errorType) {
424
+ case 'syntax':
425
+ if (message.includes('Unexpected token')) {
426
+ const tokenMatch = message.match(/Unexpected token '([^']+)'/);
427
+ if (tokenMatch) {
428
+ diagnostics.push({
429
+ type: 'error',
430
+ message: `Unexpected token: ${tokenMatch[1]}`,
431
+ });
432
+ }
433
+ }
434
+ if (message.includes('Unexpected end of input')) {
435
+ diagnostics.push({
436
+ type: 'error',
437
+ message: 'Missing closing bracket, brace, or parenthesis',
438
+ fix: 'Check for unclosed {}, [], or () brackets'
439
+ });
440
+ }
441
+ // Line number extraction
442
+ const lineMatch = message.match(/line (\d+)/i);
443
+ if (lineMatch) {
444
+ diagnostics.push({
445
+ type: 'info',
446
+ message: `Error location: line ${lineMatch[1]}`
447
+ });
448
+ }
449
+ break;
450
+ case 'import':
451
+ const missingModule = message.match(/Cannot find module '([^']+)'/)?.[1];
452
+ if (missingModule) {
453
+ diagnostics.push({
454
+ type: 'error',
455
+ message: `Missing import: ${missingModule}`,
456
+ });
457
+ // Check for common typos
458
+ if (missingModule.includes('Service') && missingModule.endsWith('Servic')) {
459
+ diagnostics.push({
460
+ type: 'warning',
461
+ message: 'Looks like a typo: missing \'e\' at end?',
462
+ fix: `Try: ${missingModule}e`
463
+ });
464
+ }
465
+ if (missingModule.includes('/services/')) {
466
+ diagnostics.push({
467
+ type: 'info',
468
+ message: 'Check service file exists and name matches'
469
+ });
470
+ }
471
+ }
472
+ break;
473
+ case 'startup':
474
+ if (message.includes('EADDRINUSE')) {
475
+ diagnostics.push({
476
+ type: 'error',
477
+ message: 'Port already in use',
478
+ fix: 'Change PORT environment variable or stop conflicting process'
479
+ });
480
+ }
481
+ if (message.includes('CONTRACT')) {
482
+ diagnostics.push({
483
+ type: 'error',
484
+ message: 'Contract validation failed',
485
+ fix: 'Run: npm run flux:check to see detailed contract issues'
486
+ });
487
+ }
488
+ break;
489
+ case 'route':
490
+ if (message.includes('export')) {
491
+ diagnostics.push({
492
+ type: 'error',
493
+ message: 'Route file must export a function as default',
494
+ fix: 'Add: export default router(...)'
495
+ });
496
+ }
497
+ break;
498
+ case 'general':
499
+ // For general errors, don't add diagnostics - just show the raw error
500
+ // This covers ReferenceError, TypeError, and all other JS errors
501
+ break;
502
+ }
503
+ return diagnostics;
504
+ }
505
+ getFixMessage(errorType, message) {
506
+ // Pattern-based error analysis - extract meaning from the error message itself
507
+ // 1. SYNTAX ERRORS - Parse what's actually expected/unexpected
508
+ const expectedMatch = message.match(/Expected "(.+?)" but found/i);
509
+ if (expectedMatch) {
510
+ return `Add missing "${expectedMatch[1]}"`;
511
+ }
512
+ const unexpectedTokenMatch = message.match(/Unexpected token "(.+?)"/i) || message.match(/Unexpected "(.+?)"/i);
513
+ if (unexpectedTokenMatch) {
514
+ return `Remove or fix unexpected "${unexpectedTokenMatch[1]}"`;
515
+ }
516
+ if (message.match(/Unexpected end of input/i)) {
517
+ return 'Add missing closing bracket, brace, or parenthesis';
518
+ }
519
+ // 2. IMPORT/MODULE ERRORS - Extract the actual module path
520
+ const moduleMatch = message.match(/Cannot find module ['"']([^'"]+)['"']/);
521
+ if (moduleMatch) {
522
+ const modulePath = moduleMatch[1];
523
+ const fileName = modulePath.split('/').pop() || modulePath;
524
+ return `Check if file "${fileName}" exists at path: ${modulePath}`;
525
+ }
526
+ // 3. REFERENCE ERRORS - Extract the undefined variable/function
527
+ const refErrorMatch = message.match(/(\w+) is not defined/);
528
+ if (refErrorMatch) {
529
+ return `Define variable or import "${refErrorMatch[1]}"`;
530
+ }
531
+ // 4. TYPE ERRORS - Extract specific type issues
532
+ const notFunctionMatch = message.match(/(\w+) is not a function/);
533
+ if (notFunctionMatch) {
534
+ return `Check that "${notFunctionMatch[1]}" is actually a function`;
535
+ }
536
+ const cannotReadMatch = message.match(/Cannot read propert(?:y|ies) ['"]?(\w+)['"]? of/);
537
+ if (cannotReadMatch) {
538
+ return `Check object exists before accessing property "${cannotReadMatch[1]}"`;
539
+ }
540
+ const cannotAccessMatch = message.match(/Cannot access ['"]?(\w+)['"]? before initialization/);
541
+ if (cannotAccessMatch) {
542
+ return `Move "${cannotAccessMatch[1]}" declaration before usage`;
543
+ }
544
+ // 5. NETWORK/CONNECTION ERRORS - Extract connection details
545
+ const econnrefusedMatch = message.match(/ECONNREFUSED.*?(\d+)/);
546
+ if (econnrefusedMatch) {
547
+ return `Connection refused on port ${econnrefusedMatch[1]} - check if service is running`;
548
+ }
549
+ if (message.match(/EADDRINUSE.*?(\d+)/)) {
550
+ const portMatch = message.match(/(\d+)/);
551
+ return portMatch ? `Port ${portMatch[1]} already in use - choose different port` : 'Port already in use';
552
+ }
553
+ // 6. FILE SYSTEM ERRORS - Extract file/directory info
554
+ const enoentMatch = message.match(/ENOENT.*?['"]([^'"]+)['"]/) || message.match(/no such file or directory.*?['"]([^'"]+)['"]/);
555
+ if (enoentMatch) {
556
+ return `File not found: ${enoentMatch[1]}`;
557
+ }
558
+ const eaccesMatch = message.match(/EACCES.*?['"]([^'"]+)['"]/) || message.match(/permission denied.*?['"]([^'"]+)['"]/);
559
+ if (eaccesMatch) {
560
+ return `Permission denied accessing: ${eaccesMatch[1]}`;
561
+ }
562
+ // 7. COMPILATION/TRANSFORM ERRORS - Extract compilation context
563
+ if (message.match(/Transform failed|compilation failed/i)) {
564
+ const lineMatch = message.match(/line (\d+)/i) || message.match(/:(\d+):/);
565
+ return lineMatch ? `Fix compilation error at line ${lineMatch[1]}` : 'Fix compilation/syntax errors';
566
+ }
567
+ // 8. PROMISE/ASYNC ERRORS
568
+ if (message.match(/UnhandledPromiseRejection/i)) {
569
+ return 'Add .catch() handler or try/catch block for async operation';
570
+ }
571
+ // 9. EXPORT/IMPORT ERRORS - Extract export context
572
+ if (message.match(/default.*?export/i) || message.match(/export.*?default/i)) {
573
+ return 'Fix export default statement syntax';
574
+ }
575
+ // 10. LINE-SPECIFIC ERRORS - Extract line numbers when available
576
+ const lineNumberMatch = message.match(/(?:line |:)(\d+)(?::(\d+))?/i);
577
+ if (lineNumberMatch) {
578
+ const line = lineNumberMatch[1];
579
+ const column = lineNumberMatch[2];
580
+ const location = column ? `line ${line}, column ${column}` : `line ${line}`;
581
+ if (message.match(/syntax|unexpected|expected/i)) {
582
+ return `Fix syntax error at ${location}`;
583
+ }
584
+ return `Check code at ${location}`;
585
+ }
586
+ // 11. GENERIC PATTERNS - Fallback pattern matching
587
+ if (message.match(/not found|missing/i)) {
588
+ return 'Check that required files/resources exist';
589
+ }
590
+ if (message.match(/timeout|timed out/i)) {
591
+ return 'Increase timeout or check network connectivity';
592
+ }
593
+ if (message.match(/invalid|malformed/i)) {
594
+ return 'Check data format and syntax';
595
+ }
596
+ if (message.match(/denied|forbidden/i)) {
597
+ return 'Check permissions and access rights';
598
+ }
599
+ // 12. FRAMEWORK-AGNOSTIC FALLBACKS by error type
600
+ switch (errorType) {
601
+ case 'import':
602
+ return 'Verify import paths and file existence';
603
+ case 'syntax':
604
+ return 'Fix JavaScript/TypeScript syntax errors';
605
+ case 'startup':
606
+ return 'Fix configuration or dependency issues';
607
+ case 'route':
608
+ return 'Check export statements and file structure';
609
+ case 'general':
610
+ return 'Review error details above';
611
+ default:
612
+ return 'Fix the error described above';
613
+ }
614
+ }
615
+ /**
616
+ * Get contextual solutions based on error message patterns
617
+ */
618
+ getSolutions(errorType, message) {
619
+ const solutions = [];
620
+ // Extract solutions based on actual error content
621
+ if (message.match(/Expected "(.+?)" but found/)) {
622
+ solutions.push('Check for missing brackets, parentheses, or braces');
623
+ solutions.push('Verify function call syntax');
624
+ }
625
+ if (message.match(/Cannot find module/)) {
626
+ solutions.push('Check if file exists at the specified path');
627
+ solutions.push('Verify import path spelling');
628
+ solutions.push('Check file extensions (.js, .ts)');
629
+ }
630
+ if (message.match(/is not defined/)) {
631
+ solutions.push('Import the required module or variable');
632
+ solutions.push('Check variable name spelling');
633
+ solutions.push('Verify variable is declared before use');
634
+ }
635
+ if (message.match(/is not a function/)) {
636
+ solutions.push('Check that imported item is actually a function');
637
+ solutions.push('Verify function is exported correctly');
638
+ }
639
+ if (message.match(/EADDRINUSE/)) {
640
+ solutions.push('Change to a different port number');
641
+ solutions.push('Stop the process using this port');
642
+ solutions.push('Check for other running servers');
643
+ }
644
+ if (message.match(/line \d+/i)) {
645
+ const lineMatch = message.match(/line (\d+)/i);
646
+ if (lineMatch) {
647
+ solutions.push(`Check syntax around line ${lineMatch[1]}`);
648
+ solutions.push('Look for missing commas or semicolons');
649
+ }
650
+ }
651
+ // Add generic solutions if none were found
652
+ if (solutions.length === 0) {
653
+ const defaultSolutions = {
654
+ import: ['Verify file paths and existence', 'Check import syntax'],
655
+ syntax: ['Fix JavaScript/TypeScript syntax', 'Check for missing punctuation'],
656
+ startup: ['Review configuration files', 'Check dependencies'],
657
+ route: ['Verify export statements', 'Check file structure'],
658
+ general: ['Review error message details', 'Check recent code changes']
659
+ };
660
+ solutions.push(...(defaultSolutions[errorType] || defaultSolutions.general));
661
+ }
662
+ return solutions;
663
+ }
664
+ // ============================================================================
665
+ // EXISTING HELPER METHODS
666
+ // ============================================================================
667
+ getCaller() {
668
+ const stack = new Error().stack;
669
+ if (!stack)
670
+ return 'unknown';
671
+ const lines = stack.split('\n');
672
+ const callerLine = lines[4] || '';
673
+ const match = callerLine.match(/\((.+):(\d+):(\d+)\)/) ||
674
+ callerLine.match(/at\s+(.+):(\d+):(\d+)/);
675
+ if (match) {
676
+ const [, filePath, lineNumber] = match;
677
+ const cleanPath = filePath.replace(process.cwd() + '/', '');
678
+ return `${cleanPath}:${lineNumber}`;
679
+ }
680
+ return 'unknown';
681
+ }
682
+ log(level, message, meta) {
683
+ if (LOG_LEVELS[level] > this.levelValue) {
684
+ return;
685
+ }
686
+ const entry = {
687
+ timestamp: new Date().toISOString(),
688
+ level,
689
+ message: message || '',
690
+ ...this.defaultMeta,
691
+ ...meta,
692
+ };
693
+ this.writeToTransports(entry);
694
+ }
695
+ writeToTransports(entry) {
696
+ const writePromises = [];
697
+ for (const [name, transport] of this.transports) {
698
+ try {
699
+ if (transport.shouldLog && !transport.shouldLog(entry.level, this.level)) {
700
+ continue;
701
+ }
702
+ const result = transport.write(entry);
703
+ if (result && typeof result.then === 'function') {
704
+ writePromises.push(result.catch((error) => {
705
+ console.error(`Transport ${name} write failed:`, error.message);
706
+ }));
707
+ }
708
+ }
709
+ catch (error) {
710
+ console.error(`Transport ${name} write error:`, error.message);
711
+ }
712
+ }
713
+ this.pendingWrites = writePromises;
714
+ }
715
+ // ============================================================================
716
+ // PUBLIC UTILITY METHODS
717
+ // ============================================================================
718
+ /**
719
+ * Flush pending logs to all transports
720
+ * @llm-rule WHEN: App shutdown or ensuring logs are persisted before critical operations
721
+ * @llm-rule AVOID: Frequent flushing during normal operations - impacts performance
722
+ */
723
+ async flush() {
724
+ if (this.pendingWrites.length > 0) {
725
+ try {
726
+ await Promise.all(this.pendingWrites);
727
+ }
728
+ catch {
729
+ // Errors already handled in writeToTransports
730
+ }
731
+ this.pendingWrites = [];
732
+ }
733
+ const flushPromises = [];
734
+ for (const [name, transport] of this.transports) {
735
+ if (transport.flush) {
736
+ try {
737
+ const result = transport.flush();
738
+ if (result) {
739
+ flushPromises.push(result.catch((error) => {
740
+ console.error(`Transport ${name} flush failed:`, error.message);
741
+ }));
742
+ }
743
+ }
744
+ catch (error) {
745
+ console.error(`Transport ${name} flush error:`, error.message);
746
+ }
747
+ }
748
+ }
749
+ if (flushPromises.length > 0) {
750
+ await Promise.all(flushPromises);
751
+ }
752
+ }
753
+ /**
754
+ * Close logger and cleanup all transports
755
+ * @llm-rule WHEN: App shutdown or logger cleanup - ensures graceful resource cleanup
756
+ * @llm-rule AVOID: Calling during normal operations - this permanently closes the logger
757
+ */
758
+ async close() {
759
+ await this.flush();
760
+ const closePromises = [];
761
+ for (const [name, transport] of this.transports) {
762
+ if (transport.close) {
763
+ try {
764
+ const result = transport.close();
765
+ if (result) {
766
+ closePromises.push(result.catch((error) => {
767
+ console.error(`Transport ${name} close failed:`, error.message);
768
+ }));
769
+ }
770
+ }
771
+ catch (error) {
772
+ console.error(`Transport ${name} close error:`, error.message);
773
+ }
774
+ }
775
+ }
776
+ if (closePromises.length > 0) {
777
+ await Promise.all(closePromises);
778
+ }
779
+ this.transports.clear();
780
+ }
781
+ /**
782
+ * Get list of active transport names
783
+ * @llm-rule WHEN: Debugging logger setup or checking which transports are running
784
+ * @llm-rule AVOID: Using for business logic - this is for debugging and monitoring only
785
+ */
786
+ getActiveTransports() {
787
+ return Array.from(this.transports.keys());
788
+ }
789
+ /**
790
+ * Check if specific transport is active
791
+ * @llm-rule WHEN: Conditionally logging based on transport availability
792
+ * @llm-rule AVOID: Complex transport detection - just log normally, transports auto-enable
793
+ */
794
+ hasTransport(name) {
795
+ return this.transports.has(name);
796
+ }
797
+ /**
798
+ * Set minimum log level dynamically
799
+ * @llm-rule WHEN: Runtime log level changes, debugging, or feature flags
800
+ * @llm-rule AVOID: Frequent level changes - impacts performance
801
+ */
802
+ setLevel(level) {
803
+ this.level = level;
804
+ this.levelValue = LOG_LEVELS[level];
805
+ }
806
+ /**
807
+ * Get current minimum log level
808
+ * @llm-rule WHEN: Debugging configuration or checking level settings
809
+ * @llm-rule AVOID: Using for filtering logic - logger handles level filtering automatically
810
+ */
811
+ getLevel() {
812
+ return this.level;
813
+ }
814
+ /**
815
+ * Check if specific log level would be written
816
+ * @llm-rule WHEN: Expensive log message preparation - check before building complex meta
817
+ * @llm-rule AVOID: Normal logging - level filtering is automatic and fast
818
+ */
819
+ isLevelEnabled(level) {
820
+ return LOG_LEVELS[level] <= this.levelValue;
821
+ }
822
+ /**
823
+ * Get current logger configuration for debugging
824
+ * @llm-rule WHEN: Debugging logger setup, checking environment detection, or monitoring
825
+ * @llm-rule AVOID: Using for runtime business logic - configuration is set at startup
826
+ */
827
+ getConfig() {
828
+ return {
829
+ level: this.level,
830
+ scope: this.config.scope,
831
+ minimal: this.config.minimal,
832
+ transports: this.getActiveTransports(),
833
+ service: this.config.service,
834
+ environment: {
835
+ NODE_ENV: process.env.NODE_ENV,
836
+ hasDbUrl: !!process.env.DATABASE_URL,
837
+ hasHttpUrl: !!process.env.VOILA_LOGGER_HTTP_URL,
838
+ hasWebhookUrl: !!process.env.VOILA_LOGGER_WEBHOOK_URL,
839
+ },
840
+ };
841
+ }
842
+ }
843
+ //# sourceMappingURL=logger.js.map