canvasframework 0.3.6
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 +554 -0
- package/components/Accordion.js +252 -0
- package/components/AndroidDatePickerDialog.js +398 -0
- package/components/AppBar.js +225 -0
- package/components/Avatar.js +202 -0
- package/components/BottomNavigationBar.js +205 -0
- package/components/BottomSheet.js +374 -0
- package/components/Button.js +225 -0
- package/components/Card.js +193 -0
- package/components/Checkbox.js +180 -0
- package/components/Chip.js +212 -0
- package/components/CircularProgress.js +143 -0
- package/components/ContextMenu.js +116 -0
- package/components/DatePicker.js +257 -0
- package/components/Dialog.js +367 -0
- package/components/Divider.js +125 -0
- package/components/Drawer.js +261 -0
- package/components/FAB.js +270 -0
- package/components/FileUpload.js +315 -0
- package/components/IOSDatePickerWheel.js +268 -0
- package/components/ImageCarousel.js +193 -0
- package/components/ImageComponent.js +223 -0
- package/components/Input.js +309 -0
- package/components/List.js +94 -0
- package/components/ListItem.js +223 -0
- package/components/Modal.js +364 -0
- package/components/MultiSelectDialog.js +206 -0
- package/components/NumberInput.js +271 -0
- package/components/ProgressBar.js +88 -0
- package/components/RadioButton.js +142 -0
- package/components/SearchInput.js +315 -0
- package/components/SegmentedControl.js +202 -0
- package/components/Select.js +199 -0
- package/components/SelectDialog.js +255 -0
- package/components/Slider.js +113 -0
- package/components/Snackbar.js +243 -0
- package/components/Stepper.js +281 -0
- package/components/SwipeableListItem.js +179 -0
- package/components/Switch.js +147 -0
- package/components/Table.js +492 -0
- package/components/Tabs.js +125 -0
- package/components/Text.js +141 -0
- package/components/TextField.js +331 -0
- package/components/Toast.js +236 -0
- package/components/TreeView.js +420 -0
- package/components/Video.js +397 -0
- package/components/View.js +140 -0
- package/components/VirtualList.js +120 -0
- package/core/CanvasFramework.js +1271 -0
- package/core/CanvasWork.js +32 -0
- package/core/Component.js +153 -0
- package/core/LogicWorker.js +25 -0
- package/core/WebGLCanvasAdapter.js +1369 -0
- package/features/Column.js +43 -0
- package/features/Grid.js +47 -0
- package/features/LayoutComponent.js +43 -0
- package/features/OpenStreetMap.js +310 -0
- package/features/Positioned.js +33 -0
- package/features/PullToRefresh.js +328 -0
- package/features/Row.js +40 -0
- package/features/SignaturePad.js +257 -0
- package/features/Skeleton.js +84 -0
- package/features/Stack.js +21 -0
- package/index.js +101 -0
- package/manager/AccessibilityManager.js +107 -0
- package/manager/ErrorHandler.js +59 -0
- package/manager/FeatureFlags.js +60 -0
- package/manager/MemoryManager.js +107 -0
- package/manager/PerformanceMonitor.js +84 -0
- package/manager/SecurityManager.js +54 -0
- package/package.json +28 -0
- package/utils/AnimationEngine.js +428 -0
- package/utils/DataStore.js +403 -0
- package/utils/EventBus.js +407 -0
- package/utils/FetchClient.js +74 -0
- package/utils/FormValidator.js +355 -0
- package/utils/GeoLocationService.js +62 -0
- package/utils/I18n.js +207 -0
- package/utils/IndexedDBManager.js +273 -0
- package/utils/OfflineSyncManager.js +342 -0
- package/utils/QueryBuilder.js +478 -0
- package/utils/SafeArea.js +64 -0
- package/utils/SecureStorage.js +289 -0
- package/utils/StateManager.js +207 -0
- package/utils/WebSocketClient.js +66 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache local avec TTL (Time To Live) et gestion avancée
|
|
3
|
+
* @class
|
|
4
|
+
* @property {Map} store - Stockage interne
|
|
5
|
+
* @property {number} defaultTTL - TTL par défaut en ms
|
|
6
|
+
* @property {number} maxSize - Taille max du cache
|
|
7
|
+
* @property {Object} stats - Statistiques du cache
|
|
8
|
+
*/
|
|
9
|
+
class DataStore {
|
|
10
|
+
/**
|
|
11
|
+
* Crée une instance de DataStore
|
|
12
|
+
* @param {Object} [options={}] - Options
|
|
13
|
+
* @param {number} [options.defaultTTL=3600000] - TTL par défaut (1h)
|
|
14
|
+
* @param {number} [options.maxSize=100] - Taille max du cache
|
|
15
|
+
* @param {boolean} [options.enableStats=true] - Activer les stats
|
|
16
|
+
*/
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.store = new Map();
|
|
19
|
+
this.defaultTTL = options.defaultTTL || 3600000; // 1 heure par défaut
|
|
20
|
+
this.maxSize = options.maxSize || 100;
|
|
21
|
+
this.enableStats = options.enableStats !== false;
|
|
22
|
+
|
|
23
|
+
// Statistiques
|
|
24
|
+
this.stats = {
|
|
25
|
+
hits: 0,
|
|
26
|
+
misses: 0,
|
|
27
|
+
sets: 0,
|
|
28
|
+
deletes: 0,
|
|
29
|
+
evictions: 0
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Nettoyage périodique
|
|
33
|
+
this.startCleanupInterval();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Stocke une valeur avec TTL
|
|
38
|
+
* @param {string} key - Clé
|
|
39
|
+
* @param {*} value - Valeur
|
|
40
|
+
* @param {number} [ttl] - TTL en ms (optionnel)
|
|
41
|
+
* @returns {DataStore} Instance pour chaînage
|
|
42
|
+
*/
|
|
43
|
+
set(key, value, ttl) {
|
|
44
|
+
const expiresAt = Date.now() + (ttl || this.defaultTTL);
|
|
45
|
+
|
|
46
|
+
// Si le cache est plein, supprimer l'élément le plus ancien
|
|
47
|
+
if (this.store.size >= this.maxSize && !this.store.has(key)) {
|
|
48
|
+
this.evictOldest();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.store.set(key, {
|
|
52
|
+
value,
|
|
53
|
+
expiresAt,
|
|
54
|
+
createdAt: Date.now(),
|
|
55
|
+
accessCount: 0
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (this.enableStats) this.stats.sets++;
|
|
59
|
+
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Récupère une valeur
|
|
65
|
+
* @param {string} key - Clé
|
|
66
|
+
* @param {*} [defaultValue=null] - Valeur par défaut
|
|
67
|
+
* @returns {*} Valeur ou null
|
|
68
|
+
*/
|
|
69
|
+
get(key, defaultValue = null) {
|
|
70
|
+
const item = this.store.get(key);
|
|
71
|
+
|
|
72
|
+
if (!item) {
|
|
73
|
+
if (this.enableStats) this.stats.misses++;
|
|
74
|
+
return defaultValue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Vérifier l'expiration
|
|
78
|
+
if (Date.now() > item.expiresAt) {
|
|
79
|
+
this.delete(key);
|
|
80
|
+
if (this.enableStats) this.stats.misses++;
|
|
81
|
+
return defaultValue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Mettre à jour les stats d'accès
|
|
85
|
+
item.accessCount++;
|
|
86
|
+
|
|
87
|
+
if (this.enableStats) this.stats.hits++;
|
|
88
|
+
|
|
89
|
+
return item.value;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Vérifie si une clé existe et n'est pas expirée
|
|
94
|
+
* @param {string} key - Clé
|
|
95
|
+
* @returns {boolean} True si existe et valide
|
|
96
|
+
*/
|
|
97
|
+
has(key) {
|
|
98
|
+
const item = this.store.get(key);
|
|
99
|
+
|
|
100
|
+
if (!item) return false;
|
|
101
|
+
|
|
102
|
+
if (Date.now() > item.expiresAt) {
|
|
103
|
+
this.delete(key);
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Supprime une entrée
|
|
112
|
+
* @param {string} key - Clé
|
|
113
|
+
* @returns {boolean} True si supprimé
|
|
114
|
+
*/
|
|
115
|
+
delete(key) {
|
|
116
|
+
const deleted = this.store.delete(key);
|
|
117
|
+
if (deleted && this.enableStats) this.stats.deletes++;
|
|
118
|
+
return deleted;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Vide tout le cache
|
|
123
|
+
*/
|
|
124
|
+
clear() {
|
|
125
|
+
this.store.clear();
|
|
126
|
+
if (this.enableStats) {
|
|
127
|
+
this.stats = {
|
|
128
|
+
hits: 0,
|
|
129
|
+
misses: 0,
|
|
130
|
+
sets: 0,
|
|
131
|
+
deletes: 0,
|
|
132
|
+
evictions: 0
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Récupère ou calcule une valeur (memoization)
|
|
139
|
+
* @param {string} key - Clé
|
|
140
|
+
* @param {Function} factory - Fonction qui retourne la valeur
|
|
141
|
+
* @param {number} [ttl] - TTL optionnel
|
|
142
|
+
* @returns {Promise<*>} Valeur
|
|
143
|
+
*/
|
|
144
|
+
async getOrSet(key, factory, ttl) {
|
|
145
|
+
if (this.has(key)) {
|
|
146
|
+
return this.get(key);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const value = await factory();
|
|
150
|
+
this.set(key, value, ttl);
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Récupère plusieurs valeurs
|
|
156
|
+
* @param {Array<string>} keys - Clés
|
|
157
|
+
* @returns {Object} Objet clé-valeur
|
|
158
|
+
*/
|
|
159
|
+
getMany(keys) {
|
|
160
|
+
const result = {};
|
|
161
|
+
|
|
162
|
+
for (let key of keys) {
|
|
163
|
+
const value = this.get(key);
|
|
164
|
+
if (value !== null) {
|
|
165
|
+
result[key] = value;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Stocke plusieurs valeurs
|
|
174
|
+
* @param {Object} items - Objet clé-valeur
|
|
175
|
+
* @param {number} [ttl] - TTL optionnel
|
|
176
|
+
* @returns {DataStore} Instance pour chaînage
|
|
177
|
+
*/
|
|
178
|
+
setMany(items, ttl) {
|
|
179
|
+
for (let key in items) {
|
|
180
|
+
this.set(key, items[key], ttl);
|
|
181
|
+
}
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Supprime plusieurs entrées
|
|
187
|
+
* @param {Array<string>} keys - Clés
|
|
188
|
+
* @returns {number} Nombre de suppressions
|
|
189
|
+
*/
|
|
190
|
+
deleteMany(keys) {
|
|
191
|
+
let count = 0;
|
|
192
|
+
for (let key of keys) {
|
|
193
|
+
if (this.delete(key)) count++;
|
|
194
|
+
}
|
|
195
|
+
return count;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Met à jour le TTL d'une entrée
|
|
200
|
+
* @param {string} key - Clé
|
|
201
|
+
* @param {number} ttl - Nouveau TTL en ms
|
|
202
|
+
* @returns {boolean} True si mis à jour
|
|
203
|
+
*/
|
|
204
|
+
touch(key, ttl) {
|
|
205
|
+
const item = this.store.get(key);
|
|
206
|
+
|
|
207
|
+
if (!item) return false;
|
|
208
|
+
|
|
209
|
+
item.expiresAt = Date.now() + (ttl || this.defaultTTL);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Obtient le TTL restant
|
|
215
|
+
* @param {string} key - Clé
|
|
216
|
+
* @returns {number} TTL en ms, ou -1 si n'existe pas
|
|
217
|
+
*/
|
|
218
|
+
ttl(key) {
|
|
219
|
+
const item = this.store.get(key);
|
|
220
|
+
|
|
221
|
+
if (!item) return -1;
|
|
222
|
+
|
|
223
|
+
const remaining = item.expiresAt - Date.now();
|
|
224
|
+
return remaining > 0 ? remaining : -1;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Évince l'élément le plus ancien (LRU)
|
|
229
|
+
* @private
|
|
230
|
+
*/
|
|
231
|
+
evictOldest() {
|
|
232
|
+
let oldestKey = null;
|
|
233
|
+
let oldestTime = Infinity;
|
|
234
|
+
|
|
235
|
+
for (let [key, item] of this.store.entries()) {
|
|
236
|
+
// Utiliser l'accès le moins récent comme critère
|
|
237
|
+
const priority = item.createdAt - (item.accessCount * 1000);
|
|
238
|
+
|
|
239
|
+
if (priority < oldestTime) {
|
|
240
|
+
oldestTime = priority;
|
|
241
|
+
oldestKey = key;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (oldestKey) {
|
|
246
|
+
this.store.delete(oldestKey);
|
|
247
|
+
if (this.enableStats) this.stats.evictions++;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Nettoie les entrées expirées
|
|
253
|
+
* @returns {number} Nombre d'entrées nettoyées
|
|
254
|
+
*/
|
|
255
|
+
cleanup() {
|
|
256
|
+
const now = Date.now();
|
|
257
|
+
let cleaned = 0;
|
|
258
|
+
|
|
259
|
+
for (let [key, item] of this.store.entries()) {
|
|
260
|
+
if (now > item.expiresAt) {
|
|
261
|
+
this.store.delete(key);
|
|
262
|
+
cleaned++;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return cleaned;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Démarre le nettoyage automatique
|
|
271
|
+
* @param {number} [interval=60000] - Intervalle en ms (1 minute)
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
startCleanupInterval(interval = 60000) {
|
|
275
|
+
if (this.cleanupTimer) {
|
|
276
|
+
clearInterval(this.cleanupTimer);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.cleanupTimer = setInterval(() => {
|
|
280
|
+
this.cleanup();
|
|
281
|
+
}, interval);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Arrête le nettoyage automatique
|
|
286
|
+
*/
|
|
287
|
+
stopCleanupInterval() {
|
|
288
|
+
if (this.cleanupTimer) {
|
|
289
|
+
clearInterval(this.cleanupTimer);
|
|
290
|
+
this.cleanupTimer = null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Obtient toutes les clés
|
|
296
|
+
* @param {boolean} [includeExpired=false] - Inclure les expirées
|
|
297
|
+
* @returns {Array<string>} Liste des clés
|
|
298
|
+
*/
|
|
299
|
+
keys(includeExpired = false) {
|
|
300
|
+
const keys = [];
|
|
301
|
+
const now = Date.now();
|
|
302
|
+
|
|
303
|
+
for (let [key, item] of this.store.entries()) {
|
|
304
|
+
if (includeExpired || now <= item.expiresAt) {
|
|
305
|
+
keys.push(key);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return keys;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Obtient la taille du cache
|
|
314
|
+
* @returns {number} Nombre d'entrées
|
|
315
|
+
*/
|
|
316
|
+
size() {
|
|
317
|
+
return this.store.size;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Obtient les statistiques
|
|
322
|
+
* @returns {Object} Statistiques
|
|
323
|
+
*/
|
|
324
|
+
getStats() {
|
|
325
|
+
const hitRate = this.stats.hits + this.stats.misses > 0
|
|
326
|
+
? (this.stats.hits / (this.stats.hits + this.stats.misses) * 100).toFixed(2)
|
|
327
|
+
: 0;
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
...this.stats,
|
|
331
|
+
size: this.store.size,
|
|
332
|
+
hitRate: `${hitRate}%`,
|
|
333
|
+
maxSize: this.maxSize
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Réinitialise les statistiques
|
|
339
|
+
*/
|
|
340
|
+
resetStats() {
|
|
341
|
+
this.stats = {
|
|
342
|
+
hits: 0,
|
|
343
|
+
misses: 0,
|
|
344
|
+
sets: 0,
|
|
345
|
+
deletes: 0,
|
|
346
|
+
evictions: 0
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Exporte le cache en JSON
|
|
352
|
+
* @returns {string} JSON
|
|
353
|
+
*/
|
|
354
|
+
export() {
|
|
355
|
+
const data = {};
|
|
356
|
+
|
|
357
|
+
for (let [key, item] of this.store.entries()) {
|
|
358
|
+
data[key] = {
|
|
359
|
+
value: item.value,
|
|
360
|
+
expiresAt: item.expiresAt,
|
|
361
|
+
createdAt: item.createdAt
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return JSON.stringify(data);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Importe un cache depuis JSON
|
|
370
|
+
* @param {string} json - JSON
|
|
371
|
+
*/
|
|
372
|
+
import(json) {
|
|
373
|
+
const data = JSON.parse(json);
|
|
374
|
+
const now = Date.now();
|
|
375
|
+
|
|
376
|
+
for (let key in data) {
|
|
377
|
+
const item = data[key];
|
|
378
|
+
|
|
379
|
+
// Ne pas importer les entrées expirées
|
|
380
|
+
if (item.expiresAt > now) {
|
|
381
|
+
this.store.set(key, {
|
|
382
|
+
value: item.value,
|
|
383
|
+
expiresAt: item.expiresAt,
|
|
384
|
+
createdAt: item.createdAt,
|
|
385
|
+
accessCount: 0
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Détruit le store
|
|
393
|
+
*/
|
|
394
|
+
destroy() {
|
|
395
|
+
this.stopCleanupInterval();
|
|
396
|
+
this.clear();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Instance globale par défaut
|
|
401
|
+
DataStore.global = new DataStore();
|
|
402
|
+
|
|
403
|
+
export default DataStore;
|