@souscheflabs/ml-vision 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 +274 -0
- package/dist/components/DetectionOverlay.d.ts +57 -0
- package/dist/components/DetectionOverlay.js +133 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +9 -0
- package/dist/core/CacheManager.d.ts +168 -0
- package/dist/core/CacheManager.js +331 -0
- package/dist/core/MLVisionProvider.d.ts +90 -0
- package/dist/core/MLVisionProvider.js +188 -0
- package/dist/core/ServerClient.d.ts +131 -0
- package/dist/core/ServerClient.js +291 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +18 -0
- package/dist/hooks/classLabels.d.ts +35 -0
- package/dist/hooks/classLabels.js +439 -0
- package/dist/hooks/classLabelsCoco.d.ts +43 -0
- package/dist/hooks/classLabelsCoco.js +103 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.js +27 -0
- package/dist/hooks/useMultiBarcodeScanner.d.ts +34 -0
- package/dist/hooks/useMultiBarcodeScanner.js +290 -0
- package/dist/hooks/useProductDetector.d.ts +38 -0
- package/dist/hooks/useProductDetector.js +679 -0
- package/dist/hooks/useReceiptScanner.d.ts +37 -0
- package/dist/hooks/useReceiptScanner.js +405 -0
- package/dist/hooks/useVideoScanner.d.ts +118 -0
- package/dist/hooks/useVideoScanner.js +383 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +130 -0
- package/dist/processors/detectionProcessor.d.ts +86 -0
- package/dist/processors/detectionProcessor.js +124 -0
- package/dist/processors/index.d.ts +5 -0
- package/dist/processors/index.js +16 -0
- package/dist/processors/tfliteFrameProcessor.d.ts +90 -0
- package/dist/processors/tfliteFrameProcessor.js +213 -0
- package/dist/types/barcode.d.ts +91 -0
- package/dist/types/barcode.js +19 -0
- package/dist/types/detection.d.ts +166 -0
- package/dist/types/detection.js +8 -0
- package/dist/types/index.d.ts +126 -0
- package/dist/types/index.js +25 -0
- package/dist/types/ocr.d.ts +202 -0
- package/dist/types/ocr.js +8 -0
- package/dist/utils/imagePreprocessor.d.ts +85 -0
- package/dist/utils/imagePreprocessor.js +304 -0
- package/dist/utils/yoloProcessor.d.ts +40 -0
- package/dist/utils/yoloProcessor.js +154 -0
- package/package.json +78 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CacheManager - MMKV-based caching for ML Vision results
|
|
4
|
+
*
|
|
5
|
+
* Provides fast, synchronous caching for:
|
|
6
|
+
* - Barcode to product lookups
|
|
7
|
+
* - Product recognition results
|
|
8
|
+
* - Receipt parsing results
|
|
9
|
+
* - Model metadata
|
|
10
|
+
*
|
|
11
|
+
* Uses react-native-mmkv for ~30x faster access than AsyncStorage.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CacheManager = exports.CACHE_TTL = void 0;
|
|
15
|
+
exports.createCacheManager = createCacheManager;
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Cache Configuration
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Default TTL values (in milliseconds)
|
|
21
|
+
*/
|
|
22
|
+
exports.CACHE_TTL = {
|
|
23
|
+
/** Barcode lookups - 7 days */
|
|
24
|
+
BARCODE: 7 * 24 * 60 * 60 * 1000,
|
|
25
|
+
/** Product recognition - 24 hours */
|
|
26
|
+
PRODUCT: 24 * 60 * 60 * 1000,
|
|
27
|
+
/** Receipt parsing - 1 hour */
|
|
28
|
+
RECEIPT: 60 * 60 * 1000,
|
|
29
|
+
/** Model metadata - until manually cleared */
|
|
30
|
+
MODEL: Infinity,
|
|
31
|
+
/** Server responses - 5 minutes */
|
|
32
|
+
SERVER: 5 * 60 * 1000,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Cache key prefixes for namespacing
|
|
36
|
+
*/
|
|
37
|
+
const CACHE_PREFIX = {
|
|
38
|
+
BARCODE: 'mlv_barcode_',
|
|
39
|
+
PRODUCT: 'mlv_product_',
|
|
40
|
+
RECEIPT: 'mlv_receipt_',
|
|
41
|
+
MODEL: 'mlv_model_',
|
|
42
|
+
CONFIG: 'mlv_config_',
|
|
43
|
+
};
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// CacheManager Class
|
|
46
|
+
// ============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* CacheManager provides fast key-value caching using MMKV
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const cache = new CacheManager(mmkvInstance);
|
|
53
|
+
*
|
|
54
|
+
* // Cache a barcode lookup
|
|
55
|
+
* cache.setBarcode('0123456789012', {
|
|
56
|
+
* barcode: '0123456789012',
|
|
57
|
+
* format: 'ean-13',
|
|
58
|
+
* productId: 'prod_123',
|
|
59
|
+
* productName: 'Example Product',
|
|
60
|
+
* found: true,
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Retrieve later
|
|
64
|
+
* const product = cache.getBarcode('0123456789012');
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
class CacheManager {
|
|
68
|
+
constructor(storage, customTTL) {
|
|
69
|
+
this.storage = storage;
|
|
70
|
+
this.defaultTTL = { ...exports.CACHE_TTL, ...customTTL };
|
|
71
|
+
}
|
|
72
|
+
// ==========================================================================
|
|
73
|
+
// Barcode Cache Methods
|
|
74
|
+
// ==========================================================================
|
|
75
|
+
/**
|
|
76
|
+
* Cache a barcode lookup result
|
|
77
|
+
*/
|
|
78
|
+
setBarcode(barcode, data, ttl) {
|
|
79
|
+
const entry = {
|
|
80
|
+
data,
|
|
81
|
+
timestamp: Date.now(),
|
|
82
|
+
ttl: ttl ?? this.defaultTTL.BARCODE,
|
|
83
|
+
};
|
|
84
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
85
|
+
this.storage.set(key, JSON.stringify(entry));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get a cached barcode lookup
|
|
89
|
+
* @returns The cached data or null if not found/expired
|
|
90
|
+
*/
|
|
91
|
+
getBarcode(barcode) {
|
|
92
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
93
|
+
const cached = this.storage.getString(key);
|
|
94
|
+
if (!cached)
|
|
95
|
+
return null;
|
|
96
|
+
try {
|
|
97
|
+
const entry = JSON.parse(cached);
|
|
98
|
+
if (this.isExpired(entry)) {
|
|
99
|
+
this.storage.delete(key);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return entry.data;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
this.storage.delete(key);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if a barcode is cached
|
|
111
|
+
*/
|
|
112
|
+
hasBarcode(barcode) {
|
|
113
|
+
return this.getBarcode(barcode) !== null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Delete a cached barcode
|
|
117
|
+
*/
|
|
118
|
+
deleteBarcode(barcode) {
|
|
119
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
120
|
+
this.storage.delete(key);
|
|
121
|
+
}
|
|
122
|
+
// ==========================================================================
|
|
123
|
+
// Product Recognition Cache Methods
|
|
124
|
+
// ==========================================================================
|
|
125
|
+
/**
|
|
126
|
+
* Cache product recognition results for an image
|
|
127
|
+
* @param imageHash - Hash of the image (e.g., MD5 or perceptual hash)
|
|
128
|
+
*/
|
|
129
|
+
setProductRecognition(imageHash, data, ttl) {
|
|
130
|
+
const entry = {
|
|
131
|
+
data,
|
|
132
|
+
timestamp: Date.now(),
|
|
133
|
+
ttl: ttl ?? this.defaultTTL.PRODUCT,
|
|
134
|
+
};
|
|
135
|
+
const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
|
|
136
|
+
this.storage.set(key, JSON.stringify(entry));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get cached product recognition for an image
|
|
140
|
+
*/
|
|
141
|
+
getProductRecognition(imageHash) {
|
|
142
|
+
const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
|
|
143
|
+
const cached = this.storage.getString(key);
|
|
144
|
+
if (!cached)
|
|
145
|
+
return null;
|
|
146
|
+
try {
|
|
147
|
+
const entry = JSON.parse(cached);
|
|
148
|
+
if (this.isExpired(entry)) {
|
|
149
|
+
this.storage.delete(key);
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
return entry.data;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
this.storage.delete(key);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// ==========================================================================
|
|
160
|
+
// Model Metadata Cache Methods
|
|
161
|
+
// ==========================================================================
|
|
162
|
+
/**
|
|
163
|
+
* Store model metadata
|
|
164
|
+
*/
|
|
165
|
+
setModelMetadata(modelId, metadata) {
|
|
166
|
+
const key = `${CACHE_PREFIX.MODEL}${modelId}`;
|
|
167
|
+
this.storage.set(key, JSON.stringify(metadata));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get model metadata
|
|
171
|
+
*/
|
|
172
|
+
getModelMetadata(modelId) {
|
|
173
|
+
const key = `${CACHE_PREFIX.MODEL}${modelId}`;
|
|
174
|
+
const cached = this.storage.getString(key);
|
|
175
|
+
if (!cached)
|
|
176
|
+
return null;
|
|
177
|
+
try {
|
|
178
|
+
return JSON.parse(cached);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ==========================================================================
|
|
185
|
+
// Config Cache Methods
|
|
186
|
+
// ==========================================================================
|
|
187
|
+
/**
|
|
188
|
+
* Store a configuration value
|
|
189
|
+
*/
|
|
190
|
+
setConfig(key, value) {
|
|
191
|
+
const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
|
|
192
|
+
this.storage.set(fullKey, JSON.stringify(value));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get a configuration value
|
|
196
|
+
*/
|
|
197
|
+
getConfig(key, defaultValue) {
|
|
198
|
+
const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
|
|
199
|
+
const cached = this.storage.getString(fullKey);
|
|
200
|
+
if (!cached)
|
|
201
|
+
return defaultValue;
|
|
202
|
+
try {
|
|
203
|
+
return JSON.parse(cached);
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return defaultValue;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// ==========================================================================
|
|
210
|
+
// Cache Management Methods
|
|
211
|
+
// ==========================================================================
|
|
212
|
+
/**
|
|
213
|
+
* Clear all expired entries from the cache
|
|
214
|
+
* Call this periodically (e.g., on app start)
|
|
215
|
+
*/
|
|
216
|
+
cleanupExpired() {
|
|
217
|
+
let removed = 0;
|
|
218
|
+
const allKeys = this.storage.getAllKeys();
|
|
219
|
+
for (const key of allKeys) {
|
|
220
|
+
// Only process our prefixed keys
|
|
221
|
+
const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
|
|
222
|
+
if (!isOurKey)
|
|
223
|
+
continue;
|
|
224
|
+
// Skip model metadata (no TTL)
|
|
225
|
+
if (key.startsWith(CACHE_PREFIX.MODEL))
|
|
226
|
+
continue;
|
|
227
|
+
const value = this.storage.getString(key);
|
|
228
|
+
if (!value)
|
|
229
|
+
continue;
|
|
230
|
+
try {
|
|
231
|
+
const entry = JSON.parse(value);
|
|
232
|
+
if (this.isExpired(entry)) {
|
|
233
|
+
this.storage.delete(key);
|
|
234
|
+
removed++;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Invalid entry, remove it
|
|
239
|
+
this.storage.delete(key);
|
|
240
|
+
removed++;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return removed;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Clear all ML Vision cache entries
|
|
247
|
+
*/
|
|
248
|
+
clearAll() {
|
|
249
|
+
const allKeys = this.storage.getAllKeys();
|
|
250
|
+
for (const key of allKeys) {
|
|
251
|
+
const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
|
|
252
|
+
if (isOurKey) {
|
|
253
|
+
this.storage.delete(key);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Clear cache by type
|
|
259
|
+
*/
|
|
260
|
+
clearByType(type) {
|
|
261
|
+
const prefix = CACHE_PREFIX[type];
|
|
262
|
+
const allKeys = this.storage.getAllKeys();
|
|
263
|
+
for (const key of allKeys) {
|
|
264
|
+
if (key.startsWith(prefix)) {
|
|
265
|
+
this.storage.delete(key);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get cache statistics
|
|
271
|
+
*/
|
|
272
|
+
getStats() {
|
|
273
|
+
const allKeys = this.storage.getAllKeys();
|
|
274
|
+
let barcodeEntries = 0;
|
|
275
|
+
let productEntries = 0;
|
|
276
|
+
let receiptEntries = 0;
|
|
277
|
+
let totalSizeBytes = 0;
|
|
278
|
+
for (const key of allKeys) {
|
|
279
|
+
if (key.startsWith(CACHE_PREFIX.BARCODE)) {
|
|
280
|
+
barcodeEntries++;
|
|
281
|
+
}
|
|
282
|
+
else if (key.startsWith(CACHE_PREFIX.PRODUCT)) {
|
|
283
|
+
productEntries++;
|
|
284
|
+
}
|
|
285
|
+
else if (key.startsWith(CACHE_PREFIX.RECEIPT)) {
|
|
286
|
+
receiptEntries++;
|
|
287
|
+
}
|
|
288
|
+
// Estimate size
|
|
289
|
+
const value = this.storage.getString(key);
|
|
290
|
+
if (value) {
|
|
291
|
+
totalSizeBytes += key.length + value.length;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
barcodeEntries,
|
|
296
|
+
productEntries,
|
|
297
|
+
receiptEntries,
|
|
298
|
+
totalSizeBytes,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// ==========================================================================
|
|
302
|
+
// Private Helper Methods
|
|
303
|
+
// ==========================================================================
|
|
304
|
+
/**
|
|
305
|
+
* Check if a cache entry has expired
|
|
306
|
+
*/
|
|
307
|
+
isExpired(entry) {
|
|
308
|
+
if (entry.ttl === Infinity)
|
|
309
|
+
return false;
|
|
310
|
+
return Date.now() - entry.timestamp > entry.ttl;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.CacheManager = CacheManager;
|
|
314
|
+
// ============================================================================
|
|
315
|
+
// Factory Function
|
|
316
|
+
// ============================================================================
|
|
317
|
+
/**
|
|
318
|
+
* Create a CacheManager instance
|
|
319
|
+
* This is the recommended way to create a CacheManager
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```typescript
|
|
323
|
+
* import { MMKV } from 'react-native-mmkv';
|
|
324
|
+
*
|
|
325
|
+
* const storage = new MMKV({ id: 'ml-vision-cache' });
|
|
326
|
+
* const cache = createCacheManager(storage);
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
function createCacheManager(storage, customTTL) {
|
|
330
|
+
return new CacheManager(storage, customTTL);
|
|
331
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MLVisionProvider - Context provider for ML Vision functionality
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Configuration management
|
|
6
|
+
* - Cache manager instance
|
|
7
|
+
* - Server client for fallback inference
|
|
8
|
+
* - Model manager for TFLite models
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { MLVisionProvider } from '@souschef/ml-vision';
|
|
13
|
+
*
|
|
14
|
+
* function App() {
|
|
15
|
+
* return (
|
|
16
|
+
* <MLVisionProvider
|
|
17
|
+
* config={{
|
|
18
|
+
* serverUrl: 'http://192.168.1.100:8000',
|
|
19
|
+
* cacheEnabled: true,
|
|
20
|
+
* }}
|
|
21
|
+
* >
|
|
22
|
+
* <YourApp />
|
|
23
|
+
* </MLVisionProvider>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import React, { type ReactNode } from 'react';
|
|
29
|
+
import type { MMKV } from 'react-native-mmkv';
|
|
30
|
+
import { CacheManager } from './CacheManager';
|
|
31
|
+
import { ServerClient } from './ServerClient';
|
|
32
|
+
import type { MLVisionConfig, ServerHealthResponse } from '../types';
|
|
33
|
+
/**
|
|
34
|
+
* Context value provided by MLVisionProvider
|
|
35
|
+
*/
|
|
36
|
+
export interface MLVisionContextValue {
|
|
37
|
+
/** Merged configuration */
|
|
38
|
+
config: Required<MLVisionConfig>;
|
|
39
|
+
/** Whether the provider is fully initialized */
|
|
40
|
+
isInitialized: boolean;
|
|
41
|
+
/** Cache manager instance (null if caching disabled) */
|
|
42
|
+
cacheManager: CacheManager | null;
|
|
43
|
+
/** Server client for fallback inference (null if no serverUrl) */
|
|
44
|
+
serverClient: ServerClient | null;
|
|
45
|
+
/** Whether the server is available */
|
|
46
|
+
serverAvailable: boolean;
|
|
47
|
+
/** Server health info */
|
|
48
|
+
serverHealth: ServerHealthResponse | null;
|
|
49
|
+
/** Check server health */
|
|
50
|
+
checkServerHealth: () => Promise<ServerHealthResponse | null>;
|
|
51
|
+
/** Update configuration at runtime */
|
|
52
|
+
updateConfig: (updates: Partial<MLVisionConfig>) => void;
|
|
53
|
+
}
|
|
54
|
+
export interface MLVisionProviderProps {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
/** Configuration options */
|
|
57
|
+
config?: MLVisionConfig;
|
|
58
|
+
/** MMKV storage instance for caching (required if cacheEnabled) */
|
|
59
|
+
storage?: MMKV;
|
|
60
|
+
/** Callback when initialization completes */
|
|
61
|
+
onInitialized?: () => void;
|
|
62
|
+
/** Callback on initialization error */
|
|
63
|
+
onError?: (error: Error) => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* MLVisionProvider - Wrap your app with this provider to use ML Vision hooks
|
|
67
|
+
*/
|
|
68
|
+
export declare function MLVisionProvider({ children, config: userConfig, storage, onInitialized, onError, }: MLVisionProviderProps): React.ReactElement;
|
|
69
|
+
/**
|
|
70
|
+
* Hook to access the MLVision context
|
|
71
|
+
*
|
|
72
|
+
* @throws Error if used outside of MLVisionProvider
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* function MyComponent() {
|
|
77
|
+
* const { config, serverAvailable, cacheManager } = useMLVisionContext();
|
|
78
|
+
*
|
|
79
|
+
* if (!serverAvailable) {
|
|
80
|
+
* console.log('Running in offline mode');
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function useMLVisionContext(): MLVisionContextValue;
|
|
86
|
+
/**
|
|
87
|
+
* Hook to check if MLVision is initialized
|
|
88
|
+
* Returns false if used outside provider (won't throw)
|
|
89
|
+
*/
|
|
90
|
+
export declare function useMLVisionReady(): boolean;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MLVisionProvider = MLVisionProvider;
|
|
4
|
+
exports.useMLVisionContext = useMLVisionContext;
|
|
5
|
+
exports.useMLVisionReady = useMLVisionReady;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
/**
|
|
8
|
+
* MLVisionProvider - Context provider for ML Vision functionality
|
|
9
|
+
*
|
|
10
|
+
* Provides:
|
|
11
|
+
* - Configuration management
|
|
12
|
+
* - Cache manager instance
|
|
13
|
+
* - Server client for fallback inference
|
|
14
|
+
* - Model manager for TFLite models
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { MLVisionProvider } from '@souschef/ml-vision';
|
|
19
|
+
*
|
|
20
|
+
* function App() {
|
|
21
|
+
* return (
|
|
22
|
+
* <MLVisionProvider
|
|
23
|
+
* config={{
|
|
24
|
+
* serverUrl: 'http://192.168.1.100:8000',
|
|
25
|
+
* cacheEnabled: true,
|
|
26
|
+
* }}
|
|
27
|
+
* >
|
|
28
|
+
* <YourApp />
|
|
29
|
+
* </MLVisionProvider>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
const react_1 = require("react");
|
|
35
|
+
const CacheManager_1 = require("./CacheManager");
|
|
36
|
+
const ServerClient_1 = require("./ServerClient");
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Default Configuration
|
|
39
|
+
// ============================================================================
|
|
40
|
+
const DEFAULT_CONFIG = {
|
|
41
|
+
serverUrl: '',
|
|
42
|
+
serverTimeout: 5000,
|
|
43
|
+
cacheEnabled: true,
|
|
44
|
+
cacheTTL: 24 * 60 * 60 * 1000, // 24 hours
|
|
45
|
+
modelUpdateCheck: true,
|
|
46
|
+
enableGPUDelegate: true,
|
|
47
|
+
};
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Context
|
|
50
|
+
// ============================================================================
|
|
51
|
+
const MLVisionContext = (0, react_1.createContext)(null);
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Provider Component
|
|
54
|
+
// ============================================================================
|
|
55
|
+
/**
|
|
56
|
+
* MLVisionProvider - Wrap your app with this provider to use ML Vision hooks
|
|
57
|
+
*/
|
|
58
|
+
function MLVisionProvider({ children, config: userConfig, storage, onInitialized, onError, }) {
|
|
59
|
+
// Merge user config with defaults
|
|
60
|
+
const [config, setConfig] = (0, react_1.useState)(() => ({
|
|
61
|
+
...DEFAULT_CONFIG,
|
|
62
|
+
...userConfig,
|
|
63
|
+
}));
|
|
64
|
+
const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
|
|
65
|
+
const [serverAvailable, setServerAvailable] = (0, react_1.useState)(false);
|
|
66
|
+
const [serverHealth, setServerHealth] = (0, react_1.useState)(null);
|
|
67
|
+
// Create cache manager
|
|
68
|
+
const cacheManager = (0, react_1.useMemo)(() => {
|
|
69
|
+
if (!config.cacheEnabled || !storage) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return (0, CacheManager_1.createCacheManager)(storage);
|
|
73
|
+
}, [config.cacheEnabled, storage]);
|
|
74
|
+
// Create server client
|
|
75
|
+
const serverClient = (0, react_1.useMemo)(() => {
|
|
76
|
+
if (!config.serverUrl) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return (0, ServerClient_1.createServerClient)(config.serverUrl, config.serverTimeout);
|
|
80
|
+
}, [config.serverUrl, config.serverTimeout]);
|
|
81
|
+
// Check server health
|
|
82
|
+
const checkServerHealth = (0, react_1.useCallback)(async () => {
|
|
83
|
+
if (!serverClient) {
|
|
84
|
+
setServerAvailable(false);
|
|
85
|
+
setServerHealth(null);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const health = await serverClient.checkHealth();
|
|
90
|
+
setServerAvailable(health.status === 'healthy');
|
|
91
|
+
setServerHealth(health);
|
|
92
|
+
return health;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
setServerAvailable(false);
|
|
96
|
+
setServerHealth(null);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}, [serverClient]);
|
|
100
|
+
// Update config at runtime
|
|
101
|
+
const updateConfig = (0, react_1.useCallback)((updates) => {
|
|
102
|
+
setConfig((prev) => ({ ...prev, ...updates }));
|
|
103
|
+
}, []);
|
|
104
|
+
// Initialize on mount
|
|
105
|
+
(0, react_1.useEffect)(() => {
|
|
106
|
+
async function initialize() {
|
|
107
|
+
try {
|
|
108
|
+
// Clean up expired cache entries
|
|
109
|
+
if (cacheManager) {
|
|
110
|
+
const removed = cacheManager.cleanupExpired();
|
|
111
|
+
if (removed > 0) {
|
|
112
|
+
console.log(`[MLVision] Cleaned up ${removed} expired cache entries`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Check server health if configured
|
|
116
|
+
if (serverClient) {
|
|
117
|
+
await checkServerHealth();
|
|
118
|
+
}
|
|
119
|
+
setIsInitialized(true);
|
|
120
|
+
onInitialized?.();
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const err = error instanceof Error ? error : new Error('Initialization failed');
|
|
124
|
+
console.error('[MLVision] Initialization error:', err);
|
|
125
|
+
onError?.(err);
|
|
126
|
+
// Still mark as initialized so the app can work in offline mode
|
|
127
|
+
setIsInitialized(true);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
initialize();
|
|
131
|
+
}, [cacheManager, serverClient, checkServerHealth, onInitialized, onError]);
|
|
132
|
+
// Context value
|
|
133
|
+
const contextValue = (0, react_1.useMemo)(() => ({
|
|
134
|
+
config,
|
|
135
|
+
isInitialized,
|
|
136
|
+
cacheManager,
|
|
137
|
+
serverClient,
|
|
138
|
+
serverAvailable,
|
|
139
|
+
serverHealth,
|
|
140
|
+
checkServerHealth,
|
|
141
|
+
updateConfig,
|
|
142
|
+
}), [
|
|
143
|
+
config,
|
|
144
|
+
isInitialized,
|
|
145
|
+
cacheManager,
|
|
146
|
+
serverClient,
|
|
147
|
+
serverAvailable,
|
|
148
|
+
serverHealth,
|
|
149
|
+
checkServerHealth,
|
|
150
|
+
updateConfig,
|
|
151
|
+
]);
|
|
152
|
+
return ((0, jsx_runtime_1.jsx)(MLVisionContext.Provider, { value: contextValue, children: children }));
|
|
153
|
+
}
|
|
154
|
+
// ============================================================================
|
|
155
|
+
// Hook
|
|
156
|
+
// ============================================================================
|
|
157
|
+
/**
|
|
158
|
+
* Hook to access the MLVision context
|
|
159
|
+
*
|
|
160
|
+
* @throws Error if used outside of MLVisionProvider
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* function MyComponent() {
|
|
165
|
+
* const { config, serverAvailable, cacheManager } = useMLVisionContext();
|
|
166
|
+
*
|
|
167
|
+
* if (!serverAvailable) {
|
|
168
|
+
* console.log('Running in offline mode');
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
function useMLVisionContext() {
|
|
174
|
+
const context = (0, react_1.useContext)(MLVisionContext);
|
|
175
|
+
if (!context) {
|
|
176
|
+
throw new Error('useMLVisionContext must be used within an MLVisionProvider. ' +
|
|
177
|
+
'Wrap your app with <MLVisionProvider> to use ML Vision hooks.');
|
|
178
|
+
}
|
|
179
|
+
return context;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Hook to check if MLVision is initialized
|
|
183
|
+
* Returns false if used outside provider (won't throw)
|
|
184
|
+
*/
|
|
185
|
+
function useMLVisionReady() {
|
|
186
|
+
const context = (0, react_1.useContext)(MLVisionContext);
|
|
187
|
+
return context?.isInitialized ?? false;
|
|
188
|
+
}
|