@talex-touch/utils 1.0.42 → 1.0.45

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 (234) hide show
  1. package/.eslintcache +1 -0
  2. package/__tests__/cloud-sync-sdk.test.ts +442 -0
  3. package/__tests__/icons/icons.test.ts +84 -0
  4. package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
  5. package/__tests__/power-sdk.test.ts +143 -0
  6. package/__tests__/preset-export-types.test.ts +108 -0
  7. package/__tests__/search/fuzzy-match.test.ts +137 -0
  8. package/__tests__/transport/port-policy.test.ts +44 -0
  9. package/__tests__/transport-domain-sdks.test.ts +152 -0
  10. package/__tests__/types/update.test.ts +67 -0
  11. package/account/account-sdk.ts +915 -0
  12. package/account/index.ts +2 -0
  13. package/account/types.ts +321 -0
  14. package/analytics/client.ts +136 -0
  15. package/analytics/index.ts +2 -0
  16. package/analytics/types.ts +156 -0
  17. package/animation/auto-resize.ts +322 -0
  18. package/animation/window-node.ts +26 -19
  19. package/auth/clerk-types.ts +12 -30
  20. package/auth/index.ts +0 -2
  21. package/auth/useAuthState.ts +6 -14
  22. package/base/index.ts +2 -0
  23. package/base/log-level.ts +105 -0
  24. package/channel/index.ts +170 -69
  25. package/cloud-sync/cloud-sync-sdk.ts +450 -0
  26. package/cloud-sync/index.ts +1 -0
  27. package/common/file-scan-utils.ts +17 -9
  28. package/common/index.ts +4 -0
  29. package/common/logger/index.ts +46 -0
  30. package/common/logger/logger-manager.ts +303 -0
  31. package/common/logger/module-logger.ts +270 -0
  32. package/common/logger/transport-logger.ts +234 -0
  33. package/common/logger/types.ts +93 -0
  34. package/common/search/gather.ts +48 -6
  35. package/common/search/index.ts +8 -0
  36. package/common/storage/constants.ts +13 -0
  37. package/common/storage/entity/app-settings.ts +245 -0
  38. package/common/storage/entity/index.ts +3 -0
  39. package/common/storage/entity/layout-atom-types.ts +147 -0
  40. package/common/storage/entity/openers.ts +1 -0
  41. package/common/storage/entity/preset-cloud-api.ts +132 -0
  42. package/common/storage/entity/preset-export-types.ts +256 -0
  43. package/common/storage/entity/shortcut-settings.ts +1 -0
  44. package/common/storage/shortcut-storage.ts +11 -0
  45. package/common/utils/clone-diagnostics.ts +105 -0
  46. package/common/utils/file.ts +16 -8
  47. package/common/utils/index.ts +6 -2
  48. package/common/utils/payload-preview.ts +173 -0
  49. package/common/utils/polling.ts +167 -13
  50. package/common/utils/safe-path.ts +103 -0
  51. package/common/utils/safe-shell.ts +115 -0
  52. package/common/utils/task-queue.ts +4 -1
  53. package/core-box/builder/tuff-builder.ts +0 -1
  54. package/core-box/index.ts +1 -1
  55. package/core-box/recommendation.ts +38 -1
  56. package/core-box/tuff/tuff-dsl.ts +32 -0
  57. package/electron/download-manager.ts +10 -7
  58. package/electron/env-tool.ts +42 -40
  59. package/electron/index.ts +0 -1
  60. package/env/index.ts +156 -0
  61. package/eslint.config.js +55 -0
  62. package/i18n/index.ts +62 -0
  63. package/i18n/locales/en.json +226 -0
  64. package/i18n/locales/zh.json +226 -0
  65. package/i18n/message-keys.ts +236 -0
  66. package/i18n/resolver.ts +181 -0
  67. package/icons/index.ts +257 -0
  68. package/icons/svg.ts +69 -0
  69. package/index.ts +9 -1
  70. package/intelligence/client.ts +72 -42
  71. package/market/constants.ts +9 -5
  72. package/market/index.ts +1 -1
  73. package/market/types.ts +19 -4
  74. package/package.json +15 -5
  75. package/permission/index.ts +143 -46
  76. package/permission/legacy.ts +26 -0
  77. package/permission/registry.ts +304 -0
  78. package/permission/types.ts +164 -0
  79. package/plugin/channel.ts +68 -39
  80. package/plugin/index.ts +80 -7
  81. package/plugin/install.ts +3 -0
  82. package/plugin/log/types.ts +22 -5
  83. package/plugin/node/logger-manager.ts +11 -3
  84. package/plugin/node/logger.ts +24 -17
  85. package/plugin/preload.ts +25 -2
  86. package/plugin/providers/index.ts +4 -4
  87. package/plugin/providers/market-client.ts +6 -3
  88. package/plugin/providers/npm-provider.ts +22 -7
  89. package/plugin/providers/tpex-provider.ts +22 -8
  90. package/plugin/sdk/box-items.ts +14 -0
  91. package/plugin/sdk/box-sdk.ts +64 -0
  92. package/plugin/sdk/channel.ts +119 -4
  93. package/plugin/sdk/clipboard.ts +26 -12
  94. package/plugin/sdk/cloud-sync.ts +113 -0
  95. package/plugin/sdk/common.ts +19 -11
  96. package/plugin/sdk/core-box.ts +6 -15
  97. package/plugin/sdk/division-box.ts +160 -65
  98. package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
  99. package/plugin/sdk/feature-sdk.ts +111 -76
  100. package/plugin/sdk/flow.ts +146 -45
  101. package/plugin/sdk/hooks/bridge.ts +13 -6
  102. package/plugin/sdk/hooks/life-cycle.ts +35 -16
  103. package/plugin/sdk/index.ts +14 -3
  104. package/plugin/sdk/intelligence.ts +87 -0
  105. package/plugin/sdk/meta/README.md +179 -0
  106. package/plugin/sdk/meta-sdk.ts +244 -0
  107. package/plugin/sdk/notification.ts +9 -0
  108. package/plugin/sdk/plugin-info.ts +64 -0
  109. package/plugin/sdk/power.ts +155 -0
  110. package/plugin/sdk/recommend.ts +21 -0
  111. package/plugin/sdk/service/index.ts +12 -8
  112. package/plugin/sdk/sqlite.ts +141 -0
  113. package/plugin/sdk/storage.ts +2 -6
  114. package/plugin/sdk/system.ts +2 -9
  115. package/plugin/sdk/temp-files.ts +41 -0
  116. package/plugin/sdk/touch-sdk.ts +18 -0
  117. package/plugin/sdk/types.ts +44 -4
  118. package/plugin/sdk/window/index.ts +12 -9
  119. package/plugin/sdk-version.ts +231 -0
  120. package/preload/renderer.ts +3 -2
  121. package/renderer/hooks/arg-mapper.ts +16 -2
  122. package/renderer/hooks/index.ts +13 -0
  123. package/renderer/hooks/initialize.ts +2 -1
  124. package/renderer/hooks/use-agent-market-sdk.ts +7 -0
  125. package/renderer/hooks/use-agent-market.ts +106 -0
  126. package/renderer/hooks/use-agents-sdk.ts +7 -0
  127. package/renderer/hooks/use-app-sdk.ts +7 -0
  128. package/renderer/hooks/use-channel.ts +33 -4
  129. package/renderer/hooks/use-download-sdk.ts +21 -0
  130. package/renderer/hooks/use-intelligence-sdk.ts +7 -0
  131. package/renderer/hooks/use-intelligence-stats.ts +290 -0
  132. package/renderer/hooks/use-intelligence.ts +55 -214
  133. package/renderer/hooks/use-market-sdk.ts +16 -0
  134. package/renderer/hooks/use-notification-sdk.ts +7 -0
  135. package/renderer/hooks/use-permission-sdk.ts +7 -0
  136. package/renderer/hooks/use-permission.ts +325 -0
  137. package/renderer/hooks/use-platform-sdk.ts +7 -0
  138. package/renderer/hooks/use-plugin-sdk.ts +16 -0
  139. package/renderer/hooks/use-settings-sdk.ts +7 -0
  140. package/renderer/hooks/use-update-sdk.ts +21 -0
  141. package/renderer/index.ts +1 -0
  142. package/renderer/ref.ts +19 -10
  143. package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
  144. package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
  145. package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
  146. package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
  147. package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
  148. package/renderer/shared/components/index.ts +5 -0
  149. package/renderer/shared/components/shims-vue.d.ts +5 -0
  150. package/renderer/shared/index.ts +2 -0
  151. package/renderer/shared/plugin-detail.ts +62 -0
  152. package/renderer/storage/app-settings.ts +3 -1
  153. package/renderer/storage/base-storage.ts +508 -82
  154. package/renderer/storage/intelligence-storage.ts +31 -40
  155. package/renderer/storage/openers.ts +3 -1
  156. package/renderer/storage/storage-subscription.ts +126 -42
  157. package/renderer/touch-sdk/env.ts +10 -10
  158. package/renderer/touch-sdk/index.ts +114 -18
  159. package/renderer/touch-sdk/terminal.ts +24 -13
  160. package/search/feature-matcher.ts +279 -0
  161. package/search/fuzzy-match.ts +64 -34
  162. package/search/index.ts +10 -0
  163. package/search/levenshtein-utils.ts +17 -11
  164. package/transport/errors.ts +310 -0
  165. package/transport/event/builder.ts +378 -0
  166. package/transport/event/index.ts +7 -0
  167. package/transport/event/types.ts +292 -0
  168. package/transport/events/index.ts +2690 -0
  169. package/transport/events/meta-overlay.ts +79 -0
  170. package/transport/events/types/agents.ts +177 -0
  171. package/transport/events/types/app-index.ts +20 -0
  172. package/transport/events/types/app.ts +475 -0
  173. package/transport/events/types/box-item.ts +222 -0
  174. package/transport/events/types/clipboard.ts +80 -0
  175. package/transport/events/types/core-box.ts +534 -0
  176. package/transport/events/types/device-idle.ts +7 -0
  177. package/transport/events/types/division-box.ts +99 -0
  178. package/transport/events/types/download.ts +115 -0
  179. package/transport/events/types/file-index.ts +84 -0
  180. package/transport/events/types/flow.ts +149 -0
  181. package/transport/events/types/index.ts +70 -0
  182. package/transport/events/types/market.ts +39 -0
  183. package/transport/events/types/meta-overlay.ts +184 -0
  184. package/transport/events/types/notification.ts +140 -0
  185. package/transport/events/types/permission.ts +90 -0
  186. package/transport/events/types/platform.ts +8 -0
  187. package/transport/events/types/plugin.ts +631 -0
  188. package/transport/events/types/sentry.ts +20 -0
  189. package/transport/events/types/storage.ts +208 -0
  190. package/transport/events/types/transport.ts +60 -0
  191. package/transport/events/types/tray.ts +16 -0
  192. package/transport/events/types/update.ts +78 -0
  193. package/transport/index.ts +141 -0
  194. package/transport/main.ts +2 -0
  195. package/transport/prelude.ts +208 -0
  196. package/transport/sdk/constants.ts +29 -0
  197. package/transport/sdk/domains/agents-market.ts +47 -0
  198. package/transport/sdk/domains/agents.ts +62 -0
  199. package/transport/sdk/domains/app.ts +48 -0
  200. package/transport/sdk/domains/disposable.ts +35 -0
  201. package/transport/sdk/domains/download.ts +139 -0
  202. package/transport/sdk/domains/index.ts +13 -0
  203. package/transport/sdk/domains/intelligence.ts +616 -0
  204. package/transport/sdk/domains/market.ts +35 -0
  205. package/transport/sdk/domains/notification.ts +62 -0
  206. package/transport/sdk/domains/permission.ts +85 -0
  207. package/transport/sdk/domains/platform.ts +19 -0
  208. package/transport/sdk/domains/plugin.ts +144 -0
  209. package/transport/sdk/domains/settings.ts +102 -0
  210. package/transport/sdk/domains/update.ts +64 -0
  211. package/transport/sdk/index.ts +60 -0
  212. package/transport/sdk/main-transport.ts +710 -0
  213. package/transport/sdk/main.ts +9 -0
  214. package/transport/sdk/plugin-transport.ts +654 -0
  215. package/transport/sdk/port-policy.ts +38 -0
  216. package/transport/sdk/renderer-transport.ts +1165 -0
  217. package/transport/types.ts +605 -0
  218. package/types/agent.ts +399 -0
  219. package/types/cloud-sync.ts +157 -0
  220. package/types/division-box.ts +31 -31
  221. package/types/download.ts +1 -0
  222. package/types/flow.ts +63 -12
  223. package/types/icon.ts +2 -1
  224. package/types/index.ts +5 -0
  225. package/types/intelligence.ts +166 -173
  226. package/types/modules/base.ts +2 -0
  227. package/types/path-browserify.d.ts +5 -0
  228. package/types/platform.ts +12 -0
  229. package/types/startup-info.ts +32 -0
  230. package/types/touch-app-core.ts +8 -8
  231. package/types/update.ts +94 -1
  232. package/vitest.config.ts +25 -0
  233. package/auth/useClerkConfig.ts +0 -40
  234. package/auth/useClerkProvider.ts +0 -52
