@souscheflabs/ml-vision 0.1.1 → 0.1.2
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/CHANGELOG.md +54 -0
- package/LICENSE +15 -0
- package/README.md +50 -5
- package/dist/{components → cjs/components}/DetectionOverlay.js +1 -0
- package/dist/cjs/components/DetectionOverlay.js.map +1 -0
- package/dist/{components → cjs/components}/index.js +1 -0
- package/dist/cjs/components/index.js.map +1 -0
- package/dist/{core → cjs/core}/CacheManager.js +1 -0
- package/dist/cjs/core/CacheManager.js.map +1 -0
- package/dist/{core → cjs/core}/MLVisionProvider.js +4 -2
- package/dist/cjs/core/MLVisionProvider.js.map +1 -0
- package/dist/{core → cjs/core}/ServerClient.js +33 -13
- package/dist/cjs/core/ServerClient.js.map +1 -0
- package/dist/{core → cjs/core}/index.js +1 -0
- package/dist/cjs/core/index.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/classLabels.js +1 -0
- package/dist/cjs/hooks/classLabels.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/classLabelsCoco.js +1 -0
- package/dist/cjs/hooks/classLabelsCoco.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/index.js +1 -0
- package/dist/cjs/hooks/index.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/useMultiBarcodeScanner.js +6 -3
- package/dist/cjs/hooks/useMultiBarcodeScanner.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/useProductDetector.js +161 -90
- package/dist/cjs/hooks/useProductDetector.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/useReceiptScanner.js +60 -52
- package/dist/cjs/hooks/useReceiptScanner.js.map +1 -0
- package/dist/{hooks → cjs/hooks}/useVideoScanner.js +8 -5
- package/dist/cjs/hooks/useVideoScanner.js.map +1 -0
- package/dist/{index.js → cjs/index.js} +8 -4
- package/dist/cjs/index.js.map +1 -0
- package/dist/{processors → cjs/processors}/detectionProcessor.js +1 -0
- package/dist/cjs/processors/detectionProcessor.js.map +1 -0
- package/dist/{processors → cjs/processors}/index.js +1 -0
- package/dist/cjs/processors/index.js.map +1 -0
- package/dist/{processors → cjs/processors}/tfliteFrameProcessor.js +108 -25
- package/dist/cjs/processors/tfliteFrameProcessor.js.map +1 -0
- package/dist/{types → cjs/types}/barcode.js +1 -0
- package/dist/cjs/types/barcode.js.map +1 -0
- package/dist/{types → cjs/types}/detection.js +1 -0
- package/dist/cjs/types/detection.js.map +1 -0
- package/dist/{types → cjs/types}/index.js +1 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/{types → cjs/types}/ocr.js +1 -0
- package/dist/cjs/types/ocr.js.map +1 -0
- package/dist/{utils → cjs/utils}/imagePreprocessor.js +30 -25
- package/dist/cjs/utils/imagePreprocessor.js.map +1 -0
- package/dist/cjs/utils/logger.js +99 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/{utils → cjs/utils}/yoloProcessor.js +1 -0
- package/dist/cjs/utils/yoloProcessor.js.map +1 -0
- package/dist/esm/components/DetectionOverlay.js +130 -0
- package/dist/esm/components/DetectionOverlay.js.map +1 -0
- package/dist/esm/components/index.js +5 -0
- package/dist/esm/components/index.js.map +1 -0
- package/dist/esm/core/CacheManager.js +327 -0
- package/dist/esm/core/CacheManager.js.map +1 -0
- package/dist/esm/core/MLVisionProvider.js +185 -0
- package/dist/esm/core/MLVisionProvider.js.map +1 -0
- package/dist/esm/core/ServerClient.js +305 -0
- package/dist/esm/core/ServerClient.js.map +1 -0
- package/dist/esm/core/index.js +7 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/hooks/classLabels.js +436 -0
- package/dist/esm/hooks/classLabels.js.map +1 -0
- package/dist/esm/hooks/classLabelsCoco.js +98 -0
- package/dist/esm/hooks/classLabelsCoco.js.map +1 -0
- package/dist/esm/hooks/index.js +9 -0
- package/dist/esm/hooks/index.js.map +1 -0
- package/dist/esm/hooks/useMultiBarcodeScanner.js +290 -0
- package/dist/esm/hooks/useMultiBarcodeScanner.js.map +1 -0
- package/dist/esm/hooks/useProductDetector.js +714 -0
- package/dist/esm/hooks/useProductDetector.js.map +1 -0
- package/dist/esm/hooks/useReceiptScanner.js +407 -0
- package/dist/esm/hooks/useReceiptScanner.js.map +1 -0
- package/dist/esm/hooks/useVideoScanner.js +383 -0
- package/dist/esm/hooks/useVideoScanner.js.map +1 -0
- package/dist/esm/index.js +93 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/processors/detectionProcessor.js +121 -0
- package/dist/esm/processors/detectionProcessor.js.map +1 -0
- package/dist/esm/processors/index.js +7 -0
- package/dist/esm/processors/index.js.map +1 -0
- package/dist/esm/processors/tfliteFrameProcessor.js +292 -0
- package/dist/esm/processors/tfliteFrameProcessor.js.map +1 -0
- package/dist/esm/types/barcode.js +17 -0
- package/dist/esm/types/barcode.js.map +1 -0
- package/dist/esm/types/detection.js +8 -0
- package/dist/esm/types/detection.js.map +1 -0
- package/dist/esm/types/index.js +10 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/ocr.js +8 -0
- package/dist/esm/types/ocr.js.map +1 -0
- package/dist/esm/utils/imagePreprocessor.js +268 -0
- package/dist/esm/utils/imagePreprocessor.js.map +1 -0
- package/dist/esm/utils/logger.js +94 -0
- package/dist/esm/utils/logger.js.map +1 -0
- package/dist/esm/utils/yoloProcessor.js +151 -0
- package/dist/esm/utils/yoloProcessor.js.map +1 -0
- package/dist/{components → types/components}/DetectionOverlay.d.ts +1 -0
- package/dist/types/components/DetectionOverlay.d.ts.map +1 -0
- package/dist/{components → types/components}/index.d.ts +1 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/{core → types/core}/CacheManager.d.ts +1 -0
- package/dist/types/core/CacheManager.d.ts.map +1 -0
- package/dist/{core → types/core}/MLVisionProvider.d.ts +1 -0
- package/dist/types/core/MLVisionProvider.d.ts.map +1 -0
- package/dist/{core → types/core}/ServerClient.d.ts +1 -0
- package/dist/types/core/ServerClient.d.ts.map +1 -0
- package/dist/{core → types/core}/index.d.ts +1 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/classLabels.d.ts +1 -0
- package/dist/types/hooks/classLabels.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/classLabelsCoco.d.ts +1 -0
- package/dist/types/hooks/classLabelsCoco.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/index.d.ts +1 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/useMultiBarcodeScanner.d.ts +1 -0
- package/dist/types/hooks/useMultiBarcodeScanner.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/useProductDetector.d.ts +1 -0
- package/dist/types/hooks/useProductDetector.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/useReceiptScanner.d.ts +2 -1
- package/dist/types/hooks/useReceiptScanner.d.ts.map +1 -0
- package/dist/{hooks → types/hooks}/useVideoScanner.d.ts +1 -0
- package/dist/types/hooks/useVideoScanner.d.ts.map +1 -0
- package/dist/types/index.d.ts +58 -124
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{processors → types/processors}/detectionProcessor.d.ts +1 -0
- package/dist/types/processors/detectionProcessor.d.ts.map +1 -0
- package/dist/{processors → types/processors}/index.d.ts +1 -0
- package/dist/types/processors/index.d.ts.map +1 -0
- package/dist/{processors → types/processors}/tfliteFrameProcessor.d.ts +5 -4
- package/dist/types/processors/tfliteFrameProcessor.d.ts.map +1 -0
- package/dist/types/{barcode.d.ts → types/barcode.d.ts} +1 -0
- package/dist/types/types/barcode.d.ts.map +1 -0
- package/dist/types/{detection.d.ts → types/detection.d.ts} +1 -0
- package/dist/types/types/detection.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +127 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/{ocr.d.ts → types/ocr.d.ts} +1 -0
- package/dist/types/types/ocr.d.ts.map +1 -0
- package/dist/{utils → types/utils}/imagePreprocessor.d.ts +1 -0
- package/dist/types/utils/imagePreprocessor.d.ts.map +1 -0
- package/dist/types/utils/logger.d.ts +52 -0
- package/dist/types/utils/logger.d.ts.map +1 -0
- package/dist/{utils → types/utils}/yoloProcessor.d.ts +1 -0
- package/dist/types/utils/yoloProcessor.d.ts.map +1 -0
- package/package.json +62 -21
- package/dist/index.d.ts +0 -58
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* DetectionOverlay Component
|
|
4
|
+
*
|
|
5
|
+
* Renders bounding boxes over detected products.
|
|
6
|
+
* Overlay this on top of your camera view or image.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { DetectionOverlay } from '@souschef/ml-vision';
|
|
11
|
+
*
|
|
12
|
+
* function CameraScreen() {
|
|
13
|
+
* const { detections } = useProductDetector();
|
|
14
|
+
*
|
|
15
|
+
* return (
|
|
16
|
+
* <View style={styles.container}>
|
|
17
|
+
* <Camera style={StyleSheet.absoluteFill} />
|
|
18
|
+
* <DetectionOverlay
|
|
19
|
+
* detections={detections}
|
|
20
|
+
* imageWidth={screenWidth}
|
|
21
|
+
* imageHeight={screenHeight}
|
|
22
|
+
* />
|
|
23
|
+
* </View>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { useMemo } from 'react';
|
|
29
|
+
import { View, Text, StyleSheet, } from 'react-native';
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Default Colors
|
|
32
|
+
// ============================================================================
|
|
33
|
+
const DEFAULT_CATEGORY_COLORS = {
|
|
34
|
+
produce: '#4CAF50', // Green
|
|
35
|
+
meat: '#F44336', // Red
|
|
36
|
+
dairy: '#2196F3', // Blue
|
|
37
|
+
packaged: '#FF9800', // Orange
|
|
38
|
+
beverage: '#9C27B0', // Purple
|
|
39
|
+
condiment: '#FFEB3B', // Yellow
|
|
40
|
+
spice: '#795548', // Brown
|
|
41
|
+
bakery: '#FFC107', // Amber
|
|
42
|
+
frozen: '#00BCD4', // Cyan
|
|
43
|
+
snack: '#E91E63', // Pink
|
|
44
|
+
unknown: '#9E9E9E', // Gray
|
|
45
|
+
};
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Component
|
|
48
|
+
// ============================================================================
|
|
49
|
+
export function DetectionOverlay({ detections, imageWidth: _imageWidth, imageHeight: _imageHeight, showConfidence = true, showLabel = true, minConfidence = 0, categoryColors = {}, boxStyle, labelStyle, onDetectionPress, }) {
|
|
50
|
+
// Merge custom colors with defaults
|
|
51
|
+
const colors = useMemo(() => ({ ...DEFAULT_CATEGORY_COLORS, ...categoryColors }), [categoryColors]);
|
|
52
|
+
// Filter detections by confidence
|
|
53
|
+
const visibleDetections = useMemo(() => detections.filter((d) => d.confidence >= minConfidence), [detections, minConfidence]);
|
|
54
|
+
return (_jsx(View, { style: styles.container, pointerEvents: "box-none", children: visibleDetections.map((detection) => {
|
|
55
|
+
if (!detection.boundingBox)
|
|
56
|
+
return null;
|
|
57
|
+
const { x, y, width, height } = detection.boundingBox;
|
|
58
|
+
const color = colors[detection.data.category];
|
|
59
|
+
const label = detection.data.name || detection.data.classLabel;
|
|
60
|
+
const confidence = Math.round(detection.confidence * 100);
|
|
61
|
+
return (_jsx(View, { style: [
|
|
62
|
+
styles.box,
|
|
63
|
+
{
|
|
64
|
+
left: x,
|
|
65
|
+
top: y,
|
|
66
|
+
width: width,
|
|
67
|
+
height: height,
|
|
68
|
+
borderColor: color,
|
|
69
|
+
},
|
|
70
|
+
boxStyle,
|
|
71
|
+
], onTouchEnd: () => onDetectionPress?.(detection), children: (showLabel || showConfidence) && (_jsx(View, { style: [styles.labelContainer, { backgroundColor: color }], children: _jsxs(Text, { style: [styles.labelText, labelStyle], numberOfLines: 1, ellipsizeMode: "tail", children: [showLabel && label, showLabel && showConfidence && ' ', showConfidence && `${confidence}%`] }) })) }, detection.id));
|
|
72
|
+
}) }));
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Styles
|
|
76
|
+
// ============================================================================
|
|
77
|
+
const styles = StyleSheet.create({
|
|
78
|
+
container: {
|
|
79
|
+
...StyleSheet.absoluteFillObject,
|
|
80
|
+
},
|
|
81
|
+
box: {
|
|
82
|
+
position: 'absolute',
|
|
83
|
+
borderWidth: 2,
|
|
84
|
+
borderRadius: 4,
|
|
85
|
+
},
|
|
86
|
+
labelContainer: {
|
|
87
|
+
position: 'absolute',
|
|
88
|
+
top: -24,
|
|
89
|
+
left: -2,
|
|
90
|
+
paddingHorizontal: 6,
|
|
91
|
+
paddingVertical: 2,
|
|
92
|
+
borderRadius: 4,
|
|
93
|
+
minWidth: 40,
|
|
94
|
+
},
|
|
95
|
+
labelText: {
|
|
96
|
+
color: '#FFFFFF',
|
|
97
|
+
fontSize: 12,
|
|
98
|
+
fontWeight: '600',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Utility Components
|
|
103
|
+
// ============================================================================
|
|
104
|
+
/**
|
|
105
|
+
* Simple loading indicator for when model is loading
|
|
106
|
+
*/
|
|
107
|
+
export function DetectionLoadingOverlay() {
|
|
108
|
+
return (_jsx(View, { style: loadingStyles.container, children: _jsx(View, { style: loadingStyles.box, children: _jsx(Text, { style: loadingStyles.text, children: "Loading model..." }) }) }));
|
|
109
|
+
}
|
|
110
|
+
const loadingStyles = StyleSheet.create({
|
|
111
|
+
container: {
|
|
112
|
+
...StyleSheet.absoluteFillObject,
|
|
113
|
+
justifyContent: 'center',
|
|
114
|
+
alignItems: 'center',
|
|
115
|
+
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
|
116
|
+
},
|
|
117
|
+
box: {
|
|
118
|
+
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
119
|
+
paddingHorizontal: 20,
|
|
120
|
+
paddingVertical: 12,
|
|
121
|
+
borderRadius: 8,
|
|
122
|
+
},
|
|
123
|
+
text: {
|
|
124
|
+
color: '#FFFFFF',
|
|
125
|
+
fontSize: 16,
|
|
126
|
+
fontWeight: '500',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
export default DetectionOverlay;
|
|
130
|
+
//# sourceMappingURL=DetectionOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DetectionOverlay.js","sourceRoot":"","sources":["../../../src/components/DetectionOverlay.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gBAAgB,EAChB,uBAAuB,GAExB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CacheManager - MMKV-based caching for ML Vision results
|
|
3
|
+
*
|
|
4
|
+
* Provides fast, synchronous caching for:
|
|
5
|
+
* - Barcode to product lookups
|
|
6
|
+
* - Product recognition results
|
|
7
|
+
* - Receipt parsing results
|
|
8
|
+
* - Model metadata
|
|
9
|
+
*
|
|
10
|
+
* Uses react-native-mmkv for ~30x faster access than AsyncStorage.
|
|
11
|
+
*/
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Cache Configuration
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Default TTL values (in milliseconds)
|
|
17
|
+
*/
|
|
18
|
+
export const CACHE_TTL = {
|
|
19
|
+
/** Barcode lookups - 7 days */
|
|
20
|
+
BARCODE: 7 * 24 * 60 * 60 * 1000,
|
|
21
|
+
/** Product recognition - 24 hours */
|
|
22
|
+
PRODUCT: 24 * 60 * 60 * 1000,
|
|
23
|
+
/** Receipt parsing - 1 hour */
|
|
24
|
+
RECEIPT: 60 * 60 * 1000,
|
|
25
|
+
/** Model metadata - until manually cleared */
|
|
26
|
+
MODEL: Infinity,
|
|
27
|
+
/** Server responses - 5 minutes */
|
|
28
|
+
SERVER: 5 * 60 * 1000,
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Cache key prefixes for namespacing
|
|
32
|
+
*/
|
|
33
|
+
const CACHE_PREFIX = {
|
|
34
|
+
BARCODE: 'mlv_barcode_',
|
|
35
|
+
PRODUCT: 'mlv_product_',
|
|
36
|
+
RECEIPT: 'mlv_receipt_',
|
|
37
|
+
MODEL: 'mlv_model_',
|
|
38
|
+
CONFIG: 'mlv_config_',
|
|
39
|
+
};
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// CacheManager Class
|
|
42
|
+
// ============================================================================
|
|
43
|
+
/**
|
|
44
|
+
* CacheManager provides fast key-value caching using MMKV
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const cache = new CacheManager(mmkvInstance);
|
|
49
|
+
*
|
|
50
|
+
* // Cache a barcode lookup
|
|
51
|
+
* cache.setBarcode('0123456789012', {
|
|
52
|
+
* barcode: '0123456789012',
|
|
53
|
+
* format: 'ean-13',
|
|
54
|
+
* productId: 'prod_123',
|
|
55
|
+
* productName: 'Example Product',
|
|
56
|
+
* found: true,
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* // Retrieve later
|
|
60
|
+
* const product = cache.getBarcode('0123456789012');
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export class CacheManager {
|
|
64
|
+
constructor(storage, customTTL) {
|
|
65
|
+
this.storage = storage;
|
|
66
|
+
this.defaultTTL = { ...CACHE_TTL, ...customTTL };
|
|
67
|
+
}
|
|
68
|
+
// ==========================================================================
|
|
69
|
+
// Barcode Cache Methods
|
|
70
|
+
// ==========================================================================
|
|
71
|
+
/**
|
|
72
|
+
* Cache a barcode lookup result
|
|
73
|
+
*/
|
|
74
|
+
setBarcode(barcode, data, ttl) {
|
|
75
|
+
const entry = {
|
|
76
|
+
data,
|
|
77
|
+
timestamp: Date.now(),
|
|
78
|
+
ttl: ttl ?? this.defaultTTL.BARCODE,
|
|
79
|
+
};
|
|
80
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
81
|
+
this.storage.set(key, JSON.stringify(entry));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get a cached barcode lookup
|
|
85
|
+
* @returns The cached data or null if not found/expired
|
|
86
|
+
*/
|
|
87
|
+
getBarcode(barcode) {
|
|
88
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
89
|
+
const cached = this.storage.getString(key);
|
|
90
|
+
if (!cached)
|
|
91
|
+
return null;
|
|
92
|
+
try {
|
|
93
|
+
const entry = JSON.parse(cached);
|
|
94
|
+
if (this.isExpired(entry)) {
|
|
95
|
+
this.storage.delete(key);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return entry.data;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
this.storage.delete(key);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a barcode is cached
|
|
107
|
+
*/
|
|
108
|
+
hasBarcode(barcode) {
|
|
109
|
+
return this.getBarcode(barcode) !== null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Delete a cached barcode
|
|
113
|
+
*/
|
|
114
|
+
deleteBarcode(barcode) {
|
|
115
|
+
const key = `${CACHE_PREFIX.BARCODE}${barcode}`;
|
|
116
|
+
this.storage.delete(key);
|
|
117
|
+
}
|
|
118
|
+
// ==========================================================================
|
|
119
|
+
// Product Recognition Cache Methods
|
|
120
|
+
// ==========================================================================
|
|
121
|
+
/**
|
|
122
|
+
* Cache product recognition results for an image
|
|
123
|
+
* @param imageHash - Hash of the image (e.g., MD5 or perceptual hash)
|
|
124
|
+
*/
|
|
125
|
+
setProductRecognition(imageHash, data, ttl) {
|
|
126
|
+
const entry = {
|
|
127
|
+
data,
|
|
128
|
+
timestamp: Date.now(),
|
|
129
|
+
ttl: ttl ?? this.defaultTTL.PRODUCT,
|
|
130
|
+
};
|
|
131
|
+
const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
|
|
132
|
+
this.storage.set(key, JSON.stringify(entry));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get cached product recognition for an image
|
|
136
|
+
*/
|
|
137
|
+
getProductRecognition(imageHash) {
|
|
138
|
+
const key = `${CACHE_PREFIX.PRODUCT}${imageHash}`;
|
|
139
|
+
const cached = this.storage.getString(key);
|
|
140
|
+
if (!cached)
|
|
141
|
+
return null;
|
|
142
|
+
try {
|
|
143
|
+
const entry = JSON.parse(cached);
|
|
144
|
+
if (this.isExpired(entry)) {
|
|
145
|
+
this.storage.delete(key);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return entry.data;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
this.storage.delete(key);
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// ==========================================================================
|
|
156
|
+
// Model Metadata Cache Methods
|
|
157
|
+
// ==========================================================================
|
|
158
|
+
/**
|
|
159
|
+
* Store model metadata
|
|
160
|
+
*/
|
|
161
|
+
setModelMetadata(modelId, metadata) {
|
|
162
|
+
const key = `${CACHE_PREFIX.MODEL}${modelId}`;
|
|
163
|
+
this.storage.set(key, JSON.stringify(metadata));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get model metadata
|
|
167
|
+
*/
|
|
168
|
+
getModelMetadata(modelId) {
|
|
169
|
+
const key = `${CACHE_PREFIX.MODEL}${modelId}`;
|
|
170
|
+
const cached = this.storage.getString(key);
|
|
171
|
+
if (!cached)
|
|
172
|
+
return null;
|
|
173
|
+
try {
|
|
174
|
+
return JSON.parse(cached);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// ==========================================================================
|
|
181
|
+
// Config Cache Methods
|
|
182
|
+
// ==========================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Store a configuration value
|
|
185
|
+
*/
|
|
186
|
+
setConfig(key, value) {
|
|
187
|
+
const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
|
|
188
|
+
this.storage.set(fullKey, JSON.stringify(value));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get a configuration value
|
|
192
|
+
*/
|
|
193
|
+
getConfig(key, defaultValue) {
|
|
194
|
+
const fullKey = `${CACHE_PREFIX.CONFIG}${key}`;
|
|
195
|
+
const cached = this.storage.getString(fullKey);
|
|
196
|
+
if (!cached)
|
|
197
|
+
return defaultValue;
|
|
198
|
+
try {
|
|
199
|
+
return JSON.parse(cached);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return defaultValue;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ==========================================================================
|
|
206
|
+
// Cache Management Methods
|
|
207
|
+
// ==========================================================================
|
|
208
|
+
/**
|
|
209
|
+
* Clear all expired entries from the cache
|
|
210
|
+
* Call this periodically (e.g., on app start)
|
|
211
|
+
*/
|
|
212
|
+
cleanupExpired() {
|
|
213
|
+
let removed = 0;
|
|
214
|
+
const allKeys = this.storage.getAllKeys();
|
|
215
|
+
for (const key of allKeys) {
|
|
216
|
+
// Only process our prefixed keys
|
|
217
|
+
const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
|
|
218
|
+
if (!isOurKey)
|
|
219
|
+
continue;
|
|
220
|
+
// Skip model metadata (no TTL)
|
|
221
|
+
if (key.startsWith(CACHE_PREFIX.MODEL))
|
|
222
|
+
continue;
|
|
223
|
+
const value = this.storage.getString(key);
|
|
224
|
+
if (!value)
|
|
225
|
+
continue;
|
|
226
|
+
try {
|
|
227
|
+
const entry = JSON.parse(value);
|
|
228
|
+
if (this.isExpired(entry)) {
|
|
229
|
+
this.storage.delete(key);
|
|
230
|
+
removed++;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// Invalid entry, remove it
|
|
235
|
+
this.storage.delete(key);
|
|
236
|
+
removed++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return removed;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Clear all ML Vision cache entries
|
|
243
|
+
*/
|
|
244
|
+
clearAll() {
|
|
245
|
+
const allKeys = this.storage.getAllKeys();
|
|
246
|
+
for (const key of allKeys) {
|
|
247
|
+
const isOurKey = Object.values(CACHE_PREFIX).some((prefix) => key.startsWith(prefix));
|
|
248
|
+
if (isOurKey) {
|
|
249
|
+
this.storage.delete(key);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Clear cache by type
|
|
255
|
+
*/
|
|
256
|
+
clearByType(type) {
|
|
257
|
+
const prefix = CACHE_PREFIX[type];
|
|
258
|
+
const allKeys = this.storage.getAllKeys();
|
|
259
|
+
for (const key of allKeys) {
|
|
260
|
+
if (key.startsWith(prefix)) {
|
|
261
|
+
this.storage.delete(key);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Get cache statistics
|
|
267
|
+
*/
|
|
268
|
+
getStats() {
|
|
269
|
+
const allKeys = this.storage.getAllKeys();
|
|
270
|
+
let barcodeEntries = 0;
|
|
271
|
+
let productEntries = 0;
|
|
272
|
+
let receiptEntries = 0;
|
|
273
|
+
let totalSizeBytes = 0;
|
|
274
|
+
for (const key of allKeys) {
|
|
275
|
+
if (key.startsWith(CACHE_PREFIX.BARCODE)) {
|
|
276
|
+
barcodeEntries++;
|
|
277
|
+
}
|
|
278
|
+
else if (key.startsWith(CACHE_PREFIX.PRODUCT)) {
|
|
279
|
+
productEntries++;
|
|
280
|
+
}
|
|
281
|
+
else if (key.startsWith(CACHE_PREFIX.RECEIPT)) {
|
|
282
|
+
receiptEntries++;
|
|
283
|
+
}
|
|
284
|
+
// Estimate size
|
|
285
|
+
const value = this.storage.getString(key);
|
|
286
|
+
if (value) {
|
|
287
|
+
totalSizeBytes += key.length + value.length;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
barcodeEntries,
|
|
292
|
+
productEntries,
|
|
293
|
+
receiptEntries,
|
|
294
|
+
totalSizeBytes,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
// ==========================================================================
|
|
298
|
+
// Private Helper Methods
|
|
299
|
+
// ==========================================================================
|
|
300
|
+
/**
|
|
301
|
+
* Check if a cache entry has expired
|
|
302
|
+
*/
|
|
303
|
+
isExpired(entry) {
|
|
304
|
+
if (entry.ttl === Infinity)
|
|
305
|
+
return false;
|
|
306
|
+
return Date.now() - entry.timestamp > entry.ttl;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// ============================================================================
|
|
310
|
+
// Factory Function
|
|
311
|
+
// ============================================================================
|
|
312
|
+
/**
|
|
313
|
+
* Create a CacheManager instance
|
|
314
|
+
* This is the recommended way to create a CacheManager
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* import { MMKV } from 'react-native-mmkv';
|
|
319
|
+
*
|
|
320
|
+
* const storage = new MMKV({ id: 'ml-vision-cache' });
|
|
321
|
+
* const cache = createCacheManager(storage);
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
export function createCacheManager(storage, customTTL) {
|
|
325
|
+
return new CacheManager(storage, customTTL);
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=CacheManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheManager.js","sourceRoot":"","sources":["../../../src/core/CacheManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,+BAA+B;IAC/B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IAChC,qCAAqC;IACrC,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IAC5B,+BAA+B;IAC/B,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IACvB,8CAA8C;IAC9C,KAAK,EAAE,QAAQ;IACf,mCAAmC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;CACb,CAAC;AAEX;;GAEG;AACH,MAAM,YAAY,GAAG;IACnB,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,cAAc;IACvB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,aAAa;CACb,CAAC;AA+BX,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,YAAY;IAIvB,YAAY,OAAa,EAAE,SAAqC;QAC9D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;IACnD,CAAC;IAED,6EAA6E;IAC7E,wBAAwB;IACxB,6EAA6E;IAE7E;;OAEG;IACH,UAAU,CAAC,OAAe,EAAE,IAAyB,EAAE,GAAY;QACjE,MAAM,KAAK,GAAoC;YAC7C,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO;SACpC,CAAC;QACF,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,OAAO,GAAG,OAAO,EAAE,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,OAAe;QACxB,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,OAAO,GAAG,OAAO,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAoC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,OAAe;QACxB,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,OAAe;QAC3B,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,OAAO,GAAG,OAAO,EAAE,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,6EAA6E;IAC7E,oCAAoC;IACpC,6EAA6E;IAE7E;;;OAGG;IACH,qBAAqB,CACnB,SAAiB,EACjB,IAA8B,EAC9B,GAAY;QAEZ,MAAM,KAAK,GAAyC;YAClD,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO;SACpC,CAAC;QACF,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,OAAO,GAAG,SAAS,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,qBAAqB,CAAC,SAAiB;QACrC,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,OAAO,GAAG,SAAS,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAyC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACvE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,+BAA+B;IAC/B,6EAA6E;IAE7E;;OAEG;IACH,gBAAgB,CAAC,OAAe,EAAE,QAAiC;QACjE,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,gBAAgB,CAA8B,OAAe;QAC3D,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,6EAA6E;IAE7E;;OAEG;IACH,SAAS,CAAI,GAAW,EAAE,KAAQ;QAChC,MAAM,OAAO,GAAG,GAAG,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,SAAS,CAAI,GAAW,EAAE,YAAe;QACvC,MAAM,OAAO,GAAG,GAAG,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAE/C,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC;QAEjC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,2BAA2B;IAC3B,6EAA6E;IAE7E;;;OAGG;IACH,cAAc;QACZ,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,iCAAiC;YACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC3D,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CACvB,CAAC;YACF,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAExB,+BAA+B;YAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC;gBAAE,SAAS;YAEjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAwB,CAAC;gBACvD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBACzB,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;gBAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC3D,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CACvB,CAAC;YACF,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,IAA+B;QACzC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1C,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,cAAc,GAAG,CAAC,CAAC;QAEvB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,cAAc,EAAE,CAAC;YACnB,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChD,cAAc,EAAE,CAAC;YACnB,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChD,cAAc,EAAE,CAAC;YACnB,CAAC;YAED,gBAAgB;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,cAAc,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,OAAO;YACL,cAAc;YACd,cAAc;YACd,cAAc;YACd,cAAc;SACf,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,yBAAyB;IACzB,6EAA6E;IAE7E;;OAEG;IACK,SAAS,CAAC,KAA0B;QAC1C,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC;IAClD,CAAC;CACF;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAa,EACb,SAAqC;IAErC,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* MLVisionProvider - Context provider for ML Vision functionality
|
|
4
|
+
*
|
|
5
|
+
* Provides:
|
|
6
|
+
* - Configuration management
|
|
7
|
+
* - Cache manager instance
|
|
8
|
+
* - Server client for fallback inference
|
|
9
|
+
* - Model manager for TFLite models
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { MLVisionProvider } from '@souschef/ml-vision';
|
|
14
|
+
*
|
|
15
|
+
* function App() {
|
|
16
|
+
* return (
|
|
17
|
+
* <MLVisionProvider
|
|
18
|
+
* config={{
|
|
19
|
+
* serverUrl: 'http://192.168.1.100:8000',
|
|
20
|
+
* cacheEnabled: true,
|
|
21
|
+
* }}
|
|
22
|
+
* >
|
|
23
|
+
* <YourApp />
|
|
24
|
+
* </MLVisionProvider>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { createContext, useContext, useEffect, useState, useCallback, useMemo, } from 'react';
|
|
30
|
+
import { createCacheManager } from './CacheManager';
|
|
31
|
+
import { createServerClient } from './ServerClient';
|
|
32
|
+
import { logger } from '../utils/logger';
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Default Configuration
|
|
35
|
+
// ============================================================================
|
|
36
|
+
const DEFAULT_CONFIG = {
|
|
37
|
+
serverUrl: '',
|
|
38
|
+
serverTimeout: 5000,
|
|
39
|
+
cacheEnabled: true,
|
|
40
|
+
cacheTTL: 24 * 60 * 60 * 1000, // 24 hours
|
|
41
|
+
modelUpdateCheck: true,
|
|
42
|
+
enableGPUDelegate: true,
|
|
43
|
+
};
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Context
|
|
46
|
+
// ============================================================================
|
|
47
|
+
const MLVisionContext = createContext(null);
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Provider Component
|
|
50
|
+
// ============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* MLVisionProvider - Wrap your app with this provider to use ML Vision hooks
|
|
53
|
+
*/
|
|
54
|
+
export function MLVisionProvider({ children, config: userConfig, storage, onInitialized, onError, }) {
|
|
55
|
+
// Merge user config with defaults
|
|
56
|
+
const [config, setConfig] = useState(() => ({
|
|
57
|
+
...DEFAULT_CONFIG,
|
|
58
|
+
...userConfig,
|
|
59
|
+
}));
|
|
60
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
61
|
+
const [serverAvailable, setServerAvailable] = useState(false);
|
|
62
|
+
const [serverHealth, setServerHealth] = useState(null);
|
|
63
|
+
// Create cache manager
|
|
64
|
+
const cacheManager = useMemo(() => {
|
|
65
|
+
if (!config.cacheEnabled || !storage) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return createCacheManager(storage);
|
|
69
|
+
}, [config.cacheEnabled, storage]);
|
|
70
|
+
// Create server client
|
|
71
|
+
const serverClient = useMemo(() => {
|
|
72
|
+
if (!config.serverUrl) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return createServerClient(config.serverUrl, config.serverTimeout);
|
|
76
|
+
}, [config.serverUrl, config.serverTimeout]);
|
|
77
|
+
// Check server health
|
|
78
|
+
const checkServerHealth = useCallback(async () => {
|
|
79
|
+
if (!serverClient) {
|
|
80
|
+
setServerAvailable(false);
|
|
81
|
+
setServerHealth(null);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const health = await serverClient.checkHealth();
|
|
86
|
+
setServerAvailable(health.status === 'healthy');
|
|
87
|
+
setServerHealth(health);
|
|
88
|
+
return health;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
setServerAvailable(false);
|
|
92
|
+
setServerHealth(null);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}, [serverClient]);
|
|
96
|
+
// Update config at runtime
|
|
97
|
+
const updateConfig = useCallback((updates) => {
|
|
98
|
+
setConfig((prev) => ({ ...prev, ...updates }));
|
|
99
|
+
}, []);
|
|
100
|
+
// Initialize on mount
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
async function initialize() {
|
|
103
|
+
try {
|
|
104
|
+
// Clean up expired cache entries
|
|
105
|
+
if (cacheManager) {
|
|
106
|
+
const removed = cacheManager.cleanupExpired();
|
|
107
|
+
if (removed > 0) {
|
|
108
|
+
logger.info(`[MLVision] Cleaned up ${removed} expired cache entries`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Check server health if configured
|
|
112
|
+
if (serverClient) {
|
|
113
|
+
await checkServerHealth();
|
|
114
|
+
}
|
|
115
|
+
setIsInitialized(true);
|
|
116
|
+
onInitialized?.();
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
const err = error instanceof Error ? error : new Error('Initialization failed');
|
|
120
|
+
logger.error('[MLVision] Initialization error:', err);
|
|
121
|
+
onError?.(err);
|
|
122
|
+
// Still mark as initialized so the app can work in offline mode
|
|
123
|
+
setIsInitialized(true);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
initialize();
|
|
127
|
+
}, [cacheManager, serverClient, checkServerHealth, onInitialized, onError]);
|
|
128
|
+
// Context value
|
|
129
|
+
const contextValue = useMemo(() => ({
|
|
130
|
+
config,
|
|
131
|
+
isInitialized,
|
|
132
|
+
cacheManager,
|
|
133
|
+
serverClient,
|
|
134
|
+
serverAvailable,
|
|
135
|
+
serverHealth,
|
|
136
|
+
checkServerHealth,
|
|
137
|
+
updateConfig,
|
|
138
|
+
}), [
|
|
139
|
+
config,
|
|
140
|
+
isInitialized,
|
|
141
|
+
cacheManager,
|
|
142
|
+
serverClient,
|
|
143
|
+
serverAvailable,
|
|
144
|
+
serverHealth,
|
|
145
|
+
checkServerHealth,
|
|
146
|
+
updateConfig,
|
|
147
|
+
]);
|
|
148
|
+
return (_jsx(MLVisionContext.Provider, { value: contextValue, children: children }));
|
|
149
|
+
}
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// Hook
|
|
152
|
+
// ============================================================================
|
|
153
|
+
/**
|
|
154
|
+
* Hook to access the MLVision context
|
|
155
|
+
*
|
|
156
|
+
* @throws Error if used outside of MLVisionProvider
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* function MyComponent() {
|
|
161
|
+
* const { config, serverAvailable, cacheManager } = useMLVisionContext();
|
|
162
|
+
*
|
|
163
|
+
* if (!serverAvailable) {
|
|
164
|
+
* console.log('Running in offline mode');
|
|
165
|
+
* }
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export function useMLVisionContext() {
|
|
170
|
+
const context = useContext(MLVisionContext);
|
|
171
|
+
if (!context) {
|
|
172
|
+
throw new Error('useMLVisionContext must be used within an MLVisionProvider. ' +
|
|
173
|
+
'Wrap your app with <MLVisionProvider> to use ML Vision hooks.');
|
|
174
|
+
}
|
|
175
|
+
return context;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Hook to check if MLVision is initialized
|
|
179
|
+
* Returns false if used outside provider (won't throw)
|
|
180
|
+
*/
|
|
181
|
+
export function useMLVisionReady() {
|
|
182
|
+
const context = useContext(MLVisionContext);
|
|
183
|
+
return context?.isInitialized ?? false;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=MLVisionProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MLVisionProvider.js","sourceRoot":"","sources":["../../../src/core/MLVisionProvider.tsx"],"names":[],"mappings":"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"}
|