@ebowwa/crm 0.1.0

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 (187) hide show
  1. package/README.md +174 -0
  2. package/dist/cli/commands/activities.d.ts +11 -0
  3. package/dist/cli/commands/activities.d.ts.map +1 -0
  4. package/dist/cli/commands/activities.js +427 -0
  5. package/dist/cli/commands/activities.js.map +1 -0
  6. package/dist/cli/commands/contacts.d.ts +11 -0
  7. package/dist/cli/commands/contacts.d.ts.map +1 -0
  8. package/dist/cli/commands/contacts.js +458 -0
  9. package/dist/cli/commands/contacts.js.map +1 -0
  10. package/dist/cli/commands/deals.d.ts +11 -0
  11. package/dist/cli/commands/deals.d.ts.map +1 -0
  12. package/dist/cli/commands/deals.js +498 -0
  13. package/dist/cli/commands/deals.js.map +1 -0
  14. package/dist/cli/commands/media.d.ts +11 -0
  15. package/dist/cli/commands/media.d.ts.map +1 -0
  16. package/dist/cli/commands/media.js +417 -0
  17. package/dist/cli/commands/media.js.map +1 -0
  18. package/dist/cli/commands/search.d.ts +11 -0
  19. package/dist/cli/commands/search.d.ts.map +1 -0
  20. package/dist/cli/commands/search.js +346 -0
  21. package/dist/cli/commands/search.js.map +1 -0
  22. package/dist/cli/index.d.ts +13 -0
  23. package/dist/cli/index.d.ts.map +1 -0
  24. package/dist/cli/index.js +173 -0
  25. package/dist/cli/index.js.map +1 -0
  26. package/dist/cli/repl.d.ts +15 -0
  27. package/dist/cli/repl.d.ts.map +1 -0
  28. package/dist/cli/repl.js +318 -0
  29. package/dist/cli/repl.js.map +1 -0
  30. package/dist/cli/utils/config.d.ts +91 -0
  31. package/dist/cli/utils/config.d.ts.map +1 -0
  32. package/dist/cli/utils/config.js +212 -0
  33. package/dist/cli/utils/config.js.map +1 -0
  34. package/dist/cli/utils/output.d.ts +136 -0
  35. package/dist/cli/utils/output.d.ts.map +1 -0
  36. package/dist/cli/utils/output.js +323 -0
  37. package/dist/cli/utils/output.js.map +1 -0
  38. package/dist/cli/utils/prompt.d.ts +81 -0
  39. package/dist/cli/utils/prompt.d.ts.map +1 -0
  40. package/dist/cli/utils/prompt.js +341 -0
  41. package/dist/cli/utils/prompt.js.map +1 -0
  42. package/dist/cli.d.ts +3 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +8 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/core/index.d.ts +6 -0
  47. package/dist/core/index.d.ts.map +1 -0
  48. package/dist/core/index.js +32 -0
  49. package/dist/core/index.js.map +1 -0
  50. package/dist/core/schemas.d.ts +3050 -0
  51. package/dist/core/schemas.d.ts.map +1 -0
  52. package/dist/core/schemas.js +667 -0
  53. package/dist/core/schemas.js.map +1 -0
  54. package/dist/core/types.d.ts +597 -0
  55. package/dist/core/types.d.ts.map +1 -0
  56. package/dist/core/types.js +8 -0
  57. package/dist/core/types.js.map +1 -0
  58. package/dist/index.d.ts +7 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +8 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/mcp/index.d.ts +14 -0
  63. package/dist/mcp/index.d.ts.map +1 -0
  64. package/dist/mcp/index.js +11 -0
  65. package/dist/mcp/index.js.map +1 -0
  66. package/dist/mcp/server.d.ts +13 -0
  67. package/dist/mcp/server.d.ts.map +1 -0
  68. package/dist/mcp/server.js +18 -0
  69. package/dist/mcp/server.js.map +1 -0
  70. package/dist/mcp/storage/client.d.ts +109 -0
  71. package/dist/mcp/storage/client.d.ts.map +1 -0
  72. package/dist/mcp/storage/client.js +355 -0
  73. package/dist/mcp/storage/client.js.map +1 -0
  74. package/dist/mcp/storage/index.d.ts +7 -0
  75. package/dist/mcp/storage/index.d.ts.map +1 -0
  76. package/dist/mcp/storage/index.js +6 -0
  77. package/dist/mcp/storage/index.js.map +1 -0
  78. package/dist/mcp/storage/types.d.ts +44 -0
  79. package/dist/mcp/storage/types.d.ts.map +1 -0
  80. package/dist/mcp/storage/types.js +35 -0
  81. package/dist/mcp/storage/types.js.map +1 -0
  82. package/dist/mcp/tools/definitions.d.ts +16 -0
  83. package/dist/mcp/tools/definitions.d.ts.map +1 -0
  84. package/dist/mcp/tools/definitions.js +914 -0
  85. package/dist/mcp/tools/definitions.js.map +1 -0
  86. package/dist/mcp/tools/handlers.d.ts +50 -0
  87. package/dist/mcp/tools/handlers.d.ts.map +1 -0
  88. package/dist/mcp/tools/handlers.js +760 -0
  89. package/dist/mcp/tools/handlers.js.map +1 -0
  90. package/dist/mcp/tools/index.d.ts +7 -0
  91. package/dist/mcp/tools/index.d.ts.map +1 -0
  92. package/dist/mcp/tools/index.js +6 -0
  93. package/dist/mcp/tools/index.js.map +1 -0
  94. package/dist/mcp/tools/types.d.ts +314 -0
  95. package/dist/mcp/tools/types.d.ts.map +1 -0
  96. package/dist/mcp/tools/types.js +5 -0
  97. package/dist/mcp/tools/types.js.map +1 -0
  98. package/dist/mcp/transports/stdio.d.ts +27 -0
  99. package/dist/mcp/transports/stdio.d.ts.map +1 -0
  100. package/dist/mcp/transports/stdio.js +237 -0
  101. package/dist/mcp/transports/stdio.js.map +1 -0
  102. package/dist/telemetry/index.d.ts +58 -0
  103. package/dist/telemetry/index.d.ts.map +1 -0
  104. package/dist/telemetry/index.js +109 -0
  105. package/dist/telemetry/index.js.map +1 -0
  106. package/dist/telemetry/logger.d.ts +116 -0
  107. package/dist/telemetry/logger.d.ts.map +1 -0
  108. package/dist/telemetry/logger.js +256 -0
  109. package/dist/telemetry/logger.js.map +1 -0
  110. package/dist/telemetry/metrics.d.ts +115 -0
  111. package/dist/telemetry/metrics.d.ts.map +1 -0
  112. package/dist/telemetry/metrics.js +292 -0
  113. package/dist/telemetry/metrics.js.map +1 -0
  114. package/dist/telemetry/tracer.d.ts +227 -0
  115. package/dist/telemetry/tracer.d.ts.map +1 -0
  116. package/dist/telemetry/tracer.js +355 -0
  117. package/dist/telemetry/tracer.js.map +1 -0
  118. package/dist/web/app.d.ts +2 -0
  119. package/dist/web/app.d.ts.map +1 -0
  120. package/dist/web/app.js +115 -0
  121. package/dist/web/app.js.map +1 -0
  122. package/dist/web/components/ContactList.d.ts +3 -0
  123. package/dist/web/components/ContactList.d.ts.map +1 -0
  124. package/dist/web/components/ContactList.js +262 -0
  125. package/dist/web/components/ContactList.js.map +1 -0
  126. package/dist/web/components/Dashboard.d.ts +3 -0
  127. package/dist/web/components/Dashboard.d.ts.map +1 -0
  128. package/dist/web/components/Dashboard.js +158 -0
  129. package/dist/web/components/Dashboard.js.map +1 -0
  130. package/dist/web/components/DealPipeline.d.ts +3 -0
  131. package/dist/web/components/DealPipeline.d.ts.map +1 -0
  132. package/dist/web/components/DealPipeline.js +306 -0
  133. package/dist/web/components/DealPipeline.js.map +1 -0
  134. package/dist/web/index.d.ts +2 -0
  135. package/dist/web/index.d.ts.map +1 -0
  136. package/dist/web/index.js +269 -0
  137. package/dist/web/index.js.map +1 -0
  138. package/dist/web/types.d.ts +75 -0
  139. package/dist/web/types.d.ts.map +1 -0
  140. package/dist/web/types.js +3 -0
  141. package/dist/web/types.js.map +1 -0
  142. package/native/index.d.ts +571 -0
  143. package/native/index.js +687 -0
  144. package/package.json +105 -0
  145. package/src/cli/commands/activities.ts +543 -0
  146. package/src/cli/commands/contacts.ts +563 -0
  147. package/src/cli/commands/deals.ts +637 -0
  148. package/src/cli/commands/media.ts +521 -0
  149. package/src/cli/commands/search.ts +426 -0
  150. package/src/cli/index.ts +203 -0
  151. package/src/cli/repl.ts +379 -0
  152. package/src/cli/utils/config.ts +299 -0
  153. package/src/cli/utils/output.ts +386 -0
  154. package/src/cli/utils/prompt.ts +444 -0
  155. package/src/cli.ts +11 -0
  156. package/src/core/index.ts +184 -0
  157. package/src/core/schemas.ts +770 -0
  158. package/src/core/types.ts +969 -0
  159. package/src/index.ts +8 -0
  160. package/src/mcp/index.ts +17 -0
  161. package/src/mcp/server.ts +26 -0
  162. package/src/mcp/storage/client.ts +408 -0
  163. package/src/mcp/storage/index.ts +7 -0
  164. package/src/mcp/storage/types.ts +72 -0
  165. package/src/mcp/tools/definitions.ts +961 -0
  166. package/src/mcp/tools/handlers.ts +805 -0
  167. package/src/mcp/tools/index.ts +7 -0
  168. package/src/mcp/tools/types.ts +390 -0
  169. package/src/mcp/transports/stdio.ts +225 -0
  170. package/src/telemetry/index.ts +131 -0
  171. package/src/telemetry/logger.ts +318 -0
  172. package/src/telemetry/metrics.ts +393 -0
  173. package/src/telemetry/tracer.ts +487 -0
  174. package/src/web/api/activities.ts +41 -0
  175. package/src/web/api/contacts.ts +114 -0
  176. package/src/web/api/deals.ts +108 -0
  177. package/src/web/api/media.ts +98 -0
  178. package/src/web/app.tsx +143 -0
  179. package/src/web/components/ActivityFeed.tsx +195 -0
  180. package/src/web/components/ContactList.tsx +340 -0
  181. package/src/web/components/Dashboard.tsx +214 -0
  182. package/src/web/components/DealPipeline.tsx +405 -0
  183. package/src/web/components/MediaGallery.tsx +334 -0
  184. package/src/web/index.html +14 -0
  185. package/src/web/index.ts +326 -0
  186. package/src/web/styles/main.css +180 -0
  187. package/src/web/types.ts +311 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Telemetry module exports
