@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,687 @@
1
+ /**
2
+ * CRM Native Module Loader
3
+ *
4
+ * Loads the native Rust module for high-performance CRM operations.
5
+ * Provides fallback implementations if native module is not available.
6
+ */
7
+
8
+ const { platform, arch } = process;
9
+
10
+ // Platform-specific binary names
11
+ const PLATFORM_BINARIES = {
12
+ 'darwin-arm64': 'crm-native.darwin-arm64.node',
13
+ 'darwin-x64': 'crm-native.darwin-x64.node',
14
+ 'linux-arm64': 'crm-native.linux-arm64.node',
15
+ 'linux-x64': 'crm-native.linux-x64.node',
16
+ 'win32-x64': 'crm-native.win32-x64.node',
17
+ 'win32-ia32': 'crm-native.win32-ia32.node',
18
+ };
19
+
20
+ /**
21
+ * Try to load the native module
22
+ */
23
+ function loadNativeModule() {
24
+ const platformKey = `${platform}-${arch}`;
25
+ const binaryName = PLATFORM_BINARIES[platformKey];
26
+
27
+ if (!binaryName) {
28
+ console.warn(`[crm-native] Unsupported platform: ${platformKey}`);
29
+ return null;
30
+ }
31
+
32
+ try {
33
+ // Try to load the native binary
34
+ const native = require(`./${binaryName}`);
35
+ return native;
36
+ } catch (err) {
37
+ console.warn(`[crm-native] Failed to load native module: ${err.message}`);
38
+ return null;
39
+ }
40
+ }
41
+
42
+ // Load native module or use fallbacks
43
+ const native = loadNativeModule();
44
+
45
+ // ============================================================================
46
+ // Search Index
47
+ // ============================================================================
48
+
49
+ /**
50
+ * CRM Search Index for full-text search
51
+ */
52
+ export class CrmSearchIndex {
53
+ constructor(indexPath) {
54
+ if (native?.CrmSearchIndex) {
55
+ this._native = new native.CrmSearchIndex(indexPath);
56
+ } else {
57
+ // Fallback implementation
58
+ this._indexPath = indexPath;
59
+ this._contacts = new Map();
60
+ this._deals = new Map();
61
+ this._companies = new Map();
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Execute a search query
67
+ */
68
+ search(options) {
69
+ if (this._native) {
70
+ return this._native.search(options);
71
+ }
72
+ return this._searchFallback(options);
73
+ }
74
+
75
+ /**
76
+ * Add a document to the index
77
+ */
78
+ addDocument(doc) {
79
+ if (this._native) {
80
+ return this._native.addDocument(doc);
81
+ }
82
+ this._addDocumentFallback(doc);
83
+ }
84
+
85
+ /**
86
+ * Remove a document from the index
87
+ */
88
+ removeDocument(id) {
89
+ if (this._native) {
90
+ return this._native.removeDocument(id);
91
+ }
92
+ this._contacts.delete(id);
93
+ this._deals.delete(id);
94
+ this._companies.delete(id);
95
+ }
96
+
97
+ /**
98
+ * Commit pending changes
99
+ */
100
+ commit() {
101
+ if (this._native) {
102
+ return this._native.commit();
103
+ }
104
+ // No-op for fallback
105
+ }
106
+
107
+ /**
108
+ * Get index statistics
109
+ */
110
+ getStats() {
111
+ if (this._native) {
112
+ return this._native.getStats();
113
+ }
114
+ return {
115
+ contactCount: this._contacts.size,
116
+ dealCount: this._deals.size,
117
+ companyCount: this._companies.size,
118
+ };
119
+ }
120
+
121
+ // Fallback implementations
122
+ _searchFallback(options) {
123
+ const results = [];
124
+ const query = (options.query || '').toLowerCase();
125
+ const limit = options.limit || 20;
126
+ const offset = options.offset || 0;
127
+ const filterTags = options.tags || [];
128
+
129
+ // Search all entity types
130
+ const searchIn = options.entityTypes || ['contact', 'deal', 'company'];
131
+
132
+ for (const entityType of searchIn) {
133
+ const entities = this._getEntitiesByType(entityType);
134
+
135
+ for (const [id, entity] of entities) {
136
+ // Filter by tags if specified
137
+ if (filterTags.length > 0) {
138
+ const entityTags = entity.tags || [];
139
+ const hasAllTags = filterTags.every(tag =>
140
+ entityTags.some(et => et.toLowerCase() === tag.toLowerCase())
141
+ );
142
+ if (!hasAllTags) continue;
143
+ }
144
+
145
+ const score = query ? this._calculateScore(query, entity) : 1;
146
+ if (score > 0) {
147
+ results.push({ id, entityType, score, ...entity });
148
+ }
149
+ }
150
+ }
151
+
152
+ // Sort by score descending
153
+ results.sort((a, b) => b.score - a.score);
154
+
155
+ // Paginate
156
+ return results.slice(offset, offset + limit);
157
+ }
158
+
159
+ _getEntitiesByType(type) {
160
+ switch (type) {
161
+ case 'contact': return this._contacts;
162
+ case 'deal': return this._deals;
163
+ case 'company': return this._companies;
164
+ default: return new Map();
165
+ }
166
+ }
167
+
168
+ _addDocumentFallback(doc) {
169
+ const entityMap = this._getEntitiesByType(doc.entityType);
170
+ if (entityMap) {
171
+ entityMap.set(doc.id, doc);
172
+ }
173
+ }
174
+
175
+ _calculateScore(query, entity) {
176
+ if (!query) return 0;
177
+
178
+ let score = 0;
179
+ const queryTerms = query.toLowerCase().split(/\s+/);
180
+
181
+ // Search in name/title
182
+ const name = (entity.name || entity.title || '').toLowerCase();
183
+ for (const term of queryTerms) {
184
+ if (name.includes(term)) {
185
+ score += 10;
186
+ if (name.startsWith(term)) {
187
+ score += 5;
188
+ }
189
+ }
190
+ }
191
+
192
+ // Search in tags
193
+ const tags = entity.tags || [];
194
+ for (const tag of tags) {
195
+ for (const term of queryTerms) {
196
+ if (tag.toLowerCase().includes(term)) {
197
+ score += 5;
198
+ }
199
+ }
200
+ }
201
+
202
+ // Search in notes
203
+ const notes = (entity.notes || '').toLowerCase();
204
+ for (const term of queryTerms) {
205
+ if (notes.includes(term)) {
206
+ score += 2;
207
+ }
208
+ }
209
+
210
+ return score;
211
+ }
212
+ }
213
+
214
+ // ============================================================================
215
+ // Index Manager
216
+ // ============================================================================
217
+
218
+ /**
219
+ * CRM Index Manager for CRUD operations
220
+ */
221
+ export class CrmIndexManager {
222
+ constructor() {
223
+ if (native?.CrmIndexManager) {
224
+ this._native = new native.CrmIndexManager();
225
+ } else {
226
+ // Fallback implementation
227
+ this._contacts = new Map();
228
+ this._deals = new Map();
229
+ this._companies = new Map();
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Index a contact
235
+ */
236
+ indexContact(contact) {
237
+ if (this._native) {
238
+ return this._native.indexContact(contact);
239
+ }
240
+ this._contacts.set(contact.id, contact);
241
+ }
242
+
243
+ /**
244
+ * Get a contact by ID
245
+ */
246
+ getContact(id) {
247
+ if (this._native) {
248
+ return this._native.getContact(id);
249
+ }
250
+ return this._contacts.get(id) || null;
251
+ }
252
+
253
+ /**
254
+ * Remove a contact
255
+ */
256
+ removeContact(id) {
257
+ if (this._native) {
258
+ return this._native.removeContact(id);
259
+ }
260
+ this._contacts.delete(id);
261
+ }
262
+
263
+ /**
264
+ * Index a deal
265
+ */
266
+ indexDeal(deal) {
267
+ if (this._native) {
268
+ return this._native.indexDeal(deal);
269
+ }
270
+ this._deals.set(deal.id, deal);
271
+ }
272
+
273
+ /**
274
+ * Get a deal by ID
275
+ */
276
+ getDeal(id) {
277
+ if (this._native) {
278
+ return this._native.getDeal(id);
279
+ }
280
+ return this._deals.get(id) || null;
281
+ }
282
+
283
+ /**
284
+ * Remove a deal
285
+ */
286
+ removeDeal(id) {
287
+ if (this._native) {
288
+ return this._native.removeDeal(id);
289
+ }
290
+ this._deals.delete(id);
291
+ }
292
+
293
+ /**
294
+ * Index a company
295
+ */
296
+ indexCompany(company) {
297
+ if (this._native) {
298
+ return this._native.indexCompany(company);
299
+ }
300
+ this._companies.set(company.id, company);
301
+ }
302
+
303
+ /**
304
+ * Get a company by ID
305
+ */
306
+ getCompany(id) {
307
+ if (this._native) {
308
+ return this._native.getCompany(id);
309
+ }
310
+ return this._companies.get(id) || null;
311
+ }
312
+
313
+ /**
314
+ * Remove a company
315
+ */
316
+ removeCompany(id) {
317
+ if (this._native) {
318
+ return this._native.removeCompany(id);
319
+ }
320
+ this._companies.delete(id);
321
+ }
322
+
323
+ /**
324
+ * Get counts of all indexed entities
325
+ */
326
+ getCounts() {
327
+ if (this._native) {
328
+ return this._native.getCounts();
329
+ }
330
+ return {
331
+ contacts: this._contacts.size,
332
+ deals: this._deals.size,
333
+ companies: this._companies.size,
334
+ };
335
+ }
336
+
337
+ /**
338
+ * Clear all indexes
339
+ */
340
+ clear() {
341
+ if (this._native) {
342
+ return this._native.clear();
343
+ }
344
+ this._contacts.clear();
345
+ this._deals.clear();
346
+ this._companies.clear();
347
+ }
348
+ }
349
+
350
+ // ============================================================================
351
+ // Media Metadata
352
+ // ============================================================================
353
+
354
+ /**
355
+ * Extract metadata from a media file
356
+ */
357
+ export function extractMediaMetadata(filePath) {
358
+ if (native?.extractMediaMetadata) {
359
+ return native.extractMediaMetadata(filePath);
360
+ }
361
+ return _extractMediaMetadataFallback(filePath);
362
+ }
363
+
364
+ /**
365
+ * Batch extract metadata from multiple files
366
+ */
367
+ export function extractMediaMetadataBatch(filePaths) {
368
+ if (native?.extractMediaMetadataBatch) {
369
+ return native.extractMediaMetadataBatch(filePaths);
370
+ }
371
+ return filePaths.map(extractMediaMetadata);
372
+ }
373
+
374
+ /**
375
+ * Generate thumbnail for an image
376
+ */
377
+ export function generateThumbnail(inputPath, outputPath, maxWidth, maxHeight) {
378
+ if (native?.generateThumbnail) {
379
+ return native.generateThumbnail(inputPath, outputPath, maxWidth, maxHeight);
380
+ }
381
+ throw new Error('Thumbnail generation requires native module');
382
+ }
383
+
384
+ /**
385
+ * Check if a file is a valid media type
386
+ */
387
+ export function isValidMediaType(filePath) {
388
+ if (native?.isValidMediaType) {
389
+ return native.isValidMediaType(filePath);
390
+ }
391
+ return _isValidMediaTypeFallback(filePath);
392
+ }
393
+
394
+ // Fallback implementations
395
+ function _extractMediaMetadataFallback(filePath) {
396
+ const fs = require('fs');
397
+ const path = require('path');
398
+
399
+ try {
400
+ const stats = fs.statSync(filePath);
401
+ const ext = path.extname(filePath).toLowerCase().slice(1);
402
+
403
+ const mimeTypes = {
404
+ jpg: 'image/jpeg',
405
+ jpeg: 'image/jpeg',
406
+ png: 'image/png',
407
+ gif: 'image/gif',
408
+ webp: 'image/webp',
409
+ mp4: 'video/mp4',
410
+ webm: 'video/webm',
411
+ mp3: 'audio/mpeg',
412
+ wav: 'audio/wav',
413
+ ogg: 'audio/ogg',
414
+ };
415
+
416
+ return {
417
+ mimeType: mimeTypes[ext] || 'application/octet-stream',
418
+ size: stats.size,
419
+ width: null,
420
+ height: null,
421
+ duration: null,
422
+ bitrate: null,
423
+ codec: null,
424
+ extra: null,
425
+ };
426
+ } catch (err) {
427
+ throw new Error(`Failed to extract metadata: ${err.message}`);
428
+ }
429
+ }
430
+
431
+ function _isValidMediaTypeFallback(filePath) {
432
+ const path = require('path');
433
+ const ext = path.extname(filePath).toLowerCase().slice(1);
434
+
435
+ const mediaExtensions = [
436
+ 'jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg',
437
+ 'mp4', 'webm', 'mov', 'avi', 'mkv',
438
+ 'mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a',
439
+ ];
440
+
441
+ return mediaExtensions.includes(ext);
442
+ }
443
+
444
+ // ============================================================================
445
+ // Search Functions
446
+ // ============================================================================
447
+
448
+ /**
449
+ * Search contacts by name
450
+ */
451
+ export function searchContactsByName(manager, nameQuery, limit) {
452
+ if (native?.searchContactsByName) {
453
+ return native.searchContactsByName(manager, nameQuery, limit);
454
+ }
455
+ // Fallback: basic implementation
456
+ return [];
457
+ }
458
+
459
+ /**
460
+ * Search contacts by company name
461
+ */
462
+ export function searchContactsByCompany(manager, companyQuery, limit) {
463
+ if (native?.searchContactsByCompany) {
464
+ return native.searchContactsByCompany(manager, companyQuery, limit);
465
+ }
466
+ return [];
467
+ }
468
+
469
+ /**
470
+ * Search contacts by tags
471
+ */
472
+ export function searchContactsByTags(manager, tags, matchAll, limit) {
473
+ if (native?.searchContactsByTags) {
474
+ return native.searchContactsByTags(manager, tags, matchAll, limit);
475
+ }
476
+ return [];
477
+ }
478
+
479
+ /**
480
+ * Search deals by title
481
+ */
482
+ export function searchDealsByTitle(manager, titleQuery, limit) {
483
+ if (native?.searchDealsByTitle) {
484
+ return native.searchDealsByTitle(manager, titleQuery, limit);
485
+ }
486
+ return [];
487
+ }
488
+
489
+ /**
490
+ * Search deals by stage
491
+ */
492
+ export function searchDealsByStage(manager, stages, limit) {
493
+ if (native?.searchDealsByStage) {
494
+ return native.searchDealsByStage(manager, stages, limit);
495
+ }
496
+ return [];
497
+ }
498
+
499
+ /**
500
+ * Search companies by name
501
+ */
502
+ export function searchCompaniesByName(manager, nameQuery, limit) {
503
+ if (native?.searchCompaniesByName) {
504
+ return native.searchCompaniesByName(manager, nameQuery, limit);
505
+ }
506
+ return [];
507
+ }
508
+
509
+ /**
510
+ * Search companies by industry
511
+ */
512
+ export function searchCompaniesByIndustry(manager, industries, limit) {
513
+ if (native?.searchCompaniesByIndustry) {
514
+ return native.searchCompaniesByIndustry(manager, industries, limit);
515
+ }
516
+ return [];
517
+ }
518
+
519
+ // ============================================================================
520
+ // Image Functions
521
+ // ============================================================================
522
+
523
+ /**
524
+ * Extract image metadata
525
+ */
526
+ export function extractImageMetadata(filePath) {
527
+ if (native?.extractImageMetadata) {
528
+ return native.extractImageMetadata(filePath);
529
+ }
530
+ const generic = extractMediaMetadata(filePath);
531
+ return {
532
+ width: 0,
533
+ height: 0,
534
+ bitsPerChannel: null,
535
+ colorSpace: null,
536
+ hasAlpha: false,
537
+ orientation: null,
538
+ dpiX: null,
539
+ dpiY: null,
540
+ cameraMake: null,
541
+ cameraModel: null,
542
+ dateTaken: null,
543
+ gpsLatitude: null,
544
+ gpsLongitude: null,
545
+ };
546
+ }
547
+
548
+ /**
549
+ * Get image dimensions
550
+ */
551
+ export function getImageDimensions(filePath) {
552
+ if (native?.getImageDimensions) {
553
+ return native.getImageDimensions(filePath);
554
+ }
555
+ return { width: 0, height: 0 };
556
+ }
557
+
558
+ /**
559
+ * Convert image format
560
+ */
561
+ export function convertImageFormat(inputPath, outputPath, format) {
562
+ if (native?.convertImageFormat) {
563
+ return native.convertImageFormat(inputPath, outputPath, format);
564
+ }
565
+ throw new Error('Image conversion requires native module');
566
+ }
567
+
568
+ // ============================================================================
569
+ // Audio Functions
570
+ // ============================================================================
571
+
572
+ /**
573
+ * Extract full audio metadata
574
+ */
575
+ export function extractFullAudioMetadata(filePath) {
576
+ if (native?.extractFullAudioMetadata) {
577
+ return native.extractFullAudioMetadata(filePath);
578
+ }
579
+ return {
580
+ duration: null,
581
+ sampleRate: null,
582
+ channels: null,
583
+ bitsPerSample: null,
584
+ bitrate: null,
585
+ codec: null,
586
+ title: null,
587
+ artist: null,
588
+ album: null,
589
+ trackNumber: null,
590
+ year: null,
591
+ genre: null,
592
+ };
593
+ }
594
+
595
+ /**
596
+ * Get audio duration
597
+ */
598
+ export function getAudioDuration(filePath) {
599
+ if (native?.getAudioDuration) {
600
+ return native.getAudioDuration(filePath);
601
+ }
602
+ return null;
603
+ }
604
+
605
+ // ============================================================================
606
+ // Video Functions
607
+ // ============================================================================
608
+
609
+ /**
610
+ * Extract full video metadata
611
+ */
612
+ export function extractFullVideoMetadata(filePath) {
613
+ if (native?.extractFullVideoMetadata) {
614
+ return native.extractFullVideoMetadata(filePath);
615
+ }
616
+ return {
617
+ width: null,
618
+ height: null,
619
+ duration: null,
620
+ frameRate: null,
621
+ videoCodec: null,
622
+ audioCodec: null,
623
+ videoBitrate: null,
624
+ audioBitrate: null,
625
+ hasAudio: false,
626
+ container: null,
627
+ totalBitrate: null,
628
+ };
629
+ }
630
+
631
+ /**
632
+ * Get video dimensions
633
+ */
634
+ export function getVideoDimensions(filePath) {
635
+ if (native?.getVideoDimensions) {
636
+ return native.getVideoDimensions(filePath);
637
+ }
638
+ return { width: 0, height: 0 };
639
+ }
640
+
641
+ /**
642
+ * Get video duration
643
+ */
644
+ export function getVideoDuration(filePath) {
645
+ if (native?.getVideoDuration) {
646
+ return native.getVideoDuration(filePath);
647
+ }
648
+ return null;
649
+ }
650
+
651
+ /**
652
+ * Check if video has audio
653
+ */
654
+ export function videoHasAudio(filePath) {
655
+ if (native?.videoHasAudio) {
656
+ return native.videoHasAudio(filePath);
657
+ }
658
+ return false;
659
+ }
660
+
661
+ /**
662
+ * Get video codec
663
+ */
664
+ export function getVideoCodec(filePath) {
665
+ if (native?.getVideoCodec) {
666
+ return native.getVideoCodec(filePath);
667
+ }
668
+ return null;
669
+ }
670
+
671
+ // ============================================================================
672
+ // Utility Functions
673
+ // ============================================================================
674
+
675
+ /**
676
+ * Check if native module is available
677
+ */
678
+ export function isNativeAvailable() {
679
+ return native !== null;
680
+ }
681
+
682
+ /**
683
+ * Get native module version
684
+ */
685
+ export function getNativeVersion() {
686
+ return native?.version || 'fallback';
687
+ }