@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,256 @@
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
+ const LOG_LEVELS = {
8
+ trace: 0,
9
+ debug: 1,
10
+ info: 2,
11
+ warn: 3,
12
+ error: 4,
13
+ fatal: 5,
14
+ };
15
+ /**
16
+ * Structured logger with context support
17
+ */
18
+ export class Logger {
19
+ level;
20
+ config;
21
+ defaultContext;
22
+ constructor(config) {
23
+ this.config = {
24
+ level: config.level ?? (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
25
+ version: config.version ?? '0.1.0',
26
+ env: config.env ?? process.env.NODE_ENV ?? 'development',
27
+ prettyPrint: config.prettyPrint ?? process.env.LOG_PRETTY === 'true',
28
+ includeStackTrace: config.includeStackTrace ?? true,
29
+ ...config,
30
+ };
31
+ this.level = LOG_LEVELS[this.config.level];
32
+ this.defaultContext = {
33
+ service: this.config.service,
34
+ version: this.config.version,
35
+ env: this.config.env,
36
+ };
37
+ }
38
+ /**
39
+ * Create a child logger with additional context
40
+ */
41
+ child(context) {
42
+ return new ChildLogger(this, { ...this.defaultContext, ...context });
43
+ }
44
+ /**
45
+ * Log at trace level (most verbose)
46
+ */
47
+ trace(message, context) {
48
+ this.log('trace', message, context);
49
+ }
50
+ /**
51
+ * Log at debug level
52
+ */
53
+ debug(message, context) {
54
+ this.log('debug', message, context);
55
+ }
56
+ /**
57
+ * Log at info level
58
+ */
59
+ info(message, context) {
60
+ this.log('info', message, context);
61
+ }
62
+ /**
63
+ * Log at warn level
64
+ */
65
+ warn(message, context) {
66
+ this.log('warn', message, context);
67
+ }
68
+ /**
69
+ * Log at error level
70
+ */
71
+ error(message, error, context) {
72
+ const entry = this.createEntry('error', message, context);
73
+ if (error instanceof Error) {
74
+ entry.error = {
75
+ name: error.name,
76
+ message: error.message,
77
+ stack: this.config.includeStackTrace ? error.stack : undefined,
78
+ };
79
+ }
80
+ else if (error !== undefined) {
81
+ entry.context = { ...entry.context, error: String(error) };
82
+ }
83
+ this.output(entry);
84
+ }
85
+ /**
86
+ * Log at fatal level (application should exit after this)
87
+ */
88
+ fatal(message, error, context) {
89
+ const entry = this.createEntry('fatal', message, context);
90
+ if (error instanceof Error) {
91
+ entry.error = {
92
+ name: error.name,
93
+ message: error.message,
94
+ stack: this.config.includeStackTrace ? error.stack : undefined,
95
+ };
96
+ }
97
+ else if (error !== undefined) {
98
+ entry.context = { ...entry.context, error: String(error) };
99
+ }
100
+ this.output(entry);
101
+ }
102
+ /**
103
+ * Log with timing information
104
+ */
105
+ time(message, durationMs, context) {
106
+ const entry = this.createEntry('info', message, context);
107
+ entry.duration = durationMs;
108
+ this.output(entry);
109
+ }
110
+ /**
111
+ * Create a timer that logs duration when stopped
112
+ */
113
+ startTimer(message, context) {
114
+ const start = performance.now();
115
+ return () => {
116
+ const duration = performance.now() - start;
117
+ this.time(message, duration, context);
118
+ return duration;
119
+ };
120
+ }
121
+ /**
122
+ * Add trace context to logs
123
+ */
124
+ withTrace(traceId, spanId) {
125
+ const logger = new Logger(this.config);
126
+ logger.defaultContext = {
127
+ ...this.defaultContext,
128
+ traceId,
129
+ spanId,
130
+ };
131
+ return logger;
132
+ }
133
+ log(level, message, context) {
134
+ if (LOG_LEVELS[level] < this.level) {
135
+ return;
136
+ }
137
+ const entry = this.createEntry(level, message, context);
138
+ this.output(entry);
139
+ }
140
+ createEntry(level, message, context) {
141
+ const entry = {
142
+ timestamp: new Date().toISOString(),
143
+ level,
144
+ message,
145
+ context: { ...this.defaultContext, ...context },
146
+ };
147
+ return entry;
148
+ }
149
+ output(entry) {
150
+ if (this.config.prettyPrint && this.config.env !== 'production') {
151
+ this.prettyOutput(entry);
152
+ }
153
+ else {
154
+ this.jsonOutput(entry);
155
+ }
156
+ }
157
+ jsonOutput(entry) {
158
+ const output = JSON.stringify(entry);
159
+ if (entry.level === 'fatal' || entry.level === 'error') {
160
+ console.error(output);
161
+ }
162
+ else if (entry.level === 'warn') {
163
+ console.warn(output);
164
+ }
165
+ else {
166
+ console.log(output);
167
+ }
168
+ }
169
+ prettyOutput(entry) {
170
+ const levelColors = {
171
+ trace: '\x1b[90m', // gray
172
+ debug: '\x1b[36m', // cyan
173
+ info: '\x1b[32m', // green
174
+ warn: '\x1b[33m', // yellow
175
+ error: '\x1b[31m', // red
176
+ fatal: '\x1b[35m', // magenta
177
+ };
178
+ const reset = '\x1b[0m';
179
+ const color = levelColors[entry.level];
180
+ const timestamp = entry.timestamp.split('T')[1]?.split('.')[0] ?? entry.timestamp;
181
+ const level = entry.level.toUpperCase().padEnd(5);
182
+ let output = `${color}[${timestamp}] ${level}${reset} ${entry.message}`;
183
+ if (entry.context && Object.keys(entry.context).length > 0) {
184
+ output += ` ${reset}\x1b[90m${JSON.stringify(entry.context)}\x1b[0m`;
185
+ }
186
+ if (entry.duration !== undefined) {
187
+ output += ` ${reset}\x1b[90m(${entry.duration.toFixed(2)}ms)\x1b[0m`;
188
+ }
189
+ if (entry.error) {
190
+ output += `\n \x1b[31m${entry.error.name}: ${entry.error.message}\x1b[0m`;
191
+ if (entry.error.stack && this.config.includeStackTrace) {
192
+ const stackLines = entry.error.stack.split('\n').slice(1, 5);
193
+ output += `\n \x1b[90m${stackLines.join('\n ')}\x1b[0m`;
194
+ }
195
+ }
196
+ if (entry.level === 'fatal' || entry.level === 'error') {
197
+ console.error(output);
198
+ }
199
+ else if (entry.level === 'warn') {
200
+ console.warn(output);
201
+ }
202
+ else {
203
+ console.log(output);
204
+ }
205
+ }
206
+ }
207
+ /**
208
+ * Child logger with bound context
209
+ */
210
+ class ChildLogger {
211
+ parent;
212
+ context;
213
+ constructor(parent, context) {
214
+ this.parent = parent;
215
+ this.context = context;
216
+ }
217
+ trace(message, additionalContext) {
218
+ this.parent.trace(message, { ...this.context, ...additionalContext });
219
+ }
220
+ debug(message, additionalContext) {
221
+ this.parent.debug(message, { ...this.context, ...additionalContext });
222
+ }
223
+ info(message, additionalContext) {
224
+ this.parent.info(message, { ...this.context, ...additionalContext });
225
+ }
226
+ warn(message, additionalContext) {
227
+ this.parent.warn(message, { ...this.context, ...additionalContext });
228
+ }
229
+ error(message, error, additionalContext) {
230
+ this.parent.error(message, error, { ...this.context, ...additionalContext });
231
+ }
232
+ fatal(message, error, additionalContext) {
233
+ this.parent.fatal(message, error, { ...this.context, ...additionalContext });
234
+ }
235
+ time(message, durationMs, additionalContext) {
236
+ const stop = this.parent.startTimer(message, { ...this.context, ...additionalContext });
237
+ // Already logged by startTimer
238
+ }
239
+ startTimer(message, additionalContext) {
240
+ return this.parent.startTimer(message, { ...this.context, ...additionalContext });
241
+ }
242
+ }
243
+ /**
244
+ * Default logger instance
245
+ */
246
+ export const logger = new Logger({
247
+ service: 'crm',
248
+ version: '0.1.0',
249
+ });
250
+ /**
251
+ * Create a new logger instance
252
+ */
253
+ export function createLogger(config) {
254
+ return new Logger(config);
255
+ }
256
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/telemetry/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Metrics module for CRM system
3
+ *
4
+ * Provides a simple metrics collection system with counters, gauges, and histograms.
5
+ * Supports exporting metrics in Prometheus format.
6
+ */
7
+ export type MetricType = 'counter' | 'gauge' | 'histogram';
8
+ export interface MetricLabel {
9
+ [key: string]: string | number;
10
+ }
11
+ export interface MetricValue {
12
+ value: number;
13
+ timestamp: number;
14
+ labels: MetricLabel;
15
+ }
16
+ export interface MetricDefinition {
17
+ name: string;
18
+ type: MetricType;
19
+ description: string;
20
+ unit?: string;
21
+ }
22
+ export interface HistogramOptions {
23
+ buckets?: number[];
24
+ }
25
+ interface CounterMetric extends MetricDefinition {
26
+ type: 'counter';
27
+ values: MetricValue[];
28
+ }
29
+ interface GaugeMetric extends MetricDefinition {
30
+ type: 'gauge';
31
+ values: MetricValue[];
32
+ }
33
+ interface HistogramMetric extends MetricDefinition {
34
+ type: 'histogram';
35
+ values: {
36
+ sum: number;
37
+ count: number;
38
+ buckets: {
39
+ boundary: number;
40
+ count: number;
41
+ }[];
42
+ timestamp: number;
43
+ labels: MetricLabel;
44
+ }[];
45
+ options: HistogramOptions;
46
+ }
47
+ type Metric = CounterMetric | GaugeMetric | HistogramMetric;
48
+ /**
49
+ * Metrics registry for collecting and exporting metrics
50
+ */
51
+ export declare class MetricsRegistry {
52
+ private readonly metrics;
53
+ private readonly prefix;
54
+ constructor(prefix?: string);
55
+ /**
56
+ * Register a counter metric
57
+ */
58
+ registerCounter(name: string, description: string, unit?: string): void;
59
+ /**
60
+ * Register a gauge metric
61
+ */
62
+ registerGauge(name: string, description: string, unit?: string): void;
63
+ /**
64
+ * Register a histogram metric
65
+ */
66
+ registerHistogram(name: string, description: string, unit?: string, options?: HistogramOptions): void;
67
+ /**
68
+ * Increment a counter
69
+ */
70
+ increment(name: string, value?: number, labels?: MetricLabel): void;
71
+ /**
72
+ * Decrement a counter (useful for error tracking)
73
+ */
74
+ decrement(name: string, value?: number, labels?: MetricLabel): void;
75
+ /**
76
+ * Set a gauge value
77
+ */
78
+ gauge(name: string, value: number, labels?: MetricLabel): void;
79
+ /**
80
+ * Observe a value for histogram
81
+ */
82
+ observe(name: string, value: number, labels?: MetricLabel): void;
83
+ /**
84
+ * Create a timer that records duration in a histogram
85
+ */
86
+ startTimer(name: string, labels?: MetricLabel): () => number;
87
+ /**
88
+ * Get all metrics
89
+ */
90
+ getMetrics(): Metric[];
91
+ /**
92
+ * Export metrics in Prometheus text format
93
+ */
94
+ exportPrometheus(): string;
95
+ /**
96
+ * Reset all metrics
97
+ */
98
+ reset(): void;
99
+ /**
100
+ * Get metric by name
101
+ */
102
+ getMetric(name: string): Metric | undefined;
103
+ private labelsMatch;
104
+ private formatLabels;
105
+ }
106
+ /**
107
+ * Default metrics registry
108
+ */
109
+ export declare const metrics: MetricsRegistry;
110
+ /**
111
+ * Pre-registered CRM metrics
112
+ */
113
+ export declare function initializeCrmMetrics(registry?: MetricsRegistry): void;
114
+ export {};
115
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,UAAU,aAAc,SAAQ,gBAAgB;IAC9C,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,UAAU,WAAY,SAAQ,gBAAgB;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,UAAU,eAAgB,SAAQ,gBAAgB;IAChD,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,WAAW,CAAC;KACrB,EAAE,CAAC;IACJ,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,KAAK,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,eAAe,CAAC;AAO5D;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,GAAE,MAAe;IAInC;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAevE;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAerE;;OAEG;IACH,iBAAiB,CACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,IAAI;IAgBP;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAAE,MAAM,GAAE,WAAgB,GAAG,IAAI;IA4B1E;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAAE,MAAM,GAAE,WAAgB,GAAG,IAAI;IAI1E;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB,GAAG,IAAI;IA4BlE;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB,GAAG,IAAI;IA0CpE;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB,GAAG,MAAM,MAAM;IAWhE;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAItB;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAyC1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3C,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,YAAY;CAWrB;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,iBAA8B,CAAC;AAEnD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,eAAyB,GAAG,IAAI,CA2B9E"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Metrics module for CRM system
3
+ *
4
+ * Provides a simple metrics collection system with counters, gauges, and histograms.
5
+ * Supports exporting metrics in Prometheus format.
6
+ */
7
+ /**
8
+ * Default histogram buckets (in seconds for latency)
9
+ */
10
+ const DEFAULT_BUCKETS = [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
11
+ /**
12
+ * Metrics registry for collecting and exporting metrics
13
+ */
14
+ export class MetricsRegistry {
15
+ metrics = new Map();
16
+ prefix;
17
+ constructor(prefix = 'crm_') {
18
+ this.prefix = prefix;
19
+ }
20
+ /**
21
+ * Register a counter metric
22
+ */
23
+ registerCounter(name, description, unit) {
24
+ const metricName = this.prefix + name;
25
+ if (this.metrics.has(metricName)) {
26
+ throw new Error(`Metric ${metricName} already registered`);
27
+ }
28
+ this.metrics.set(metricName, {
29
+ name: metricName,
30
+ type: 'counter',
31
+ description,
32
+ unit,
33
+ values: [],
34
+ });
35
+ }
36
+ /**
37
+ * Register a gauge metric
38
+ */
39
+ registerGauge(name, description, unit) {
40
+ const metricName = this.prefix + name;
41
+ if (this.metrics.has(metricName)) {
42
+ throw new Error(`Metric ${metricName} already registered`);
43
+ }
44
+ this.metrics.set(metricName, {
45
+ name: metricName,
46
+ type: 'gauge',
47
+ description,
48
+ unit,
49
+ values: [],
50
+ });
51
+ }
52
+ /**
53
+ * Register a histogram metric
54
+ */
55
+ registerHistogram(name, description, unit, options) {
56
+ const metricName = this.prefix + name;
57
+ if (this.metrics.has(metricName)) {
58
+ throw new Error(`Metric ${metricName} already registered`);
59
+ }
60
+ this.metrics.set(metricName, {
61
+ name: metricName,
62
+ type: 'histogram',
63
+ description,
64
+ unit,
65
+ options: { buckets: options?.buckets ?? DEFAULT_BUCKETS },
66
+ values: [],
67
+ });
68
+ }
69
+ /**
70
+ * Increment a counter
71
+ */
72
+ increment(name, value = 1, labels = {}) {
73
+ const metricName = this.prefix + name;
74
+ const metric = this.metrics.get(metricName);
75
+ if (!metric) {
76
+ throw new Error(`Metric ${metricName} not found`);
77
+ }
78
+ if (metric.type !== 'counter') {
79
+ throw new Error(`Metric ${metricName} is not a counter`);
80
+ }
81
+ const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
82
+ if (existingIndex >= 0) {
83
+ metric.values[existingIndex].value += value;
84
+ metric.values[existingIndex].timestamp = Date.now();
85
+ }
86
+ else {
87
+ metric.values.push({
88
+ value,
89
+ timestamp: Date.now(),
90
+ labels,
91
+ });
92
+ }
93
+ }
94
+ /**
95
+ * Decrement a counter (useful for error tracking)
96
+ */
97
+ decrement(name, value = 1, labels = {}) {
98
+ this.increment(name, -value, labels);
99
+ }
100
+ /**
101
+ * Set a gauge value
102
+ */
103
+ gauge(name, value, labels = {}) {
104
+ const metricName = this.prefix + name;
105
+ const metric = this.metrics.get(metricName);
106
+ if (!metric) {
107
+ throw new Error(`Metric ${metricName} not found`);
108
+ }
109
+ if (metric.type !== 'gauge') {
110
+ throw new Error(`Metric ${metricName} is not a gauge`);
111
+ }
112
+ const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
113
+ if (existingIndex >= 0) {
114
+ metric.values[existingIndex].value = value;
115
+ metric.values[existingIndex].timestamp = Date.now();
116
+ }
117
+ else {
118
+ metric.values.push({
119
+ value,
120
+ timestamp: Date.now(),
121
+ labels,
122
+ });
123
+ }
124
+ }
125
+ /**
126
+ * Observe a value for histogram
127
+ */
128
+ observe(name, value, labels = {}) {
129
+ const metricName = this.prefix + name;
130
+ const metric = this.metrics.get(metricName);
131
+ if (!metric) {
132
+ throw new Error(`Metric ${metricName} not found`);
133
+ }
134
+ if (metric.type !== 'histogram') {
135
+ throw new Error(`Metric ${metricName} is not a histogram`);
136
+ }
137
+ const existingIndex = metric.values.findIndex(v => this.labelsMatch(v.labels, labels));
138
+ if (existingIndex >= 0) {
139
+ const existing = metric.values[existingIndex];
140
+ existing.sum += value;
141
+ existing.count += 1;
142
+ for (const bucket of existing.buckets) {
143
+ if (value <= bucket.boundary) {
144
+ bucket.count += 1;
145
+ }
146
+ }
147
+ existing.timestamp = Date.now();
148
+ }
149
+ else {
150
+ const buckets = metric.options.buckets ?? DEFAULT_BUCKETS;
151
+ metric.values.push({
152
+ sum: value,
153
+ count: 1,
154
+ buckets: buckets.map(boundary => ({
155
+ boundary,
156
+ count: value <= boundary ? 1 : 0,
157
+ })),
158
+ timestamp: Date.now(),
159
+ labels,
160
+ });
161
+ }
162
+ }
163
+ /**
164
+ * Create a timer that records duration in a histogram
165
+ */
166
+ startTimer(name, labels = {}) {
167
+ const start = process.hrtime.bigint();
168
+ return () => {
169
+ const end = process.hrtime.bigint();
170
+ const durationSeconds = Number(end - start) / 1e9;
171
+ this.observe(name, durationSeconds, labels);
172
+ return durationSeconds;
173
+ };
174
+ }
175
+ /**
176
+ * Get all metrics
177
+ */
178
+ getMetrics() {
179
+ return Array.from(this.metrics.values());
180
+ }
181
+ /**
182
+ * Export metrics in Prometheus text format
183
+ */
184
+ exportPrometheus() {
185
+ const lines = [];
186
+ for (const metric of this.metrics.values()) {
187
+ // Add help and type comments
188
+ lines.push(`# HELP ${metric.name} ${metric.description}`);
189
+ lines.push(`# TYPE ${metric.name} ${metric.type}`);
190
+ if (metric.type === 'counter' || metric.type === 'gauge') {
191
+ for (const value of metric.values) {
192
+ const labelStr = this.formatLabels(value.labels);
193
+ lines.push(`${metric.name}${labelStr} ${value.value}`);
194
+ }
195
+ }
196
+ else if (metric.type === 'histogram') {
197
+ for (const value of metric.values) {
198
+ const labelStr = this.formatLabels(value.labels);
199
+ // Bucket counts
200
+ for (const bucket of value.buckets) {
201
+ const bucketLabels = { ...value.labels, le: bucket.boundary.toString() };
202
+ const bucketLabelStr = this.formatLabels(bucketLabels);
203
+ lines.push(`${metric.name}_bucket${bucketLabelStr} ${bucket.count}`);
204
+ }
205
+ // +Inf bucket (same as count)
206
+ const infLabels = { ...value.labels, le: '+Inf' };
207
+ const infLabelStr = this.formatLabels(infLabels);
208
+ lines.push(`${metric.name}_bucket${infLabelStr} ${value.count}`);
209
+ // Sum and count
210
+ lines.push(`${metric.name}_sum${labelStr} ${value.sum}`);
211
+ lines.push(`${metric.name}_count${labelStr} ${value.count}`);
212
+ }
213
+ }
214
+ lines.push(''); // Empty line between metrics
215
+ }
216
+ return lines.join('\n');
217
+ }
218
+ /**
219
+ * Reset all metrics
220
+ */
221
+ reset() {
222
+ for (const metric of this.metrics.values()) {
223
+ if (metric.type === 'histogram') {
224
+ metric.values = [];
225
+ }
226
+ else {
227
+ metric.values = [];
228
+ }
229
+ }
230
+ }
231
+ /**
232
+ * Get metric by name
233
+ */
234
+ getMetric(name) {
235
+ return this.metrics.get(this.prefix + name);
236
+ }
237
+ labelsMatch(a, b) {
238
+ const keysA = Object.keys(a).sort();
239
+ const keysB = Object.keys(b).sort();
240
+ if (keysA.length !== keysB.length)
241
+ return false;
242
+ return keysA.every((key, i) => {
243
+ if (key !== keysB[i])
244
+ return false;
245
+ return a[key] === b[key];
246
+ });
247
+ }
248
+ formatLabels(labels) {
249
+ const entries = Object.entries(labels);
250
+ if (entries.length === 0)
251
+ return '';
252
+ const formatted = entries.map(([key, value]) => {
253
+ const escapedValue = String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
254
+ return `${key}="${escapedValue}"`;
255
+ });
256
+ return `{${formatted.join(',')}}`;
257
+ }
258
+ }
259
+ /**
260
+ * Default metrics registry
261
+ */
262
+ export const metrics = new MetricsRegistry('crm_');
263
+ /**
264
+ * Pre-registered CRM metrics
265
+ */
266
+ export function initializeCrmMetrics(registry = metrics) {
267
+ // Contact metrics
268
+ registry.registerCounter('contacts_created_total', 'Total number of contacts created');
269
+ registry.registerCounter('contacts_updated_total', 'Total number of contacts updated');
270
+ registry.registerCounter('contacts_deleted_total', 'Total number of contacts deleted');
271
+ registry.registerGauge('contacts_active_count', 'Current number of active contacts');
272
+ // Deal metrics
273
+ registry.registerCounter('deals_created_total', 'Total number of deals created');
274
+ registry.registerCounter('deals_won_total', 'Total number of deals won');
275
+ registry.registerCounter('deals_lost_total', 'Total number of deals lost');
276
+ registry.registerGauge('deals_active_count', 'Current number of active deals');
277
+ registry.registerGauge('deals_pipeline_value', 'Total value of deals in pipeline', 'USD');
278
+ // Activity metrics
279
+ registry.registerCounter('activities_created_total', 'Total number of activities created');
280
+ registry.registerCounter('activities_completed_total', 'Total number of activities completed');
281
+ registry.registerGauge('activities_pending_count', 'Current number of pending activities');
282
+ // API metrics
283
+ registry.registerHistogram('api_request_duration_seconds', 'API request duration in seconds');
284
+ registry.registerCounter('api_requests_total', 'Total number of API requests');
285
+ registry.registerCounter('api_errors_total', 'Total number of API errors');
286
+ // Search metrics
287
+ registry.registerHistogram('search_duration_seconds', 'Search query duration in seconds');
288
+ registry.registerCounter('search_queries_total', 'Total number of search queries');
289
+ }
290
+ // Initialize default metrics
291
+ initializeCrmMetrics();
292
+ //# sourceMappingURL=metrics.js.map