@@ -0,0 +1,303 @@
1
+ /**
2
+ * LoggerManager
3
+ *
4
+ * Singleton manager for all module loggers.
5
+ * Handles configuration, global controls, and logger lifecycle.
6
+ */
7
+
8
+ import type { LoggerInfo, LoggingConfig, ModuleLoggerOptions } from './types'
9
+ import { ModuleLogger } from './module-logger'
10
+ import {
11
+
12
+ LogLevel,
13
+ logLevelToString,
14
+
15
+ stringToLogLevel,
16
+ } from './types'
17
+
18
+ /**
19
+ * Default logging configuration
20
+ */
21
+ const DEFAULT_CONFIG: LoggingConfig = {
22
+ enabled: true,
23
+ globalLevel: 'debug',
24
+ modules: {},
25
+ }
26
+
27
+ /**
28
+ * Predefined module defaults
29
+ */
30
+ const MODULE_DEFAULTS: Record<string, { enabled: boolean, level: LogLevel, color: string }> = {
31
+ 'search-engine': { enabled: true, level: LogLevel.DEBUG, color: 'cyan' },
32
+ 'file-provider': { enabled: false, level: LogLevel.DEBUG, color: 'green' },
33
+ 'app-provider': { enabled: false, level: LogLevel.DEBUG, color: 'blue' },
34
+ 'plugin-system': { enabled: true, level: LogLevel.INFO, color: 'magenta' },
35
+ 'database': { enabled: false, level: LogLevel.WARN, color: 'yellow' },
36
+ 'storage': { enabled: false, level: LogLevel.WARN, color: 'yellow' },
37
+ 'clipboard': { enabled: false, level: LogLevel.INFO, color: 'cyan' },
38
+ 'flow-bus': { enabled: true, level: LogLevel.INFO, color: 'green' },
39
+ 'division-box': { enabled: true, level: LogLevel.INFO, color: 'blue' },
40
+ 'channel-core': { enabled: true, level: LogLevel.INFO, color: 'cyan' },
41
+ 'core-box': { enabled: true, level: LogLevel.INFO, color: 'cyan' },
42
+ 'tray': { enabled: false, level: LogLevel.INFO, color: 'gray' },
43
+ 'download': { enabled: true, level: LogLevel.INFO, color: 'green' },
44
+ 'intelligence': { enabled: true, level: LogLevel.INFO, color: 'magenta' },
45
+ 'terminal': { enabled: false, level: LogLevel.DEBUG, color: 'gray' },
46
+ 'update': { enabled: true, level: LogLevel.INFO, color: 'blue' },
47
+ 'widget': { enabled: true, level: LogLevel.DEBUG, color: 'cyan' },
48
+ }
49
+
50
+ /**
51
+ * LoggerManager singleton
52
+ *
53
+ * Manages all module loggers with:
54
+ * - Centralized configuration
55
+ * - Global enable/disable
56
+ * - Per-module level control
57
+ * - Configuration persistence
58
+ */
59
+ export class LoggerManager {
60
+ private static instance: LoggerManager | null = null
61
+ private loggers: Map<string, ModuleLogger> = new Map()
62
+ private config: LoggingConfig = { ...DEFAULT_CONFIG }
63
+ private configLoader: (() => Promise<LoggingConfig | null>) | null = null
64
+ private configSaver: ((config: LoggingConfig) => Promise<void>) | null = null
65
+
66
+ private constructor() {}
67
+
68
+ /**
69
+ * Get singleton instance
70
+ */
71
+ static getInstance(): LoggerManager {
72
+ if (!LoggerManager.instance) {
73
+ LoggerManager.instance = new LoggerManager()
74
+ }
75
+ return LoggerManager.instance
76
+ }
77
+
78
+ /**
79
+ * Get or create a logger for a module
80
+ */
81
+ getLogger(module: string, options?: Partial<ModuleLoggerOptions>): ModuleLogger {
82
+ let logger = this.loggers.get(module)
83
+
84
+ if (!logger) {
85
+ // Get module defaults
86
+ const defaults = MODULE_DEFAULTS[module]
87
+ const moduleConfig = this.config.modules[module]
88
+
89
+ // Determine enabled state
90
+ let enabled = this.config.enabled
91
+ if (moduleConfig?.enabled !== undefined) {
92
+ enabled = enabled && moduleConfig.enabled
93
+ }
94
+ else if (defaults?.enabled !== undefined) {
95
+ enabled = enabled && defaults.enabled
96
+ }
97
+ if (options?.enabled !== undefined) {
98
+ enabled = enabled && options.enabled
99
+ }
100
+
101
+ // Determine log level
102
+ let level = stringToLogLevel(this.config.globalLevel)
103
+ if (moduleConfig?.level) {
104
+ level = Math.max(level, stringToLogLevel(moduleConfig.level))
105
+ }
106
+ else if (defaults?.level !== undefined) {
107
+ level = Math.max(level, defaults.level)
108
+ }
109
+ if (options?.level !== undefined) {
110
+ level = options.level
111
+ }
112
+
113
+ // Determine color
114
+ const color = options?.color ?? defaults?.color ?? 'cyan'
115
+
116
+ logger = new ModuleLogger({
117
+ module,
118
+ color,
119
+ enabled,
120
+ level,
121
+ prefix: options?.prefix,
122
+ })
123
+
124
+ this.loggers.set(module, logger)
125
+ }
126
+
127
+ return logger
128
+ }
129
+
130
+ /**
131
+ * Enable all loggers
132
+ */
133
+ enableAll(): void {
134
+ this.config.enabled = true
135
+ for (const logger of this.loggers.values()) {
136
+ logger.setEnabled(true)
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Disable all loggers
142
+ */
143
+ disableAll(): void {
144
+ this.config.enabled = false
145
+ for (const logger of this.loggers.values()) {
146
+ logger.setEnabled(false)
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Set global log level
152
+ */
153
+ setGlobalLevel(level: LogLevel): void {
154
+ this.config.globalLevel = logLevelToString(level)
155
+ for (const logger of this.loggers.values()) {
156
+ if (logger.getLevel() < level) {
157
+ logger.setLevel(level)
158
+ }
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Set module-specific configuration
164
+ */
165
+ setModuleConfig(module: string, enabled: boolean, level: LogLevel): void {
166
+ this.config.modules[module] = {
167
+ enabled,
168
+ level: logLevelToString(level),
169
+ }
170
+
171
+ const logger = this.loggers.get(module)
172
+ if (logger) {
173
+ logger.setEnabled(this.config.enabled && enabled)
174
+ logger.setLevel(level)
175
+ }
176
+ }
177
+
178
+ /**
179
+ * List all registered loggers
180
+ */
181
+ listLoggers(): LoggerInfo[] {
182
+ return Array.from(this.loggers.entries()).map(([module, logger]) => ({
183
+ module,
184
+ enabled: logger.isEnabled(),
185
+ level: logger.getLevel(),
186
+ color: logger.getColor(),
187
+ }))
188
+ }
189
+
190
+ /**
191
+ * Get current configuration
192
+ */
193
+ getConfig(): LoggingConfig {
194
+ return { ...this.config }
195
+ }
196
+
197
+ /**
198
+ * Set configuration
199
+ */
200
+ setConfig(config: Partial<LoggingConfig>): void {
201
+ this.config = { ...this.config, ...config }
202
+ this.applyConfig()
203
+ }
204
+
205
+ /**
206
+ * Set config loader function
207
+ */
208
+ setConfigLoader(loader: () => Promise<LoggingConfig | null>): void {
209
+ this.configLoader = loader
210
+ }
211
+
212
+ /**
213
+ * Set config saver function
214
+ */
215
+ setConfigSaver(saver: (config: LoggingConfig) => Promise<void>): void {
216
+ this.configSaver = saver
217
+ }
218
+
219
+ /**
220
+ * Load configuration from storage
221
+ */
222
+ async loadConfig(): Promise<void> {
223
+ if (!this.configLoader)
224
+ return
225
+
226
+ try {
227
+ const loaded = await this.configLoader()
228
+ if (loaded) {
229
+ this.config = { ...DEFAULT_CONFIG, ...loaded }
230
+ this.applyConfig()
231
+ }
232
+ }
233
+ catch (error) {
234
+ console.error('[LoggerManager] Failed to load config:', error)
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Save configuration to storage
240
+ */
241
+ async saveConfig(): Promise<void> {
242
+ if (!this.configSaver)
243
+ return
244
+
245
+ try {
246
+ await this.configSaver(this.config)
247
+ }
248
+ catch (error) {
249
+ console.error('[LoggerManager] Failed to save config:', error)
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Apply current configuration to all loggers
255
+ */
256
+ private applyConfig(): void {
257
+ for (const [module, logger] of this.loggers) {
258
+ const moduleConfig = this.config.modules[module]
259
+ const defaults = MODULE_DEFAULTS[module]
260
+
261
+ // Determine enabled state
262
+ let enabled = this.config.enabled
263
+ if (moduleConfig?.enabled !== undefined) {
264
+ enabled = enabled && moduleConfig.enabled
265
+ }
266
+ else if (defaults?.enabled !== undefined) {
267
+ enabled = enabled && defaults.enabled
268
+ }
269
+
270
+ // Determine log level
271
+ let level = stringToLogLevel(this.config.globalLevel)
272
+ if (moduleConfig?.level) {
273
+ level = Math.max(level, stringToLogLevel(moduleConfig.level))
274
+ }
275
+ else if (defaults?.level !== undefined) {
276
+ level = Math.max(level, defaults.level)
277
+ }
278
+
279
+ logger.setEnabled(enabled)
280
+ logger.setLevel(level)
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Reset to default configuration
286
+ */
287
+ reset(): void {
288
+ this.config = { ...DEFAULT_CONFIG }
289
+ this.applyConfig()
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Singleton instance
295
+ */
296
+ export const loggerManager = LoggerManager.getInstance()
297
+
298
+ /**
299
+ * Shorthand for getting a logger
300
+ */
301
+ export function getLogger(module: string, options?: Partial<ModuleLoggerOptions>): ModuleLogger {
302
+ return loggerManager.getLogger(module, options)
303
+ }
@@ -0,0 +1,270 @@
1
+ /**
2
+ * ModuleLogger
3
+ *
4
+ * Provides structured, configurable logging for individual modules.
5
+ * Supports log levels, timing, grouping, and zero-overhead when disabled.
6
+ */
7
+
8
+ import type { ModuleLoggerOptions } from './types'
9
+ import { LogLevel } from './types'
10
+
11
+ /**
12
+ * ANSI color codes for terminal output
13
+ */
14
+ const COLORS: Record<string, string> = {
15
+ reset: '\x1B[0m',
16
+ gray: '\x1B[90m',
17
+ red: '\x1B[31m',
18
+ green: '\x1B[32m',
19
+ yellow: '\x1B[33m',
20
+ blue: '\x1B[34m',
21
+ magenta: '\x1B[35m',
22
+ cyan: '\x1B[36m',
23
+ white: '\x1B[37m',
24
+ bgRed: '\x1B[41m',
25
+ bgGreen: '\x1B[42m',
26
+ bgYellow: '\x1B[43m',
27
+ bgBlue: '\x1B[44m',
28
+ bgMagenta: '\x1B[45m',
29
+ bgCyan: '\x1B[46m',
30
+ bold: '\x1B[1m',
31
+ }
32
+
33
+ /**
34
+ * Level color mapping
35
+ */
36
+ const LEVEL_COLORS: Record<LogLevel, string> = {
37
+ [LogLevel.DEBUG]: 'gray',
38
+ [LogLevel.INFO]: 'blue',
39
+ [LogLevel.WARN]: 'yellow',
40
+ [LogLevel.ERROR]: 'red',
41
+ [LogLevel.NONE]: 'white',
42
+ }
43
+
44
+ /**
45
+ * Level labels
46
+ */
47
+ const LEVEL_LABELS: Record<LogLevel, string> = {
48
+ [LogLevel.DEBUG]: 'DEBUG',
49
+ [LogLevel.INFO]: 'INFO ',
50
+ [LogLevel.WARN]: 'WARN ',
51
+ [LogLevel.ERROR]: 'ERROR',
52
+ [LogLevel.NONE]: 'NONE ',
53
+ }
54
+
55
+ /**
56
+ * ModuleLogger class
57
+ *
58
+ * Provides logging capabilities with:
59
+ * - Log levels (debug, info, warn, error)
60
+ * - Enable/disable per module
61
+ * - Timing functions
62
+ * - Grouping support
63
+ * - Zero overhead when disabled
64
+ */
65
+ export class ModuleLogger {
66
+ private readonly module: string
67
+ private readonly color: string
68
+ private readonly prefix: string
69
+ private enabled: boolean
70
+ private level: LogLevel
71
+ private timers: Map<string, number> = new Map()
72
+ private groupDepth = 0
73
+
74
+ constructor(options: ModuleLoggerOptions) {
75
+ this.module = options.module
76
+ this.color = options.color ?? 'cyan'
77
+ this.prefix = options.prefix ?? ''
78
+ this.enabled = options.enabled ?? true
79
+ this.level = options.level ?? LogLevel.DEBUG
80
+ }
81
+
82
+ /**
83
+ * Check if logger is enabled
84
+ */
85
+ isEnabled(): boolean {
86
+ return this.enabled
87
+ }
88
+
89
+ /**
90
+ * Get current log level
91
+ */
92
+ getLevel(): LogLevel {
93
+ return this.level
94
+ }
95
+
96
+ /**
97
+ * Get module name
98
+ */
99
+ getModule(): string {
100
+ return this.module
101
+ }
102
+
103
+ /**
104
+ * Get color
105
+ */
106
+ getColor(): string {
107
+ return this.color
108
+ }
109
+
110
+ /**
111
+ * Set enabled state
112
+ */
113
+ setEnabled(enabled: boolean): void {
114
+ this.enabled = enabled
115
+ }
116
+
117
+ /**
118
+ * Set log level
119
+ */
120
+ setLevel(level: LogLevel): void {
121
+ this.level = level
122
+ }
123
+
124
+ /**
125
+ * Log debug message
126
+ */
127
+ debug(message: string, ...args: unknown[]): void {
128
+ this.log(LogLevel.DEBUG, message, ...args)
129
+ }
130
+
131
+ /**
132
+ * Log info message
133
+ */
134
+ info(message: string, ...args: unknown[]): void {
135
+ this.log(LogLevel.INFO, message, ...args)
136
+ }
137
+
138
+ /**
139
+ * Log warning message
140
+ */
141
+ warn(message: string, ...args: unknown[]): void {
142
+ this.log(LogLevel.WARN, message, ...args)
143
+ }
144
+
145
+ /**
146
+ * Log error message
147
+ */
148
+ error(message: string, ...args: unknown[]): void {
149
+ this.log(LogLevel.ERROR, message, ...args)
150
+ }
151
+
152
+ /**
153
+ * Start a timer
154
+ */
155
+ time(label: string): void {
156
+ if (!this.shouldLog(LogLevel.DEBUG))
157
+ return
158
+ this.timers.set(label, performance.now())
159
+ }
160
+
161
+ /**
162
+ * End a timer and log duration
163
+ */
164
+ timeEnd(label: string): number {
165
+ if (!this.shouldLog(LogLevel.DEBUG))
166
+ return 0
167
+ const start = this.timers.get(label)
168
+ if (start === undefined) {
169
+ this.warn(`Timer "${label}" does not exist`)
170
+ return 0
171
+ }
172
+ this.timers.delete(label)
173
+ const duration = performance.now() - start
174
+ this.debug(`${label}: ${duration.toFixed(2)}ms`)
175
+ return duration
176
+ }
177
+
178
+ /**
179
+ * Start a log group
180
+ */
181
+ group(label: string): void {
182
+ if (!this.shouldLog(LogLevel.DEBUG))
183
+ return
184
+ this.info(label)
185
+ this.groupDepth++
186
+ }
187
+
188
+ /**
189
+ * End a log group
190
+ */
191
+ groupEnd(): void {
192
+ if (this.groupDepth > 0) {
193
+ this.groupDepth--
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Create a child logger with a sub-module prefix
199
+ */
200
+ child(subModule: string): ModuleLogger {
201
+ return new ModuleLogger({
202
+ module: `${this.module}:${subModule}`,
203
+ color: this.color,
204
+ enabled: this.enabled,
205
+ level: this.level,
206
+ prefix: this.prefix,
207
+ })
208
+ }
209
+
210
+ /**
211
+ * Check if a level should be logged
212
+ */
213
+ private shouldLog(level: LogLevel): boolean {
214
+ return this.enabled && level >= this.level
215
+ }
216
+
217
+ /**
218
+ * Core logging method
219
+ */
220
+ private log(level: LogLevel, message: string, ...args: unknown[]): void {
221
+ if (!this.shouldLog(level))
222
+ return
223
+
224
+ const timestamp = this.formatTimestamp()
225
+ const levelLabel = LEVEL_LABELS[level]
226
+ const levelColor = COLORS[LEVEL_COLORS[level]] ?? ''
227
+ const moduleColor = COLORS[this.color] ?? ''
228
+ const reset = COLORS.reset
229
+
230
+ // Build indent for groups
231
+ const indent = ' '.repeat(this.groupDepth)
232
+
233
+ // Format: [HH:MM:SS.mmm] [module] LEVEL message
234
+ const formattedModule = `${moduleColor}[${this.module}]${reset}`
235
+ const formattedLevel = `${levelColor}${levelLabel}${reset}`
236
+ const formattedMessage = `${indent}${message}`
237
+
238
+ const output = `${COLORS.gray}[${timestamp}]${reset} ${formattedModule} ${formattedLevel} ${formattedMessage}`
239
+
240
+ // Use appropriate console method
241
+ switch (level) {
242
+ case LogLevel.DEBUG:
243
+ console.debug(output, ...args)
244
+ break
245
+ case LogLevel.INFO:
246
+ console.info(output, ...args)
247
+ break
248
+ case LogLevel.WARN:
249
+ console.warn(output, ...args)
250
+ break
251
+ case LogLevel.ERROR:
252
+ console.error(output, ...args)
253
+ break
254
+ default:
255
+ console.log(output, ...args)
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Format timestamp as HH:MM:SS.mmm
261
+ */
262
+ private formatTimestamp(): string {
263
+ const now = new Date()
264
+ const hours = now.getHours().toString().padStart(2, '0')
265
+ const minutes = now.getMinutes().toString().padStart(2, '0')
266
+ const seconds = now.getSeconds().toString().padStart(2, '0')
267
+ const ms = now.getMilliseconds().toString().padStart(3, '0')
268
+ return `${hours}:${minutes}:${seconds}.${ms}`
269
+ }
270
+ }