@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.
- package/README.md +174 -0
- package/dist/cli/commands/activities.d.ts +11 -0
- package/dist/cli/commands/activities.d.ts.map +1 -0
- package/dist/cli/commands/activities.js +427 -0
- package/dist/cli/commands/activities.js.map +1 -0
- package/dist/cli/commands/contacts.d.ts +11 -0
- package/dist/cli/commands/contacts.d.ts.map +1 -0
- package/dist/cli/commands/contacts.js +458 -0
- package/dist/cli/commands/contacts.js.map +1 -0
- package/dist/cli/commands/deals.d.ts +11 -0
- package/dist/cli/commands/deals.d.ts.map +1 -0
- package/dist/cli/commands/deals.js +498 -0
- package/dist/cli/commands/deals.js.map +1 -0
- package/dist/cli/commands/media.d.ts +11 -0
- package/dist/cli/commands/media.d.ts.map +1 -0
- package/dist/cli/commands/media.js +417 -0
- package/dist/cli/commands/media.js.map +1 -0
- package/dist/cli/commands/search.d.ts +11 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +346 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/repl.d.ts +15 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +318 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/utils/config.d.ts +91 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +212 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/output.d.ts +136 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +323 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/cli/utils/prompt.d.ts +81 -0
- package/dist/cli/utils/prompt.d.ts.map +1 -0
- package/dist/cli/utils/prompt.js +341 -0
- package/dist/cli/utils/prompt.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +32 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/schemas.d.ts +3050 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +667 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/types.d.ts +597 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +8 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +18 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/storage/client.d.ts +109 -0
- package/dist/mcp/storage/client.d.ts.map +1 -0
- package/dist/mcp/storage/client.js +355 -0
- package/dist/mcp/storage/client.js.map +1 -0
- package/dist/mcp/storage/index.d.ts +7 -0
- package/dist/mcp/storage/index.d.ts.map +1 -0
- package/dist/mcp/storage/index.js +6 -0
- package/dist/mcp/storage/index.js.map +1 -0
- package/dist/mcp/storage/types.d.ts +44 -0
- package/dist/mcp/storage/types.d.ts.map +1 -0
- package/dist/mcp/storage/types.js +35 -0
- package/dist/mcp/storage/types.js.map +1 -0
- package/dist/mcp/tools/definitions.d.ts +16 -0
- package/dist/mcp/tools/definitions.d.ts.map +1 -0
- package/dist/mcp/tools/definitions.js +914 -0
- package/dist/mcp/tools/definitions.js.map +1 -0
- package/dist/mcp/tools/handlers.d.ts +50 -0
- package/dist/mcp/tools/handlers.d.ts.map +1 -0
- package/dist/mcp/tools/handlers.js +760 -0
- package/dist/mcp/tools/handlers.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +7 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +6 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/types.d.ts +314 -0
- package/dist/mcp/tools/types.d.ts.map +1 -0
- package/dist/mcp/tools/types.js +5 -0
- package/dist/mcp/tools/types.js.map +1 -0
- package/dist/mcp/transports/stdio.d.ts +27 -0
- package/dist/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/mcp/transports/stdio.js +237 -0
- package/dist/mcp/transports/stdio.js.map +1 -0
- package/dist/telemetry/index.d.ts +58 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +109 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/logger.d.ts +116 -0
- package/dist/telemetry/logger.d.ts.map +1 -0
- package/dist/telemetry/logger.js +256 -0
- package/dist/telemetry/logger.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +115 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +292 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/tracer.d.ts +227 -0
- package/dist/telemetry/tracer.d.ts.map +1 -0
- package/dist/telemetry/tracer.js +355 -0
- package/dist/telemetry/tracer.js.map +1 -0
- package/dist/web/app.d.ts +2 -0
- package/dist/web/app.d.ts.map +1 -0
- package/dist/web/app.js +115 -0
- package/dist/web/app.js.map +1 -0
- package/dist/web/components/ContactList.d.ts +3 -0
- package/dist/web/components/ContactList.d.ts.map +1 -0
- package/dist/web/components/ContactList.js +262 -0
- package/dist/web/components/ContactList.js.map +1 -0
- package/dist/web/components/Dashboard.d.ts +3 -0
- package/dist/web/components/Dashboard.d.ts.map +1 -0
- package/dist/web/components/Dashboard.js +158 -0
- package/dist/web/components/Dashboard.js.map +1 -0
- package/dist/web/components/DealPipeline.d.ts +3 -0
- package/dist/web/components/DealPipeline.d.ts.map +1 -0
- package/dist/web/components/DealPipeline.js +306 -0
- package/dist/web/components/DealPipeline.js.map +1 -0
- package/dist/web/index.d.ts +2 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +269 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/types.d.ts +75 -0
- package/dist/web/types.d.ts.map +1 -0
- package/dist/web/types.js +3 -0
- package/dist/web/types.js.map +1 -0
- package/native/index.d.ts +571 -0
- package/native/index.js +687 -0
- package/package.json +105 -0
- package/src/cli/commands/activities.ts +543 -0
- package/src/cli/commands/contacts.ts +563 -0
- package/src/cli/commands/deals.ts +637 -0
- package/src/cli/commands/media.ts +521 -0
- package/src/cli/commands/search.ts +426 -0
- package/src/cli/index.ts +203 -0
- package/src/cli/repl.ts +379 -0
- package/src/cli/utils/config.ts +299 -0
- package/src/cli/utils/output.ts +386 -0
- package/src/cli/utils/prompt.ts +444 -0
- package/src/cli.ts +11 -0
- package/src/core/index.ts +184 -0
- package/src/core/schemas.ts +770 -0
- package/src/core/types.ts +969 -0
- package/src/index.ts +8 -0
- package/src/mcp/index.ts +17 -0
- package/src/mcp/server.ts +26 -0
- package/src/mcp/storage/client.ts +408 -0
- package/src/mcp/storage/index.ts +7 -0
- package/src/mcp/storage/types.ts +72 -0
- package/src/mcp/tools/definitions.ts +961 -0
- package/src/mcp/tools/handlers.ts +805 -0
- package/src/mcp/tools/index.ts +7 -0
- package/src/mcp/tools/types.ts +390 -0
- package/src/mcp/transports/stdio.ts +225 -0
- package/src/telemetry/index.ts +131 -0
- package/src/telemetry/logger.ts +318 -0
- package/src/telemetry/metrics.ts +393 -0
- package/src/telemetry/tracer.ts +487 -0
- package/src/web/api/activities.ts +41 -0
- package/src/web/api/contacts.ts +114 -0
- package/src/web/api/deals.ts +108 -0
- package/src/web/api/media.ts +98 -0
- package/src/web/app.tsx +143 -0
- package/src/web/components/ActivityFeed.tsx +195 -0
- package/src/web/components/ContactList.tsx +340 -0
- package/src/web/components/Dashboard.tsx +214 -0
- package/src/web/components/DealPipeline.tsx +405 -0
- package/src/web/components/MediaGallery.tsx +334 -0
- package/src/web/index.html +14 -0
- package/src/web/index.ts +326 -0
- package/src/web/styles/main.css +180 -0
- package/src/web/types.ts +311 -0
package/native/index.js
ADDED
|
@@ -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
|
+
}
|