3
+ *
4
+ * Provides unified access to logging, metrics, and tracing.
5
+ */
6
+
7
+ export { Logger, createLogger, logger, type LogLevel, type LogContext, type LogEntry, type LoggerConfig } from './logger.js';
8
+ export { MetricsRegistry, metrics, initializeCrmMetrics, type MetricType, type MetricLabel, type MetricValue, type MetricDefinition, type HistogramOptions } from './metrics.js';
9
+ export { Tracer, SpanHandle, tracer, createTracer, withSpan, type TraceContext, type SpanAttribute, type SpanEvent, type SpanLink, type SpanStatus, type Span, type TracerConfig } from './tracer.js';
10
+
11
+ /**
12
+ * Combined telemetry context for a request/operation
13
+ */
14
+ export class TelemetryContext {
15
+ public readonly logger: ReturnType<typeof logger.child>;
16
+ private span?: SpanHandle;
17
+ private timer?: () => number;
18
+
19
+ constructor(
20
+ public readonly operation: string,
21
+ context?: Record<string, unknown>
22
+ ) {
23
+ this.logger = logger.child({ operation, ...context });
24
+ }
25
+
26
+ /**
27
+ * Start telemetry tracking for an operation
28
+ */
29
+ start(labels?: Record<string, string>): void {
30
+ this.span = tracer.startSpan(this.operation, {
31
+ kind: 'internal',
32
+ attributes: Object.entries(labels ?? {}).map(([key, value]) => ({
33
+ key,
34
+ value,
35
+ })),
36
+ });
37
+ this.timer = metrics.startTimer('operation_duration_seconds', {
38
+ operation: this.operation,
39
+ ...labels,
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Add an event to the span
45
+ */
46
+ addEvent(name: string, attributes?: Record<string, unknown>): void {
47
+ this.span?.addEvent(name, attributes as Record<string, string | number | boolean>);
48
+ }
49
+
50
+ /**
51
+ * Set an attribute on the span
52
+ */
53
+ setAttribute(key: string, value: string | number | boolean): void {
54
+ this.span?.setAttribute(key, value);
55
+ }
56
+
57
+ /**
58
+ * Increment a metric
59
+ */
60
+ incrementMetric(name: string, value: number = 1, labels?: Record<string, string | number>): void {
61
+ metrics.increment(name, value, labels ?? {});
62
+ }
63
+
64
+ /**
65
+ * Mark the operation as successful and end tracking
66
+ */
67
+ success(message?: string): void {
68
+ if (message) {
69
+ this.logger.info(message);
70
+ }
71
+ this.span?.ok();
72
+ this.end();
73
+ }
74
+
75
+ /**
76
+ * Mark the operation as failed and end tracking
77
+ */
78
+ failure(error: Error | string): void {
79
+ const err = typeof error === 'string' ? new Error(error) : error;
80
+ this.logger.error(err.message, err);
81
+ this.span?.recordException(err);
82
+ this.end();
83
+ }
84
+
85
+ /**
86
+ * End telemetry tracking
87
+ */
88
+ private end(): void {
89
+ if (this.timer) {
90
+ const duration = this.timer();
91
+ this.span?.setAttribute('duration_ms', duration * 1000);
92
+ }
93
+ this.span?.end();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Create a telemetry context for an operation
99
+ */
100
+ export function createTelemetryContext(
101
+ operation: string,
102
+ context?: Record<string, unknown>
103
+ ): TelemetryContext {
104
+ const ctx = new TelemetryContext(operation, context);
105
+ ctx.start();
106
+ return ctx;
107
+ }
108
+
109
+ /**
110
+ * Wrap an async function with telemetry
111
+ */
112
+ export async function withTelemetry<T>(
113
+ operation: string,
114
+ fn: (ctx: TelemetryContext) => Promise<T>,
115
+ options?: {
116
+ context?: Record<string, unknown>;
117
+ labels?: Record<string, string>;
118
+ }
119
+ ): Promise<T> {
120
+ const ctx = new TelemetryContext(operation, options?.context);
121
+ ctx.start(options?.labels);
122
+
123
+ try {
124
+ const result = await fn(ctx);
125
+ ctx.success();
126
+ return result;
127
+ } catch (error) {
128
+ ctx.failure(error instanceof Error ? error : String(error));
129
+ throw error;
130
+ }
131
+ }
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Logger module for CRM system
3
+ *
4
+ * Provides structured logging with multiple log levels and formatters.
5
+ * Supports JSON output for production and pretty printing for development.
6
+ */
7
+
8
+ export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
9
+
10
+ export interface LogContext {
11
+ [key: string]: unknown;
12
+ }
13
+
14
+ export interface LogEntry {
15
+ timestamp: string;
16
+ level: LogLevel;
17
+ message: string;
18
+ context?: LogContext;
19
+ error?: {
20
+ name: string;
21
+ message: string;
22
+ stack?: string;
23
+ };
24
+ duration?: number;
25
+ traceId?: string;
26
+ spanId?: string;
27
+ }
28
+
29
+ export interface LoggerConfig {
30
+ level: LogLevel;
31
+ service: string;
32
+ version: string;
33
+ env: 'development' | 'production' | 'test';
34
+ prettyPrint?: boolean;
35
+ includeStackTrace?: boolean;
36
+ }
37
+
38
+ const LOG_LEVELS: Record<LogLevel, number> = {
39
+ trace: 0,
40
+ debug: 1,
41
+ info: 2,
42
+ warn: 3,
43
+ error: 4,
44
+ fatal: 5,
45
+ };
46
+
47
+ /**
48
+ * Structured logger with context support
49
+ */
50
+ export class Logger {
51
+ private readonly level: number;
52
+ private readonly config: LoggerConfig;
53
+ private readonly defaultContext: LogContext;
54
+
55
+ constructor(config: Partial<LoggerConfig> & { service: string }) {
56
+ this.config = {
57
+ level: config.level ?? (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
58
+ version: config.version ?? '0.1.0',
59
+ env: (config.env as LoggerConfig['env']) ?? (process.env.NODE_ENV as LoggerConfig['env']) ?? 'development',
60
+ prettyPrint: config.prettyPrint ?? process.env.LOG_PRETTY === 'true',
61
+ includeStackTrace: config.includeStackTrace ?? true,
62
+ ...config,
63
+ };
64
+ this.level = LOG_LEVELS[this.config.level];
65
+ this.defaultContext = {
66
+ service: this.config.service,
67
+ version: this.config.version,
68
+ env: this.config.env,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Create a child logger with additional context
74
+ */
75
+ child(context: LogContext): ChildLogger {
76
+ return new ChildLogger(this, { ...this.defaultContext, ...context });
77
+ }
78
+
79
+ /**
80
+ * Log at trace level (most verbose)
81
+ */
82
+ trace(message: string, context?: LogContext): void {
83
+ this.log('trace', message, context);
84
+ }
85
+
86
+ /**
87
+ * Log at debug level
88
+ */
89
+ debug(message: string, context?: LogContext): void {
90
+ this.log('debug', message, context);
91
+ }
92
+
93
+ /**
94
+ * Log at info level
95
+ */
96
+ info(message: string, context?: LogContext): void {
97
+ this.log('info', message, context);
98
+ }
99
+
100
+ /**
101
+ * Log at warn level
102
+ */
103
+ warn(message: string, context?: LogContext): void {
104
+ this.log('warn', message, context);
105
+ }
106
+
107
+ /**
108
+ * Log at error level
109
+ */
110
+ error(message: string, error?: Error | unknown, context?: LogContext): void {
111
+ const entry: LogEntry = this.createEntry('error', message, context);
112
+
113
+ if (error instanceof Error) {
114
+ entry.error = {
115
+ name: error.name,
116
+ message: error.message,
117
+ stack: this.config.includeStackTrace ? error.stack : undefined,
118
+ };
119
+ } else if (error !== undefined) {
120
+ entry.context = { ...entry.context, error: String(error) };
121
+ }
122
+
123
+ this.output(entry);
124
+ }
125
+
126
+ /**
127
+ * Log at fatal level (application should exit after this)
128
+ */
129
+ fatal(message: string, error?: Error | unknown, context?: LogContext): void {
130
+ const entry: LogEntry = this.createEntry('fatal', message, context);
131
+
132
+ if (error instanceof Error) {
133
+ entry.error = {
134
+ name: error.name,
135
+ message: error.message,
136
+ stack: this.config.includeStackTrace ? error.stack : undefined,
137
+ };
138
+ } else if (error !== undefined) {
139
+ entry.context = { ...entry.context, error: String(error) };
140
+ }
141
+
142
+ this.output(entry);
143
+ }
144
+
145
+ /**
146
+ * Log with timing information
147
+ */
148
+ time(message: string, durationMs: number, context?: LogContext): void {
149
+ const entry = this.createEntry('info', message, context);
150
+ entry.duration = durationMs;
151
+ this.output(entry);
152
+ }
153
+
154
+ /**
155
+ * Create a timer that logs duration when stopped
156
+ */
157
+ startTimer(message: string, context?: LogContext): () => number {
158
+ const start = performance.now();
159
+ return () => {
160
+ const duration = performance.now() - start;
161
+ this.time(message, duration, context);
162
+ return duration;
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Add trace context to logs
168
+ */
169
+ withTrace(traceId: string, spanId?: string): Logger {
170
+ const logger = new Logger(this.config);
171
+ (logger as unknown as { defaultContext: LogContext }).defaultContext = {
172
+ ...this.defaultContext,
173
+ traceId,
174
+ spanId,
175
+ };
176
+ return logger;
177
+ }
178
+
179
+ private log(level: LogLevel, message: string, context?: LogContext): void {
180
+ if (LOG_LEVELS[level] < this.level) {
181
+ return;
182
+ }
183
+
184
+ const entry = this.createEntry(level, message, context);
185
+ this.output(entry);
186
+ }
187
+
188
+ private createEntry(level: LogLevel, message: string, context?: LogContext): LogEntry {
189
+ const entry: LogEntry = {
190
+ timestamp: new Date().toISOString(),
191
+ level,
192
+ message,
193
+ context: { ...this.defaultContext, ...context },
194
+ };
195
+
196
+ return entry;
197
+ }
198
+
199
+ private output(entry: LogEntry): void {
200
+ if (this.config.prettyPrint && this.config.env !== 'production') {
201
+ this.prettyOutput(entry);
202
+ } else {
203
+ this.jsonOutput(entry);
204
+ }
205
+ }
206
+
207
+ private jsonOutput(entry: LogEntry): void {
208
+ const output = JSON.stringify(entry);
209
+
210
+ if (entry.level === 'fatal' || entry.level === 'error') {
211
+ console.error(output);
212
+ } else if (entry.level === 'warn') {
213
+ console.warn(output);
214
+ } else {
215
+ console.log(output);
216
+ }
217
+ }
218
+
219
+ private prettyOutput(entry: LogEntry): void {
220
+ const levelColors: Record<LogLevel, string> = {
221
+ trace: '\x1b[90m', // gray
222
+ debug: '\x1b[36m', // cyan
223
+ info: '\x1b[32m', // green
224
+ warn: '\x1b[33m', // yellow
225
+ error: '\x1b[31m', // red
226
+ fatal: '\x1b[35m', // magenta
227
+ };
228
+ const reset = '\x1b[0m';
229
+ const color = levelColors[entry.level];
230
+
231
+ const timestamp = entry.timestamp.split('T')[1]?.split('.')[0] ?? entry.timestamp;
232
+ const level = entry.level.toUpperCase().padEnd(5);
233
+
234
+ let output = `${color}[${timestamp}] ${level}${reset} ${entry.message}`;
235
+
236
+ if (entry.context && Object.keys(entry.context).length > 0) {
237
+ output += ` ${reset}\x1b[90m${JSON.stringify(entry.context)}\x1b[0m`;
238
+ }
239
+
240
+ if (entry.duration !== undefined) {
241
+ output += ` ${reset}\x1b[90m(${entry.duration.toFixed(2)}ms)\x1b[0m`;
242
+ }
243
+
244
+ if (entry.error) {
245
+ output += `\n \x1b[31m${entry.error.name}: ${entry.error.message}\x1b[0m`;
246
+ if (entry.error.stack && this.config.includeStackTrace) {
247
+ const stackLines = entry.error.stack.split('\n').slice(1, 5);
248
+ output += `\n \x1b[90m${stackLines.join('\n ')}\x1b[0m`;
249
+ }
250
+ }
251
+
252
+ if (entry.level === 'fatal' || entry.level === 'error') {
253
+ console.error(output);
254
+ } else if (entry.level === 'warn') {
255
+ console.warn(output);
256
+ } else {
257
+ console.log(output);
258
+ }
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Child logger with bound context
264
+ */
265
+ class ChildLogger {
266
+ constructor(
267
+ private readonly parent: Logger,
268
+ private readonly context: LogContext
269
+ ) {}
270
+
271
+ trace(message: string, additionalContext?: LogContext): void {
272
+ this.parent.trace(message, { ...this.context, ...additionalContext });
273
+ }
274
+
275
+ debug(message: string, additionalContext?: LogContext): void {
276
+ this.parent.debug(message, { ...this.context, ...additionalContext });
277
+ }
278
+
279
+ info(message: string, additionalContext?: LogContext): void {
280
+ this.parent.info(message, { ...this.context, ...additionalContext });
281
+ }
282
+
283
+ warn(message: string, additionalContext?: LogContext): void {
284
+ this.parent.warn(message, { ...this.context, ...additionalContext });
285
+ }
286
+
287
+ error(message: string, error?: Error | unknown, additionalContext?: LogContext): void {
288
+ this.parent.error(message, error, { ...this.context, ...additionalContext });
289
+ }
290
+
291
+ fatal(message: string, error?: Error | unknown, additionalContext?: LogContext): void {
292
+ this.parent.fatal(message, error, { ...this.context, ...additionalContext });
293
+ }
294
+
295
+ time(message: string, durationMs: number, additionalContext?: LogContext): void {
296
+ const stop = this.parent.startTimer(message, { ...this.context, ...additionalContext });
297
+ // Already logged by startTimer
298
+ }
299
+
300
+ startTimer(message: string, additionalContext?: LogContext): () => number {
301
+ return this.parent.startTimer(message, { ...this.context, ...additionalContext });
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Default logger instance
307
+ */
308
+ export const logger = new Logger({
309
+ service: 'crm',
310
+ version: '0.1.0',
311
+ });
312
+
313
+ /**
314
+ * Create a new logger instance
315
+ */
316
+ export function createLogger(config: Partial<LoggerConfig> & { service: string }): Logger {
317
+ return new Logger(config);
318
+ }