@katlux/providers 0.1.0-alpha.81

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/dist/index.cjs ADDED
@@ -0,0 +1,2763 @@
1
+ 'use strict';
2
+
3
+ const vue = require('vue');
4
+ const nuxtAppCompat = require('@katlux/providers/nuxtAppCompat');
5
+ const providers = require('@katlux/providers');
6
+ const h3 = require('h3');
7
+ const ofetch = require('ofetch');
8
+
9
+ var EDataFilterOperator = /* @__PURE__ */ ((EDataFilterOperator2) => {
10
+ EDataFilterOperator2["Equal"] = "==";
11
+ EDataFilterOperator2["NotEqual"] = "!=";
12
+ EDataFilterOperator2["GreaterThan"] = ">";
13
+ EDataFilterOperator2["LessThan"] = "<";
14
+ EDataFilterOperator2["GreaterThanOrEqual"] = ">=";
15
+ EDataFilterOperator2["LessThanOrEqual"] = "<=";
16
+ EDataFilterOperator2["In"] = "in";
17
+ EDataFilterOperator2["NotIn"] = "nin";
18
+ EDataFilterOperator2["And"] = "and";
19
+ EDataFilterOperator2["Or"] = "or";
20
+ EDataFilterOperator2["Nand"] = "nand";
21
+ EDataFilterOperator2["Nor"] = "nor";
22
+ return EDataFilterOperator2;
23
+ })(EDataFilterOperator || {});
24
+ var ECacheStrategy = /* @__PURE__ */ ((ECacheStrategy2) => {
25
+ ECacheStrategy2["Application"] = "Application";
26
+ ECacheStrategy2["Session"] = "Session";
27
+ ECacheStrategy2["Memory"] = "Memory";
28
+ ECacheStrategy2["LocalStorage"] = "LocalStorage";
29
+ ECacheStrategy2["IndexedDB"] = "IndexedDB";
30
+ ECacheStrategy2["Cookie"] = "Cookie";
31
+ return ECacheStrategy2;
32
+ })(ECacheStrategy || {});
33
+
34
+ const useDebounce = (callback, delay) => {
35
+ let timeoutId = null;
36
+ return function(...args) {
37
+ if (timeoutId !== null) {
38
+ clearTimeout(timeoutId);
39
+ }
40
+ timeoutId = setTimeout(() => {
41
+ callback.apply(this, args);
42
+ }, delay);
43
+ };
44
+ };
45
+
46
+ class ADataProvider {
47
+ filter = vue.ref(null);
48
+ sortList = vue.ref([]);
49
+ currentPage = vue.ref(1);
50
+ pageSize = vue.ref(10);
51
+ pageData = vue.ref([]);
52
+ rowCount = vue.ref(0);
53
+ loading = vue.ref(false);
54
+ SSR = vue.ref(false);
55
+ deduplicate = vue.ref(true);
56
+ nuxtApp = null;
57
+ urlPageParam = vue.ref("");
58
+ selectedRows = vue.ref([]);
59
+ selectAll = vue.ref(false);
60
+ constructor(options) {
61
+ if (options?.nuxtApp) {
62
+ this.nuxtApp = options.nuxtApp;
63
+ } else if (undefined) {
64
+ try {
65
+ this.nuxtApp = nuxtAppCompat.getNuxtApp();
66
+ } catch {
67
+ }
68
+ }
69
+ if (options?.filter) {
70
+ this.filter.value = options.filter;
71
+ }
72
+ if (options?.sortList) {
73
+ this.sortList.value = options.sortList;
74
+ }
75
+ if (options?.pageSize) {
76
+ this.pageSize.value = options.pageSize;
77
+ }
78
+ if (options?.currentPage) {
79
+ this.currentPage.value = options.currentPage;
80
+ }
81
+ if (options?.SSR) {
82
+ this.SSR.value = options.SSR;
83
+ }
84
+ if (options?.deduplicate !== void 0) {
85
+ this.deduplicate.value = options.deduplicate;
86
+ }
87
+ if (options?.urlPageParam) {
88
+ this.urlPageParam.value = options.urlPageParam;
89
+ if (undefined) {
90
+ try {
91
+ const route = nuxtAppCompat.getRoute();
92
+ if (route) {
93
+ const pageFromUrl = route.query[options.urlPageParam];
94
+ if (pageFromUrl) {
95
+ const parsedPage = parseInt(pageFromUrl, 10);
96
+ if (!isNaN(parsedPage) && parsedPage > 0) {
97
+ this.currentPage.value = parsedPage;
98
+ }
99
+ }
100
+ }
101
+ } catch (e) {
102
+ }
103
+ }
104
+ }
105
+ vue.watch(this.currentPage, (newPage) => {
106
+ this.loadPageData();
107
+ if (undefined && this.urlPageParam.value) {
108
+ try {
109
+ const router = nuxtAppCompat.getRouter();
110
+ if (router) {
111
+ const currentQuery = { ...router.currentRoute.value.query };
112
+ if (newPage === 1) {
113
+ delete currentQuery[this.urlPageParam.value];
114
+ } else {
115
+ currentQuery[this.urlPageParam.value] = String(newPage);
116
+ }
117
+ router.replace({ query: currentQuery });
118
+ }
119
+ } catch (e) {
120
+ }
121
+ }
122
+ });
123
+ vue.watch(this.pageSize, () => {
124
+ this.currentPage.value = 1;
125
+ this.loadPageData();
126
+ });
127
+ vue.watch(this.filter, useDebounce(() => {
128
+ this.currentPage.value = 1;
129
+ this.loadPageData();
130
+ }, 300));
131
+ vue.watch(this.sortList, () => {
132
+ this.currentPage.value = 1;
133
+ this.loadPageData();
134
+ });
135
+ }
136
+ setFilter(filter) {
137
+ this.filter.value = filter;
138
+ }
139
+ setSortList(sortList) {
140
+ this.sortList.value = sortList;
141
+ }
142
+ setCurrentPage(currentPage) {
143
+ this.currentPage.value = currentPage;
144
+ }
145
+ setPageSize(pageSize) {
146
+ this.pageSize.value = pageSize;
147
+ }
148
+ async refresh(hardRefresh = false) {
149
+ this.loadPageData();
150
+ }
151
+ }
152
+
153
+ const useFilterLogic = () => {
154
+ const evaluateFilter = (filter, row) => {
155
+ if (filter.operator === providers.EDataFilterOperator.And || filter.operator === providers.EDataFilterOperator.Or || filter.operator === providers.EDataFilterOperator.Nand || filter.operator === providers.EDataFilterOperator.Nor) {
156
+ return !filter.active || applyOperator(filter.operator, row, filter.field);
157
+ }
158
+ if ("operator" in filter.field && "field" in filter.field) {
159
+ return !filter.active || evaluateFilter(filter.field, row);
160
+ }
161
+ const field = filter.field;
162
+ const fieldKeys = Object.keys(field);
163
+ return !filter.active || fieldKeys.every((key) => {
164
+ const filterValue = field[key];
165
+ const rowValue = row[key];
166
+ return applyOperator(filter.operator, rowValue, filterValue);
167
+ });
168
+ };
169
+ const applyOperator = (operator, rowValue, filterValue) => {
170
+ switch (operator) {
171
+ case providers.EDataFilterOperator.And:
172
+ return compareAnd(rowValue, filterValue);
173
+ case providers.EDataFilterOperator.Or:
174
+ return compareOr(rowValue, filterValue);
175
+ case providers.EDataFilterOperator.Nand:
176
+ return !compareAnd(rowValue, filterValue);
177
+ case providers.EDataFilterOperator.Nor:
178
+ return !compareOr(rowValue, filterValue);
179
+ case providers.EDataFilterOperator.Equal:
180
+ return compareEqual(rowValue, filterValue);
181
+ case providers.EDataFilterOperator.NotEqual:
182
+ return !compareEqual(rowValue, filterValue);
183
+ case providers.EDataFilterOperator.GreaterThan:
184
+ return compareValues(rowValue, filterValue) > 0;
185
+ case providers.EDataFilterOperator.LessThan:
186
+ return compareValues(rowValue, filterValue) < 0;
187
+ case providers.EDataFilterOperator.GreaterThanOrEqual:
188
+ return compareValues(rowValue, filterValue) >= 0;
189
+ case providers.EDataFilterOperator.LessThanOrEqual:
190
+ return compareValues(rowValue, filterValue) <= 0;
191
+ case providers.EDataFilterOperator.In:
192
+ return compareIn(rowValue, filterValue);
193
+ case providers.EDataFilterOperator.NotIn:
194
+ return !compareIn(rowValue, filterValue);
195
+ default:
196
+ return compareEqual(rowValue, filterValue);
197
+ }
198
+ };
199
+ const compareAnd = (row, nested) => {
200
+ const subFilters = Array.isArray(nested) ? nested : nested && typeof nested === "object" ? Object.values(nested) : [];
201
+ const validFilters = subFilters.filter((f) => f && typeof f === "object" && "operator" in f && "field" in f);
202
+ if (validFilters.length === 0) return true;
203
+ return validFilters.every((f) => {
204
+ const active = f.active !== false;
205
+ return active ? evaluateFilter(f, row) : true;
206
+ });
207
+ };
208
+ const compareOr = (row, nested) => {
209
+ const subFilters = Array.isArray(nested) ? nested : nested && typeof nested === "object" ? Object.values(nested) : [];
210
+ const validFilters = subFilters.filter((f) => f && typeof f === "object" && "operator" in f && "field" in f);
211
+ const activeFilters = validFilters.filter((f) => f.active !== false);
212
+ if (activeFilters.length === 0) return true;
213
+ return activeFilters.some((f) => {
214
+ return evaluateFilter(f, row);
215
+ });
216
+ };
217
+ const compareIn = (rowValue, filterValue) => {
218
+ if (typeof rowValue === "string" && typeof filterValue === "string") {
219
+ return rowValue.toLowerCase().includes(filterValue.toLowerCase());
220
+ }
221
+ return false;
222
+ };
223
+ const compareEqual = (rowValue, filterValue) => {
224
+ if (typeof rowValue === "string" && typeof filterValue === "string") {
225
+ return rowValue.toLowerCase() == filterValue.toLowerCase();
226
+ }
227
+ if (typeof rowValue === "number" && typeof filterValue === "number") {
228
+ return rowValue === filterValue;
229
+ }
230
+ if (typeof rowValue === "boolean" && typeof filterValue === "boolean") {
231
+ return rowValue === filterValue;
232
+ }
233
+ return rowValue === filterValue;
234
+ };
235
+ const compareValues = (rowValue, filterValue) => {
236
+ if (rowValue == null || filterValue == null) {
237
+ return rowValue == null ? -1 : 1;
238
+ }
239
+ if (typeof rowValue === "string" && typeof filterValue === "string") {
240
+ return rowValue.localeCompare(filterValue);
241
+ }
242
+ if (typeof rowValue === "number" && typeof filterValue === "number") {
243
+ return rowValue - filterValue;
244
+ }
245
+ return String(rowValue).localeCompare(String(filterValue));
246
+ };
247
+ const filterTreeData = (nodes, filter, options) => {
248
+ const { idKey, parentKey } = options;
249
+ const nodeMap = new Map(nodes.map((node) => [node[idKey], node]));
250
+ const childrenMap = /* @__PURE__ */ new Map();
251
+ nodes.forEach((node) => {
252
+ const pId = node[parentKey];
253
+ if (pId != null) {
254
+ if (!childrenMap.has(pId)) {
255
+ childrenMap.set(pId, []);
256
+ }
257
+ childrenMap.get(pId).push(node);
258
+ }
259
+ });
260
+ const matchingNodeIds = /* @__PURE__ */ new Set();
261
+ const expandedNodes = /* @__PURE__ */ new Set();
262
+ const visibleNodeIds = /* @__PURE__ */ new Set();
263
+ nodes.forEach((node) => {
264
+ const evalRow = node.data ? { ...node.data, ...node } : node;
265
+ if (evaluateFilter(filter, evalRow)) {
266
+ matchingNodeIds.add(node[idKey]);
267
+ }
268
+ });
269
+ const addDescendants = (nodeId) => {
270
+ const children = childrenMap.get(nodeId);
271
+ if (children && children.length > 0) {
272
+ expandedNodes.add(nodeId);
273
+ children.forEach((child) => {
274
+ visibleNodeIds.add(child[idKey]);
275
+ addDescendants(child[idKey]);
276
+ });
277
+ }
278
+ };
279
+ matchingNodeIds.forEach((id) => {
280
+ visibleNodeIds.add(id);
281
+ addDescendants(id);
282
+ let currentId = id;
283
+ while (currentId != null) {
284
+ visibleNodeIds.add(currentId);
285
+ const node = nodeMap.get(currentId);
286
+ if (node) {
287
+ if (node[parentKey] != null) {
288
+ expandedNodes.add(node[parentKey]);
289
+ currentId = node[parentKey];
290
+ } else {
291
+ currentId = null;
292
+ }
293
+ } else {
294
+ break;
295
+ }
296
+ }
297
+ });
298
+ const visibleNodes = nodes.filter((node) => visibleNodeIds.has(node[idKey]));
299
+ return {
300
+ visibleNodes,
301
+ expandedNodes
302
+ };
303
+ };
304
+ const filterData = (data, filter, options) => {
305
+ if (options?.treeOptions) {
306
+ const { visibleNodes, expandedNodes } = filterTreeData(
307
+ data,
308
+ filter,
309
+ options.treeOptions
310
+ );
311
+ return { results: visibleNodes, expandedNodes };
312
+ }
313
+ const results = data.filter((row) => evaluateFilter(filter, row));
314
+ return { results };
315
+ };
316
+ return {
317
+ evaluateFilter,
318
+ filterTreeData,
319
+ filterData
320
+ };
321
+ };
322
+
323
+ const useSortLogic = () => {
324
+ const sortData = (sortList, rows) => {
325
+ if (!sortList || sortList.length === 0 || !rows || rows.length === 0) {
326
+ return rows;
327
+ }
328
+ const sortedRows = [...rows];
329
+ const compare = (a, b) => {
330
+ for (const sort of sortList) {
331
+ const aVal = a[sort.field];
332
+ const bVal = b[sort.field];
333
+ if (aVal === null || aVal === void 0) {
334
+ if (bVal === null || bVal === void 0) continue;
335
+ return sort.direction === "asc" ? -1 : 1;
336
+ }
337
+ if (bVal === null || bVal === void 0) {
338
+ return sort.direction === "asc" ? 1 : -1;
339
+ }
340
+ if (aVal < bVal) {
341
+ return sort.direction === "asc" ? -1 : 1;
342
+ } else if (aVal > bVal) {
343
+ return sort.direction === "asc" ? 1 : -1;
344
+ }
345
+ }
346
+ return 0;
347
+ };
348
+ const merge = (left, right) => {
349
+ const result = [];
350
+ let leftIndex = 0;
351
+ let rightIndex = 0;
352
+ while (leftIndex < left.length && rightIndex < right.length) {
353
+ if (compare(left[leftIndex], right[rightIndex]) <= 0) {
354
+ result.push(left[leftIndex]);
355
+ leftIndex++;
356
+ } else {
357
+ result.push(right[rightIndex]);
358
+ rightIndex++;
359
+ }
360
+ }
361
+ return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
362
+ };
363
+ const mergeSort = (arr) => {
364
+ if (arr.length <= 1) {
365
+ return arr;
366
+ }
367
+ const mid = Math.floor(arr.length / 2);
368
+ const left = mergeSort(arr.slice(0, mid));
369
+ const right = mergeSort(arr.slice(mid));
370
+ return merge(left, right);
371
+ };
372
+ return mergeSort(sortedRows);
373
+ };
374
+ return {
375
+ sortData
376
+ };
377
+ };
378
+
379
+ const { filterData: filterData$1 } = useFilterLogic();
380
+ const { sortData } = useSortLogic();
381
+ class CFlatClientDataProvider extends ADataProvider {
382
+ allData = vue.ref([]);
383
+ filteredData = vue.ref([]);
384
+ constructor(options) {
385
+ super(options);
386
+ }
387
+ setData(data) {
388
+ this.allData.value = [...data];
389
+ this.loadPageData();
390
+ }
391
+ async loadPageData() {
392
+ if (!this.filter.value) {
393
+ this.filteredData.value = this.allData.value;
394
+ } else {
395
+ const { results } = filterData$1(this.allData.value, this.filter.value);
396
+ this.filteredData.value = results;
397
+ }
398
+ this.rowCount.value = this.filteredData.value.length;
399
+ if (this.sortList.value.length > 0)
400
+ this.filteredData.value = sortData(this.sortList.value, this.filteredData.value);
401
+ if (this.pageSize.value <= 0) {
402
+ this.pageData.value = this.filteredData.value;
403
+ } else {
404
+ const startIndex = (this.currentPage.value - 1) * this.pageSize.value;
405
+ const endIndex = startIndex + this.pageSize.value;
406
+ this.pageData.value = this.filteredData.value.slice(startIndex, endIndex);
407
+ }
408
+ }
409
+ }
410
+
411
+ class ACacheProvider {
412
+ constructor() {
413
+ this.cleanupExpired();
414
+ }
415
+ }
416
+
417
+ class CApplicationCache extends ACacheProvider {
418
+ static instance = null;
419
+ static _storage = null;
420
+ static get storage() {
421
+ if (!this._storage) {
422
+ this._storage = /* @__PURE__ */ new Map();
423
+ }
424
+ return this._storage;
425
+ }
426
+ static getInstance() {
427
+ if (!this.instance) {
428
+ this.instance = new CApplicationCache();
429
+ }
430
+ return this.instance;
431
+ }
432
+ static getSnapshot() {
433
+ return this.storage;
434
+ }
435
+ constructor() {
436
+ super();
437
+ }
438
+ async getKeyList(nuxtApp) {
439
+ const prefix = "cache:";
440
+ const storage = CApplicationCache.storage;
441
+ return Array.from(storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
442
+ }
443
+ async get(key, nuxtApp) {
444
+ if (undefined) {
445
+ const prefixedKey = "cache:" + key;
446
+ const storage = CApplicationCache.storage;
447
+ const entry = storage.get(prefixedKey);
448
+ if (!entry) return null;
449
+ if (Date.now() - entry.timestamp > entry.lifetime) {
450
+ storage.delete(prefixedKey);
451
+ return null;
452
+ }
453
+ return entry.data;
454
+ }
455
+ return null;
456
+ }
457
+ async set(key, data, lifetime, nuxtApp) {
458
+ if (undefined) {
459
+ const prefixedKey = "cache:" + key;
460
+ const storage = CApplicationCache.storage;
461
+ storage.set(prefixedKey, {
462
+ data,
463
+ timestamp: Date.now(),
464
+ lifetime
465
+ });
466
+ }
467
+ }
468
+ async remove(key, nuxtApp) {
469
+ if (undefined) {
470
+ const prefixedKey = "cache:" + key;
471
+ CApplicationCache.storage.delete(prefixedKey);
472
+ }
473
+ }
474
+ async removeByPrefix(prefix, nuxtApp) {
475
+ if (undefined) {
476
+ const fullPrefix = "cache:" + prefix;
477
+ const storage = CApplicationCache.storage;
478
+ const keysToDelete = [];
479
+ for (const key of storage.keys()) {
480
+ if (key.startsWith(fullPrefix)) {
481
+ keysToDelete.push(key);
482
+ }
483
+ }
484
+ for (const key of keysToDelete) {
485
+ storage.delete(key);
486
+ }
487
+ }
488
+ }
489
+ async getRemainingTime(key, nuxtApp) {
490
+ if (undefined) {
491
+ const prefixedKey = "cache:" + key;
492
+ const storage = CApplicationCache.storage;
493
+ const entry = storage.get(prefixedKey);
494
+ if (!entry) return null;
495
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
496
+ }
497
+ return null;
498
+ }
499
+ async cleanupExpired() {
500
+ if (undefined) {
501
+ const prefix = "cache:";
502
+ const now = Date.now();
503
+ const storage = CApplicationCache.storage;
504
+ const keysToDelete = [];
505
+ for (const [key, entry] of storage.entries()) {
506
+ if (key.startsWith(prefix)) {
507
+ if (now - entry.timestamp > entry.lifetime) {
508
+ keysToDelete.push(key);
509
+ }
510
+ }
511
+ }
512
+ for (const key of keysToDelete) {
513
+ storage.delete(key);
514
+ }
515
+ }
516
+ }
517
+ }
518
+
519
+ class CMemoryCache extends ACacheProvider {
520
+ static instance = null;
521
+ static _storage = null;
522
+ static get storage() {
523
+ if (!this._storage) this._storage = /* @__PURE__ */ new Map();
524
+ return this._storage;
525
+ }
526
+ static getInstance() {
527
+ if (!this.instance) {
528
+ this.instance = new CMemoryCache();
529
+ }
530
+ return this.instance;
531
+ }
532
+ constructor() {
533
+ super();
534
+ if (undefined && CMemoryCache.storage.size === 0) {
535
+ this._hydrateFromPayload();
536
+ }
537
+ }
538
+ async _hydrateFromPayload() {
539
+ try {
540
+ const nuxtApp = await nuxtAppCompat.getNuxtApp();
541
+ const payloadData = nuxtApp?.payload?.data || globalThis.__NUXT__?.payload?.data;
542
+ if (!payloadData) return;
543
+ for (const key in payloadData) {
544
+ const value = payloadData[key];
545
+ if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
546
+ if (typeof value.lifetime === "number") {
547
+ CMemoryCache.storage.set(key, value);
548
+ }
549
+ }
550
+ }
551
+ } catch (e) {
552
+ }
553
+ }
554
+ async getKeyList(nuxtApp) {
555
+ const prefix = "cache:";
556
+ return Array.from(CMemoryCache.storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
557
+ }
558
+ async get(key, nuxtApp) {
559
+ const prefixedKey = "cache:" + key;
560
+ if (undefined) {
561
+ const entry = CMemoryCache.storage.get(prefixedKey);
562
+ if (entry) {
563
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
564
+ return entry.data;
565
+ } else {
566
+ CMemoryCache.storage.delete(prefixedKey);
567
+ }
568
+ }
569
+ }
570
+ try {
571
+ let payloadData = null;
572
+ if (undefined) {
573
+ payloadData = globalThis.__NUXT__?.payload?.data;
574
+ } else if (nuxtApp) {
575
+ payloadData = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
576
+ }
577
+ if (payloadData && payloadData[prefixedKey]) {
578
+ const entry = payloadData[prefixedKey];
579
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
580
+ if (undefined) {
581
+ CMemoryCache.storage.set(prefixedKey, entry);
582
+ }
583
+ return entry.data;
584
+ }
585
+ }
586
+ } catch (e) {
587
+ }
588
+ return null;
589
+ }
590
+ async set(key, data, lifetime, nuxtApp) {
591
+ const prefixedKey = "cache:" + key;
592
+ const entry = {
593
+ data,
594
+ timestamp: Date.now(),
595
+ lifetime
596
+ };
597
+ if (undefined && nuxtApp) {
598
+ try {
599
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
600
+ if (payload) {
601
+ payload[prefixedKey] = entry;
602
+ }
603
+ } catch (e) {
604
+ }
605
+ }
606
+ if (undefined) {
607
+ CMemoryCache.storage.set(prefixedKey, entry);
608
+ }
609
+ }
610
+ async remove(key, nuxtApp) {
611
+ const prefixedKey = "cache:" + key;
612
+ CMemoryCache.storage.delete(prefixedKey);
613
+ if (undefined && nuxtApp) {
614
+ try {
615
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
616
+ if (payload && payload[prefixedKey]) {
617
+ delete payload[prefixedKey];
618
+ }
619
+ } catch (e) {
620
+ }
621
+ }
622
+ }
623
+ async removeByPrefix(prefix, nuxtApp) {
624
+ const fullPrefix = "cache:" + prefix;
625
+ const keysToDelete = [];
626
+ for (const key of CMemoryCache.storage.keys()) {
627
+ if (key.startsWith(fullPrefix)) {
628
+ keysToDelete.push(key);
629
+ }
630
+ }
631
+ for (const key of keysToDelete) {
632
+ CMemoryCache.storage.delete(key);
633
+ }
634
+ if (undefined && nuxtApp) {
635
+ try {
636
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
637
+ if (payload) {
638
+ for (const key in payload) {
639
+ if (key.startsWith(fullPrefix)) {
640
+ delete payload[key];
641
+ }
642
+ }
643
+ }
644
+ } catch (e) {
645
+ }
646
+ }
647
+ }
648
+ async getRemainingTime(key, nuxtApp) {
649
+ const prefixedKey = "cache:" + key;
650
+ const entry = CMemoryCache.storage.get(prefixedKey);
651
+ if (!entry) return null;
652
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
653
+ }
654
+ async cleanupExpired() {
655
+ const prefix = "cache:";
656
+ const now = Date.now();
657
+ const keysToDelete = [];
658
+ for (const [key, entry] of CMemoryCache.storage.entries()) {
659
+ if (key.startsWith(prefix)) {
660
+ if (now - entry.timestamp > entry.lifetime) {
661
+ keysToDelete.push(key);
662
+ }
663
+ }
664
+ }
665
+ for (const key of keysToDelete) {
666
+ CMemoryCache.storage.delete(key);
667
+ }
668
+ }
669
+ }
670
+
671
+ class CLocalStorageCache extends ACacheProvider {
672
+ static instance = null;
673
+ static getInstance() {
674
+ if (!this.instance) {
675
+ this.instance = new CLocalStorageCache();
676
+ }
677
+ return this.instance;
678
+ }
679
+ type = "LocalStorage";
680
+ constructor() {
681
+ super();
682
+ if (undefined) {
683
+ this._hydrateFromPayload();
684
+ }
685
+ }
686
+ async _hydrateFromPayload() {
687
+ try {
688
+ const nuxtApp = await nuxtAppCompat.getNuxtApp();
689
+ const payloadData = nuxtApp?.payload?.data || window.__NUXT__?.payload?.data;
690
+ if (!payloadData) return;
691
+ const prefix = "cache:";
692
+ let count = 0;
693
+ for (const key in payloadData) {
694
+ if (key.startsWith(prefix)) {
695
+ const value = payloadData[key];
696
+ if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
697
+ try {
698
+ localStorage.setItem(key, JSON.stringify(value));
699
+ count++;
700
+ } catch (e) {
701
+ }
702
+ }
703
+ }
704
+ }
705
+ if (count > 0) console.log(`[CLocalStorageCache] Hydrated ${count} entries from payload`);
706
+ } catch (e) {
707
+ }
708
+ }
709
+ async getKeyList(nuxtApp) {
710
+ if (!undefined) return [];
711
+ const prefix = "cache:";
712
+ return Object.keys(localStorage).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
713
+ }
714
+ async get(key, nuxtApp) {
715
+ const prefixedKey = "cache:" + key;
716
+ if (undefined) {
717
+ try {
718
+ const stored = localStorage.getItem(prefixedKey);
719
+ if (stored) {
720
+ const entry = JSON.parse(stored);
721
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
722
+ console.log(`[CLocalStorageCache] GET SUCCESS: ${key}`);
723
+ return entry.data;
724
+ } else {
725
+ console.log(`[CLocalStorageCache] EXPIRED: ${key}`);
726
+ localStorage.removeItem(prefixedKey);
727
+ }
728
+ } else {
729
+ console.log(`[CLocalStorageCache] NOT IN STORAGE: ${key}`);
730
+ }
731
+ } catch (e) {
732
+ }
733
+ }
734
+ try {
735
+ let payloadData = null;
736
+ if (undefined) {
737
+ payloadData = window.__NUXT__?.payload?.data;
738
+ } else if (nuxtApp) {
739
+ payloadData = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
740
+ }
741
+ if (payloadData && payloadData[prefixedKey]) {
742
+ const entry = payloadData[prefixedKey];
743
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
744
+ if (undefined) {
745
+ localStorage.setItem(prefixedKey, JSON.stringify(entry));
746
+ }
747
+ return entry.data;
748
+ }
749
+ }
750
+ } catch (e) {
751
+ }
752
+ return null;
753
+ }
754
+ async set(key, data, lifetime, nuxtApp) {
755
+ const prefixedKey = "cache:" + key;
756
+ const entry = {
757
+ data,
758
+ timestamp: Date.now(),
759
+ lifetime
760
+ };
761
+ if (undefined && nuxtApp) {
762
+ try {
763
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
764
+ if (payload) {
765
+ payload[prefixedKey] = entry;
766
+ }
767
+ } catch (e) {
768
+ }
769
+ }
770
+ if (undefined) {
771
+ try {
772
+ localStorage.setItem(prefixedKey, JSON.stringify(entry));
773
+ } catch (e) {
774
+ }
775
+ }
776
+ }
777
+ async remove(key, nuxtApp) {
778
+ const prefixedKey = "cache:" + key;
779
+ if (undefined) {
780
+ localStorage.removeItem(prefixedKey);
781
+ }
782
+ if (undefined && nuxtApp) {
783
+ try {
784
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
785
+ if (payload && payload[prefixedKey]) {
786
+ delete payload[prefixedKey];
787
+ }
788
+ } catch (e) {
789
+ }
790
+ }
791
+ }
792
+ async removeByPrefix(prefix, nuxtApp) {
793
+ const fullPrefix = "cache:" + prefix;
794
+ if (undefined) {
795
+ const keysToDelete = [];
796
+ for (let i = 0; i < localStorage.length; i++) {
797
+ const key = localStorage.key(i);
798
+ if (key && key.startsWith(fullPrefix)) {
799
+ keysToDelete.push(key);
800
+ }
801
+ }
802
+ for (const key of keysToDelete) {
803
+ localStorage.removeItem(key);
804
+ }
805
+ }
806
+ if (undefined && nuxtApp) {
807
+ try {
808
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
809
+ if (payload) {
810
+ for (const key in payload) {
811
+ if (key.startsWith(fullPrefix)) {
812
+ delete payload[key];
813
+ }
814
+ }
815
+ }
816
+ } catch (e) {
817
+ }
818
+ }
819
+ }
820
+ async getRemainingTime(key, nuxtApp) {
821
+ if (undefined) {
822
+ const prefixedKey = "cache:" + key;
823
+ const entryStr = localStorage.getItem(prefixedKey);
824
+ if (!entryStr) return null;
825
+ try {
826
+ const entry = JSON.parse(entryStr);
827
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
828
+ } catch (e) {
829
+ return null;
830
+ }
831
+ }
832
+ return null;
833
+ }
834
+ async cleanupExpired() {
835
+ if (undefined) {
836
+ try {
837
+ const prefix = "cache:";
838
+ const now = Date.now();
839
+ const keysToDelete = [];
840
+ for (let i = 0; i < localStorage.length; i++) {
841
+ const key = localStorage.key(i);
842
+ if (key && key.startsWith(prefix)) {
843
+ const stored = localStorage.getItem(key);
844
+ if (stored) {
845
+ try {
846
+ const entry = JSON.parse(stored);
847
+ if (now - entry.timestamp > entry.lifetime) {
848
+ keysToDelete.push(key);
849
+ }
850
+ } catch (e) {
851
+ keysToDelete.push(key);
852
+ }
853
+ }
854
+ }
855
+ }
856
+ for (const key of keysToDelete) {
857
+ localStorage.removeItem(key);
858
+ }
859
+ } catch (e) {
860
+ }
861
+ }
862
+ }
863
+ }
864
+
865
+ class CIndexedDBCache extends ACacheProvider {
866
+ static instance = null;
867
+ static getInstance() {
868
+ if (!this.instance) {
869
+ this.instance = new CIndexedDBCache();
870
+ }
871
+ return this.instance;
872
+ }
873
+ dbName = "KatluxDB";
874
+ storeName = "cache";
875
+ version = 2;
876
+ dbPromise = null;
877
+ setStore(storeName = "cache") {
878
+ this.storeName = storeName || "cache";
879
+ if (undefined) {
880
+ this.dbPromise = this.openDB();
881
+ this._hydrateFromPayload();
882
+ }
883
+ }
884
+ constructor() {
885
+ super();
886
+ this.setStore();
887
+ }
888
+ async _hydrateFromPayload() {
889
+ try {
890
+ const nuxtApp = await nuxtAppCompat.getNuxtApp();
891
+ const payloadData = nuxtApp?.payload?.data || globalThis.__NUXT__?.payload?.data;
892
+ if (!payloadData) return;
893
+ const prefix = "cache:";
894
+ let count = 0;
895
+ for (const key in payloadData) {
896
+ if (key.startsWith(prefix)) {
897
+ const value = payloadData[key];
898
+ if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
899
+ this.dbPromise?.then(async (db) => {
900
+ try {
901
+ const tx = db.transaction(this.storeName, "readwrite");
902
+ const store = tx.objectStore(this.storeName);
903
+ store.put(value, key);
904
+ tx.commit?.();
905
+ } catch (e) {
906
+ }
907
+ });
908
+ count++;
909
+ }
910
+ }
911
+ }
912
+ if (count > 0) console.log(`[CIndexedDBCache] Hydrated ${count} entries from payload`);
913
+ } catch (e) {
914
+ }
915
+ }
916
+ openDB() {
917
+ return new Promise((resolve, reject) => {
918
+ const request = indexedDB.open(this.dbName, this.version);
919
+ request.onerror = () => reject(request.error);
920
+ request.onsuccess = () => resolve(request.result);
921
+ request.onupgradeneeded = (event) => {
922
+ const db = event.target.result;
923
+ if (!db.objectStoreNames.contains(this.storeName)) {
924
+ db.createObjectStore(this.storeName);
925
+ }
926
+ };
927
+ });
928
+ }
929
+ async getStore(mode) {
930
+ if (!this.dbPromise) return Promise.reject("IndexedDB not initialized");
931
+ const db = await this.dbPromise;
932
+ return db.transaction(this.storeName, mode).objectStore(this.storeName);
933
+ }
934
+ async getKeyList(nuxtApp) {
935
+ if (!undefined || !this.dbPromise) return [];
936
+ const db = await this.dbPromise;
937
+ const store = db.transaction(this.storeName, "readonly").objectStore(this.storeName);
938
+ const keys = await new Promise((resolve, reject) => {
939
+ const req = store.getAllKeys();
940
+ req.onsuccess = () => resolve(req.result);
941
+ req.onerror = () => reject(req.error);
942
+ });
943
+ const prefix = "cache:";
944
+ return keys.filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
945
+ }
946
+ async get(key, nuxtApp) {
947
+ const prefixedKey = "cache:" + key;
948
+ if (undefined) {
949
+ try {
950
+ const store = await this.getStore("readonly");
951
+ const data = await new Promise((resolve, reject) => {
952
+ const req = store.get(prefixedKey);
953
+ req.onsuccess = () => resolve(req.result);
954
+ req.onerror = () => reject(req.error);
955
+ });
956
+ if (data) {
957
+ if (Date.now() - data.timestamp <= data.lifetime) {
958
+ console.log(`[CIndexedDBCache] GET SUCCESS: ${key}`);
959
+ return data.data;
960
+ } else {
961
+ console.log(`[CIndexedDBCache] EXPIRED: ${key}`);
962
+ const writeStore = await this.getStore("readwrite");
963
+ writeStore.delete(prefixedKey);
964
+ }
965
+ } else {
966
+ console.log(`[CIndexedDBCache] NOT IN DB: ${key}`);
967
+ }
968
+ } catch (e) {
969
+ }
970
+ }
971
+ try {
972
+ let payloadData = null;
973
+ if (undefined) {
974
+ payloadData = globalThis.__NUXT__?.payload?.data;
975
+ } else if (nuxtApp) {
976
+ payloadData = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
977
+ }
978
+ if (payloadData && payloadData[prefixedKey]) {
979
+ const entry = payloadData[prefixedKey];
980
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
981
+ if (undefined) {
982
+ this.set(key, entry.data, entry.lifetime, nuxtApp);
983
+ }
984
+ return entry.data;
985
+ }
986
+ }
987
+ } catch (e) {
988
+ }
989
+ return null;
990
+ }
991
+ async set(key, data, lifetime, nuxtApp) {
992
+ const prefixedKey = "cache:" + key;
993
+ const entry = {
994
+ data,
995
+ timestamp: Date.now(),
996
+ lifetime
997
+ };
998
+ if (undefined && nuxtApp) {
999
+ try {
1000
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1001
+ if (payload) {
1002
+ payload[prefixedKey] = entry;
1003
+ }
1004
+ } catch (e) {
1005
+ }
1006
+ }
1007
+ if (undefined) {
1008
+ try {
1009
+ const store = await this.getStore("readwrite");
1010
+ await new Promise((resolve, reject) => {
1011
+ const req = store.put(entry, prefixedKey);
1012
+ req.onsuccess = () => resolve();
1013
+ req.onerror = () => reject(req.error);
1014
+ });
1015
+ } catch (e) {
1016
+ }
1017
+ }
1018
+ }
1019
+ async remove(key, nuxtApp) {
1020
+ const prefixedKey = "cache:" + key;
1021
+ if (undefined) {
1022
+ try {
1023
+ const store = await this.getStore("readwrite");
1024
+ await new Promise((resolve, reject) => {
1025
+ const req = store.delete(prefixedKey);
1026
+ req.onsuccess = () => resolve();
1027
+ req.onerror = () => reject(req.error);
1028
+ });
1029
+ } catch (e) {
1030
+ }
1031
+ }
1032
+ if (undefined && nuxtApp) {
1033
+ try {
1034
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1035
+ if (payload && payload[prefixedKey]) {
1036
+ delete payload[prefixedKey];
1037
+ }
1038
+ } catch (e) {
1039
+ }
1040
+ }
1041
+ }
1042
+ async removeByPrefix(prefix, nuxtApp) {
1043
+ const fullPrefix = "cache:" + prefix;
1044
+ if (undefined) {
1045
+ try {
1046
+ const store = await this.getStore("readwrite");
1047
+ const allKeys = await new Promise((resolve, reject) => {
1048
+ const req = store.getAllKeys();
1049
+ req.onsuccess = () => resolve(req.result);
1050
+ req.onerror = () => reject(req.error);
1051
+ });
1052
+ const keysToDelete = allKeys.filter((k) => k.startsWith(fullPrefix));
1053
+ for (const key of keysToDelete) {
1054
+ await new Promise((resolve, reject) => {
1055
+ const req = store.delete(key);
1056
+ req.onsuccess = () => resolve();
1057
+ req.onerror = () => reject(req.error);
1058
+ });
1059
+ }
1060
+ } catch (e) {
1061
+ }
1062
+ }
1063
+ if (undefined && nuxtApp) {
1064
+ try {
1065
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1066
+ if (payload) {
1067
+ for (const key in payload) {
1068
+ if (key.startsWith(fullPrefix)) {
1069
+ delete payload[key];
1070
+ }
1071
+ }
1072
+ }
1073
+ } catch (e) {
1074
+ }
1075
+ }
1076
+ }
1077
+ async getRemainingTime(key, nuxtApp) {
1078
+ if (undefined) {
1079
+ try {
1080
+ const prefixedKey = "cache:" + key;
1081
+ const store = await this.getStore("readonly");
1082
+ const entry = await new Promise((resolve, reject) => {
1083
+ const req = store.get(prefixedKey);
1084
+ req.onsuccess = () => resolve(req.result);
1085
+ req.onerror = () => reject(req.error);
1086
+ });
1087
+ if (!entry) return null;
1088
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
1089
+ } catch (e) {
1090
+ return null;
1091
+ }
1092
+ }
1093
+ return null;
1094
+ }
1095
+ async cleanupExpired() {
1096
+ if (undefined && this.dbPromise) {
1097
+ try {
1098
+ const prefix = "cache:";
1099
+ const now = Date.now();
1100
+ const keysToDelete = [];
1101
+ const store = await this.getStore("readwrite");
1102
+ const allKeys = await new Promise((resolve, reject) => {
1103
+ const req = store.getAllKeys();
1104
+ req.onsuccess = () => resolve(req.result);
1105
+ req.onerror = () => reject(req.error);
1106
+ });
1107
+ for (const key of allKeys) {
1108
+ if (key.startsWith(prefix)) {
1109
+ const entry = await new Promise((resolve, reject) => {
1110
+ const req = store.get(key);
1111
+ req.onsuccess = () => resolve(req.result);
1112
+ req.onerror = () => reject(req.error);
1113
+ });
1114
+ if (entry && now - entry.timestamp > entry.lifetime) {
1115
+ keysToDelete.push(key);
1116
+ }
1117
+ }
1118
+ }
1119
+ for (const key of keysToDelete) {
1120
+ await new Promise((resolve, reject) => {
1121
+ const req = store.delete(key);
1122
+ req.onsuccess = () => resolve();
1123
+ req.onerror = () => reject(req.error);
1124
+ });
1125
+ }
1126
+ } catch (e) {
1127
+ }
1128
+ }
1129
+ }
1130
+ }
1131
+
1132
+ class CCookieCache extends ACacheProvider {
1133
+ static instance = null;
1134
+ static getInstance() {
1135
+ if (!this.instance) {
1136
+ this.instance = new CCookieCache();
1137
+ }
1138
+ return this.instance;
1139
+ }
1140
+ type = "Cookie";
1141
+ constructor() {
1142
+ super();
1143
+ }
1144
+ async getKeyList(nuxtApp) {
1145
+ const prefix = "cache:";
1146
+ let cookieStr = "";
1147
+ if (undefined) {
1148
+ cookieStr = document.cookie;
1149
+ } else if (nuxtApp) {
1150
+ const event = nuxtApp.ssrContext?.event;
1151
+ if (event) {
1152
+ const cookies2 = h3.parseCookies(event);
1153
+ return Object.keys(cookies2).filter((k) => k.startsWith(prefix)).map((k) => k.substring(prefix.length));
1154
+ }
1155
+ }
1156
+ if (!cookieStr) return [];
1157
+ const keys = [];
1158
+ const cookies = cookieStr.split(";");
1159
+ for (let i = 0; i < cookies.length; i++) {
1160
+ const cookie = cookies[i].trim();
1161
+ const eqPos = cookie.indexOf("=");
1162
+ if (eqPos > 0) {
1163
+ const name = decodeURIComponent(cookie.substring(0, eqPos));
1164
+ if (name.startsWith(prefix)) {
1165
+ keys.push(name.substring(prefix.length));
1166
+ }
1167
+ }
1168
+ }
1169
+ return keys;
1170
+ }
1171
+ async get(key, nuxtApp) {
1172
+ const prefixedKey = "cache:" + key;
1173
+ let cookieValue = null;
1174
+ if (undefined) {
1175
+ const name = prefixedKey + "=";
1176
+ const ca = document.cookie.split(";");
1177
+ for (let i = 0; i < ca.length; i++) {
1178
+ let c = ca[i].trim();
1179
+ if (c.indexOf(name) === 0) {
1180
+ cookieValue = c.substring(name.length, c.length);
1181
+ break;
1182
+ }
1183
+ }
1184
+ } else if (nuxtApp) {
1185
+ const event = nuxtApp.ssrContext?.event;
1186
+ if (event) {
1187
+ cookieValue = h3.getCookie(event, prefixedKey) ?? null;
1188
+ }
1189
+ }
1190
+ if (!cookieValue) return null;
1191
+ try {
1192
+ const val = JSON.parse(cookieValue);
1193
+ if (val && val.timestamp && val.lifetime) {
1194
+ if (Date.now() - val.timestamp <= val.lifetime) {
1195
+ return val.data;
1196
+ } else {
1197
+ await this.set(key, null, 0, nuxtApp);
1198
+ }
1199
+ }
1200
+ return null;
1201
+ } catch (e) {
1202
+ return null;
1203
+ }
1204
+ }
1205
+ async set(key, data, lifetime, nuxtApp) {
1206
+ const prefixedKey = "cache:" + key;
1207
+ const entry = {
1208
+ data,
1209
+ timestamp: Date.now(),
1210
+ lifetime
1211
+ };
1212
+ const maxAge = Math.floor(lifetime / 1e3);
1213
+ if (undefined) {
1214
+ const cookieValue = encodeURIComponent(JSON.stringify(entry));
1215
+ document.cookie = `${prefixedKey}=${cookieValue}; Max-Age=${maxAge}; Path=/; SameSite=Lax`;
1216
+ } else if (nuxtApp) {
1217
+ const event = nuxtApp.ssrContext?.event;
1218
+ if (event) {
1219
+ h3.setCookie(event, prefixedKey, JSON.stringify(entry), {
1220
+ maxAge,
1221
+ path: "/",
1222
+ sameSite: "lax",
1223
+ httpOnly: true
1224
+ });
1225
+ }
1226
+ }
1227
+ }
1228
+ async remove(key, nuxtApp) {
1229
+ const prefixedKey = "cache:" + key;
1230
+ if (undefined) {
1231
+ document.cookie = `${prefixedKey}=; Max-Age=0; Path=/; SameSite=Lax`;
1232
+ } else if (nuxtApp) {
1233
+ const event = nuxtApp.ssrContext?.event;
1234
+ if (event) {
1235
+ h3.deleteCookie(event, prefixedKey, { path: "/", sameSite: "lax", httpOnly: true });
1236
+ }
1237
+ }
1238
+ }
1239
+ async getRemainingTime(key, nuxtApp) {
1240
+ const prefixedKey = "cache:" + key;
1241
+ let cookieValue = null;
1242
+ if (undefined) {
1243
+ const name = prefixedKey + "=";
1244
+ const ca = document.cookie.split(";");
1245
+ for (let i = 0; i < ca.length; i++) {
1246
+ let c = ca[i].trim();
1247
+ if (c.indexOf(name) === 0) {
1248
+ cookieValue = c.substring(name.length, c.length);
1249
+ break;
1250
+ }
1251
+ }
1252
+ } else if (nuxtApp) {
1253
+ const event = nuxtApp.ssrContext?.event;
1254
+ if (event) {
1255
+ cookieValue = h3.getCookie(event, prefixedKey) ?? null;
1256
+ }
1257
+ }
1258
+ if (!cookieValue) return null;
1259
+ try {
1260
+ const val = JSON.parse(cookieValue);
1261
+ if (val && val.timestamp && val.lifetime) {
1262
+ return Math.max(0, val.timestamp + val.lifetime - Date.now());
1263
+ }
1264
+ return null;
1265
+ } catch (e) {
1266
+ return null;
1267
+ }
1268
+ }
1269
+ async cleanupExpired() {
1270
+ if (undefined) {
1271
+ const prefix = "cache:";
1272
+ const now = Date.now();
1273
+ const cookies = document.cookie.split(";");
1274
+ for (let i = 0; i < cookies.length; i++) {
1275
+ const cookie = cookies[i].trim();
1276
+ const eqPos = cookie.indexOf("=");
1277
+ if (eqPos > 0) {
1278
+ const name = decodeURIComponent(cookie.substring(0, eqPos));
1279
+ if (name.startsWith(prefix)) {
1280
+ const value = decodeURIComponent(cookie.substring(eqPos + 1));
1281
+ try {
1282
+ const entry = JSON.parse(value);
1283
+ if (now - entry.timestamp > entry.lifetime) {
1284
+ document.cookie = `${encodeURIComponent(name)}=; max-age=0; path=/`;
1285
+ }
1286
+ } catch (e) {
1287
+ document.cookie = `${encodeURIComponent(name)}=; max-age=0; path=/`;
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ }
1293
+ }
1294
+ }
1295
+
1296
+ class CSessionCache extends ACacheProvider {
1297
+ static instance = null;
1298
+ static getInstance() {
1299
+ if (!this.instance) {
1300
+ this.instance = new CSessionCache();
1301
+ }
1302
+ return this.instance;
1303
+ }
1304
+ // Use global symbol to share storage across module instances (API vs App)
1305
+ static get storage() {
1306
+ const globalKey = Symbol.for("Katlux_CSessionCache_Storage");
1307
+ const _global = globalThis;
1308
+ if (!_global[globalKey]) {
1309
+ _global[globalKey] = /* @__PURE__ */ new Map();
1310
+ }
1311
+ return _global[globalKey];
1312
+ }
1313
+ static getSnapshot() {
1314
+ return this.storage;
1315
+ }
1316
+ sessionIdCache = null;
1317
+ sessionId = null;
1318
+ SESSION_ID_KEY = "_session_id";
1319
+ constructor() {
1320
+ super();
1321
+ this.sessionIdCache = CCookieCache.getInstance();
1322
+ }
1323
+ /**
1324
+ * Generate a UUID v4 sessionId
1325
+ */
1326
+ generateSessionId() {
1327
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1328
+ const r = Math.random() * 16 | 0;
1329
+ const v = c === "x" ? r : r & 3 | 8;
1330
+ return v.toString(16);
1331
+ });
1332
+ }
1333
+ /**
1334
+ * Get or create sessionId
1335
+ */
1336
+ async getSessionId(nuxtApp) {
1337
+ if (this.sessionId) {
1338
+ return this.sessionId;
1339
+ }
1340
+ if (!this.sessionIdCache) {
1341
+ return this.generateSessionId();
1342
+ }
1343
+ const existingId = await this.sessionIdCache.get(this.SESSION_ID_KEY, nuxtApp);
1344
+ if (existingId) {
1345
+ this.sessionId = existingId;
1346
+ return existingId;
1347
+ }
1348
+ const newId = this.generateSessionId();
1349
+ this.sessionId = newId;
1350
+ if (this.sessionIdCache) {
1351
+ await this.sessionIdCache.set(this.SESSION_ID_KEY, newId, 365 * 24 * 60 * 60 * 1e3, nuxtApp);
1352
+ }
1353
+ return newId;
1354
+ }
1355
+ async getKeyList(nuxtApp) {
1356
+ const prefix = "cache:";
1357
+ if (undefined) {
1358
+ return Object.keys(sessionStorage).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
1359
+ }
1360
+ const sessionId = await this.getSessionId(nuxtApp);
1361
+ const sessionData = CSessionCache.storage.get(sessionId);
1362
+ if (!sessionData) {
1363
+ return [];
1364
+ }
1365
+ return Array.from(sessionData.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
1366
+ }
1367
+ async get(key, nuxtApp) {
1368
+ const prefixedKey = "cache:" + key;
1369
+ if (undefined) {
1370
+ try {
1371
+ const stored = sessionStorage.getItem(prefixedKey);
1372
+ if (stored) {
1373
+ const entry = JSON.parse(stored);
1374
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
1375
+ return entry.data;
1376
+ } else {
1377
+ sessionStorage.removeItem(prefixedKey);
1378
+ }
1379
+ }
1380
+ } catch (e) {
1381
+ }
1382
+ try {
1383
+ const payloadData = window.__NUXT__?.payload?.data;
1384
+ if (payloadData && payloadData[prefixedKey]) {
1385
+ const entry = payloadData[prefixedKey];
1386
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
1387
+ window.sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
1388
+ return entry.data;
1389
+ }
1390
+ }
1391
+ } catch (e) {
1392
+ }
1393
+ return null;
1394
+ }
1395
+ if (undefined) {
1396
+ const sessionId = await this.getSessionId(nuxtApp);
1397
+ const sessionData = CSessionCache.storage.get(sessionId);
1398
+ if (!sessionData) {
1399
+ return null;
1400
+ }
1401
+ const entry = sessionData.get(prefixedKey);
1402
+ if (!entry) {
1403
+ return null;
1404
+ }
1405
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
1406
+ return entry.data;
1407
+ } else {
1408
+ sessionData.delete(prefixedKey);
1409
+ return null;
1410
+ }
1411
+ }
1412
+ return null;
1413
+ }
1414
+ async set(key, data, lifetime, nuxtApp) {
1415
+ const prefixedKey = "cache:" + key;
1416
+ const entry = {
1417
+ data,
1418
+ timestamp: Date.now(),
1419
+ lifetime
1420
+ };
1421
+ if (undefined) {
1422
+ try {
1423
+ sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
1424
+ } catch (e) {
1425
+ }
1426
+ }
1427
+ if (undefined) {
1428
+ try {
1429
+ const sessionId = await this.getSessionId(nuxtApp);
1430
+ let sessionData = CSessionCache.storage.get(sessionId);
1431
+ if (!sessionData) {
1432
+ sessionData = /* @__PURE__ */ new Map();
1433
+ CSessionCache.storage.set(sessionId, sessionData);
1434
+ }
1435
+ sessionData.set(prefixedKey, entry);
1436
+ if (nuxtApp) {
1437
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1438
+ if (payload) {
1439
+ payload[prefixedKey] = entry;
1440
+ }
1441
+ }
1442
+ } catch (e) {
1443
+ }
1444
+ }
1445
+ }
1446
+ async remove(key, nuxtApp) {
1447
+ const prefixedKey = "cache:" + key;
1448
+ if (undefined) {
1449
+ sessionStorage.removeItem(prefixedKey);
1450
+ }
1451
+ if (undefined) {
1452
+ try {
1453
+ const sessionId = await this.getSessionId(nuxtApp);
1454
+ const sessionData = CSessionCache.storage.get(sessionId);
1455
+ if (sessionData) {
1456
+ sessionData.delete(prefixedKey);
1457
+ }
1458
+ if (nuxtApp) {
1459
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1460
+ if (payload && payload[prefixedKey]) {
1461
+ delete payload[prefixedKey];
1462
+ }
1463
+ }
1464
+ } catch (e) {
1465
+ }
1466
+ }
1467
+ }
1468
+ async removeByPrefix(prefix, nuxtApp) {
1469
+ const fullPrefix = "cache:" + prefix;
1470
+ if (undefined) {
1471
+ const keysToDelete = [];
1472
+ for (let i = 0; i < sessionStorage.length; i++) {
1473
+ const key = sessionStorage.key(i);
1474
+ if (key && key.startsWith(fullPrefix)) {
1475
+ keysToDelete.push(key);
1476
+ }
1477
+ }
1478
+ for (const key of keysToDelete) {
1479
+ sessionStorage.removeItem(key);
1480
+ }
1481
+ }
1482
+ if (undefined) {
1483
+ try {
1484
+ const sessionId = await this.getSessionId(nuxtApp);
1485
+ const sessionData = CSessionCache.storage.get(sessionId);
1486
+ if (sessionData) {
1487
+ const keysToDelete = [];
1488
+ for (const key of sessionData.keys()) {
1489
+ if (key.startsWith(fullPrefix)) {
1490
+ keysToDelete.push(key);
1491
+ }
1492
+ }
1493
+ for (const key of keysToDelete) {
1494
+ sessionData.delete(key);
1495
+ }
1496
+ }
1497
+ if (nuxtApp) {
1498
+ const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
1499
+ if (payload) {
1500
+ for (const key in payload) {
1501
+ if (key.startsWith(fullPrefix)) {
1502
+ delete payload[key];
1503
+ }
1504
+ }
1505
+ }
1506
+ }
1507
+ } catch (e) {
1508
+ }
1509
+ }
1510
+ }
1511
+ async getRemainingTime(key, nuxtApp) {
1512
+ const prefixedKey = "cache:" + key;
1513
+ if (undefined) {
1514
+ const entryStr = sessionStorage.getItem(prefixedKey);
1515
+ if (!entryStr) return null;
1516
+ try {
1517
+ const entry = JSON.parse(entryStr);
1518
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
1519
+ } catch (e) {
1520
+ return null;
1521
+ }
1522
+ }
1523
+ if (undefined) {
1524
+ const sessionId = await this.getSessionId(nuxtApp);
1525
+ const sessionData = CSessionCache.storage.get(sessionId);
1526
+ if (!sessionData) return null;
1527
+ const entry = sessionData.get(prefixedKey);
1528
+ if (!entry) return null;
1529
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
1530
+ }
1531
+ return null;
1532
+ }
1533
+ async cleanupExpired() {
1534
+ const prefix = "cache:";
1535
+ const now = Date.now();
1536
+ if (undefined) {
1537
+ const keysToDelete = [];
1538
+ for (let i = 0; i < sessionStorage.length; i++) {
1539
+ const key = sessionStorage.key(i);
1540
+ if (key && key.startsWith(prefix)) {
1541
+ const stored = sessionStorage.getItem(key);
1542
+ if (stored) {
1543
+ try {
1544
+ const entry = JSON.parse(stored);
1545
+ if (now - entry.timestamp > entry.lifetime) {
1546
+ keysToDelete.push(key);
1547
+ }
1548
+ } catch (e) {
1549
+ keysToDelete.push(key);
1550
+ }
1551
+ }
1552
+ }
1553
+ }
1554
+ for (const key of keysToDelete) {
1555
+ sessionStorage.removeItem(key);
1556
+ }
1557
+ }
1558
+ if (undefined) {
1559
+ const sessionsToDelete = [];
1560
+ for (const [sessionId, sessionData] of CSessionCache.storage.entries()) {
1561
+ const keysToDelete = [];
1562
+ for (const [key, entry] of sessionData.entries()) {
1563
+ if (key.startsWith(prefix)) {
1564
+ if (now - entry.timestamp > entry.lifetime) {
1565
+ keysToDelete.push(key);
1566
+ }
1567
+ }
1568
+ }
1569
+ for (const key of keysToDelete) {
1570
+ sessionData.delete(key);
1571
+ }
1572
+ if (sessionData.size === 0) {
1573
+ sessionsToDelete.push(sessionId);
1574
+ }
1575
+ }
1576
+ for (const sessionId of sessionsToDelete) {
1577
+ CSessionCache.storage.delete(sessionId);
1578
+ }
1579
+ }
1580
+ }
1581
+ }
1582
+
1583
+ class CacheProviderFactory {
1584
+ static getProvider(strategy) {
1585
+ switch (strategy) {
1586
+ case ECacheStrategy.Application:
1587
+ return CApplicationCache.getInstance();
1588
+ case ECacheStrategy.Session:
1589
+ return CSessionCache.getInstance();
1590
+ case ECacheStrategy.Memory:
1591
+ return CMemoryCache.getInstance();
1592
+ case ECacheStrategy.LocalStorage:
1593
+ return CLocalStorageCache.getInstance();
1594
+ case ECacheStrategy.IndexedDB:
1595
+ return CIndexedDBCache.getInstance();
1596
+ case ECacheStrategy.Cookie:
1597
+ return CCookieCache.getInstance();
1598
+ default:
1599
+ return null;
1600
+ }
1601
+ }
1602
+ }
1603
+
1604
+ class RequestProvider {
1605
+ cacheProvider = null;
1606
+ cacheLifetime = 60 * 60 * 1e3;
1607
+ deduplicate = true;
1608
+ cacheKey = "";
1609
+ static requestQueue = [];
1610
+ static executing = false;
1611
+ static requestsInFlight = /* @__PURE__ */ new Map();
1612
+ lastUrl;
1613
+ lastOptions;
1614
+ dataReceivedCallback;
1615
+ constructor(provider, lifetime, deduplicate) {
1616
+ if (provider) this.setCacheProvider(provider);
1617
+ if (lifetime) this.setCacheLifetime(lifetime);
1618
+ if (deduplicate !== void 0) this.setDeduplicate(deduplicate);
1619
+ }
1620
+ setCacheProvider(provider) {
1621
+ if (!provider) {
1622
+ console.warn("RequestProvider: provider is required");
1623
+ }
1624
+ if (provider instanceof ACacheProvider) this.cacheProvider = provider;
1625
+ else this.cacheProvider = CacheProviderFactory.getProvider(provider);
1626
+ }
1627
+ setCacheLifetime(lifetime) {
1628
+ this.cacheLifetime = lifetime;
1629
+ }
1630
+ setDeduplicate(deduplicate) {
1631
+ this.deduplicate = deduplicate;
1632
+ }
1633
+ onDataReceived(callback) {
1634
+ this.dataReceivedCallback = callback;
1635
+ }
1636
+ hasLastUrl() {
1637
+ return !!this.lastUrl;
1638
+ }
1639
+ async refresh(hardRefresh = false) {
1640
+ if (!this.dataReceivedCallback) {
1641
+ return null;
1642
+ }
1643
+ if (!this.lastUrl) {
1644
+ console.warn("[RequestProvider] refresh called before any request was made.");
1645
+ return null;
1646
+ }
1647
+ const options = { ...this.lastOptions };
1648
+ if (hardRefresh) {
1649
+ options.disableCache = true;
1650
+ }
1651
+ return this.request(this.lastUrl, options);
1652
+ }
1653
+ getUniqueKey(url, options) {
1654
+ if (options?.key) return options.key;
1655
+ const { query, body, headers, method } = options || {};
1656
+ const stableStringify = (val) => JSON.stringify(val === void 0 ? null : val);
1657
+ return [
1658
+ url,
1659
+ stableStringify(query || {}),
1660
+ stableStringify(body || null),
1661
+ stableStringify(headers || {}),
1662
+ method || "GET"
1663
+ ].join("|");
1664
+ }
1665
+ registerRequest(url, options) {
1666
+ const uniqueKey = this.getUniqueKey(url, options);
1667
+ const shouldDeduplicate = options?.deduplicate ?? this.deduplicate;
1668
+ if (shouldDeduplicate && RequestProvider.requestsInFlight.has(uniqueKey)) {
1669
+ const inflightPromise = RequestProvider.requestsInFlight.get(uniqueKey);
1670
+ return inflightPromise.then((result) => {
1671
+ this.lastUrl = url;
1672
+ this.lastOptions = options;
1673
+ if (this.dataReceivedCallback) {
1674
+ this.dataReceivedCallback(result);
1675
+ }
1676
+ return result;
1677
+ });
1678
+ }
1679
+ const promise = new Promise((resolve, reject) => {
1680
+ RequestProvider.requestQueue.push({
1681
+ url,
1682
+ options,
1683
+ instance: this,
1684
+ resolve,
1685
+ reject
1686
+ });
1687
+ RequestProvider.executeAll();
1688
+ }).finally(() => {
1689
+ if (shouldDeduplicate) {
1690
+ RequestProvider.requestsInFlight.delete(uniqueKey);
1691
+ }
1692
+ });
1693
+ if (shouldDeduplicate) {
1694
+ RequestProvider.requestsInFlight.set(uniqueKey, promise);
1695
+ }
1696
+ return promise;
1697
+ }
1698
+ static executeAll() {
1699
+ if (RequestProvider.executing) return;
1700
+ if (RequestProvider.requestQueue.length === 0) return;
1701
+ RequestProvider.executing = true;
1702
+ const queue = [...RequestProvider.requestQueue];
1703
+ RequestProvider.requestQueue = [];
1704
+ queue.forEach((queuedRequest) => {
1705
+ queuedRequest.instance.request(queuedRequest.url, queuedRequest.options).then((result) => queuedRequest.resolve?.(result)).catch((error) => queuedRequest.reject?.(error instanceof Error ? error : new Error(String(error))));
1706
+ });
1707
+ Promise.resolve().then(() => {
1708
+ RequestProvider.executing = false;
1709
+ if (RequestProvider.requestQueue.length > 0) {
1710
+ RequestProvider.executeAll();
1711
+ }
1712
+ });
1713
+ }
1714
+ async request(url, options) {
1715
+ const { cacheStrategy, lifetime, query, body, headers, method } = options || {};
1716
+ const uniqueKey = this.getUniqueKey(url, options);
1717
+ const nuxtApp = options?.nuxtApp;
1718
+ let serverHeaders = {};
1719
+ if (nuxtApp && undefined) {
1720
+ const event = nuxtApp.ssrContext?.event;
1721
+ if (event) {
1722
+ const { getRequestHeader } = await import('h3');
1723
+ const cookieHeader = getRequestHeader(event, "cookie");
1724
+ if (cookieHeader) {
1725
+ serverHeaders = { cookie: cookieHeader };
1726
+ }
1727
+ }
1728
+ }
1729
+ const provider = cacheStrategy ? CacheProviderFactory.getProvider(cacheStrategy) : this.cacheProvider;
1730
+ const cacheLifetime = lifetime || this.cacheLifetime;
1731
+ const requestMethod = method || "GET";
1732
+ const isGetRequest = requestMethod === "GET";
1733
+ if (provider && isGetRequest && !options?.disableCache) {
1734
+ const cached = await provider.get(uniqueKey, nuxtApp);
1735
+ if (cached) {
1736
+ console.log(`[RequestProvider] CACHE HIT: ${url}`);
1737
+ this.lastUrl = url;
1738
+ this.lastOptions = options;
1739
+ if (this.dataReceivedCallback) {
1740
+ this.dataReceivedCallback(cached);
1741
+ }
1742
+ return cached;
1743
+ }
1744
+ console.log(`[RequestProvider] CACHE MISS: ${url}`);
1745
+ }
1746
+ const fetchOptions = {
1747
+ method: requestMethod,
1748
+ body,
1749
+ headers: { ...headers, ...serverHeaders },
1750
+ query
1751
+ };
1752
+ const responseData = await ofetch.$fetch(url, fetchOptions);
1753
+ if (provider && cacheLifetime && responseData && isGetRequest) {
1754
+ await provider.set(uniqueKey, responseData, cacheLifetime, nuxtApp);
1755
+ }
1756
+ this.lastUrl = url;
1757
+ this.lastOptions = options;
1758
+ if (this.dataReceivedCallback) {
1759
+ this.dataReceivedCallback(responseData);
1760
+ }
1761
+ return responseData;
1762
+ }
1763
+ }
1764
+
1765
+ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1766
+ apiUrl = vue.ref("");
1767
+ contextKey = vue.ref("");
1768
+ initialLoad = vue.ref(true);
1769
+ requestProvider = new RequestProvider();
1770
+ cacheStrategy = vue.ref(null);
1771
+ cacheLifetime = vue.ref(0);
1772
+ refreshOnMutation = vue.ref(void 0);
1773
+ constructor(options) {
1774
+ super(options);
1775
+ if (options?.cacheStrategy) this.cacheStrategy.value = options.cacheStrategy;
1776
+ if (options?.cacheLifetime) this.cacheLifetime.value = options.cacheLifetime;
1777
+ if (options?.refreshOnMutation !== void 0) this.refreshOnMutation.value = options.refreshOnMutation;
1778
+ this.requestProvider.onDataReceived((data) => {
1779
+ if (data) {
1780
+ this.setData(data.rows || data);
1781
+ }
1782
+ });
1783
+ }
1784
+ setContextKey(key) {
1785
+ this.contextKey.value = key;
1786
+ this.requestProvider.cacheKey = key;
1787
+ if (this.cacheStrategy.value) this.requestProvider.setCacheProvider(this.cacheStrategy.value);
1788
+ if (this.cacheLifetime.value) this.requestProvider.setCacheLifetime(this.cacheLifetime.value);
1789
+ }
1790
+ async refresh(hardRefresh = false) {
1791
+ await this.refreshData({ disableCache: hardRefresh });
1792
+ }
1793
+ async refreshData(options) {
1794
+ if (!this.requestProvider.hasLastUrl()) {
1795
+ await this._initialFetch(options?.disableCache ?? false);
1796
+ return;
1797
+ }
1798
+ this.loading.value = true;
1799
+ try {
1800
+ await this.requestProvider.refresh(options?.disableCache ?? false);
1801
+ } finally {
1802
+ this.loading.value = false;
1803
+ }
1804
+ }
1805
+ async _initialFetch(disableCache = false) {
1806
+ if (!this.SSR.value && undefined) return;
1807
+ const fetcher = async () => {
1808
+ const promise = this.requestProvider.registerRequest(this.apiUrl.value, {
1809
+ deduplicate: this.deduplicate.value,
1810
+ nuxtApp: this.nuxtApp,
1811
+ disableCache
1812
+ });
1813
+ if (this.SSR.value && undefined) return await promise;
1814
+ return promise;
1815
+ };
1816
+ const key = `${this.contextKey.value}`;
1817
+ if (this.contextKey.value && this.initialLoad.value && !disableCache) {
1818
+ const { data } = nuxtAppCompat.getNuxtData(key, this.nuxtApp);
1819
+ if (data.value) {
1820
+ const result = data.value;
1821
+ this.setData(result.rows);
1822
+ this.initialLoad.value = false;
1823
+ this.loading.value = false;
1824
+ return;
1825
+ }
1826
+ }
1827
+ if (undefined && this.contextKey.value) {
1828
+ if (disableCache) {
1829
+ nuxtAppCompat.clearNuxtDataKey(key, this.nuxtApp);
1830
+ }
1831
+ const { data } = await nuxtAppCompat.getAsyncData(key, fetcher, this.nuxtApp);
1832
+ if (data.value) {
1833
+ const result = data.value;
1834
+ this.setData(result.rows);
1835
+ this.initialLoad.value = false;
1836
+ this.loading.value = false;
1837
+ return;
1838
+ }
1839
+ }
1840
+ if (!this.SSR.value) {
1841
+ const promise = this.requestProvider.registerRequest(this.apiUrl.value, {
1842
+ deduplicate: this.deduplicate.value,
1843
+ nuxtApp: this.nuxtApp,
1844
+ disableCache
1845
+ });
1846
+ promise.then(() => {
1847
+ this.initialLoad.value = false;
1848
+ this.loading.value = false;
1849
+ }).catch(() => {
1850
+ this.initialLoad.value = false;
1851
+ this.loading.value = false;
1852
+ });
1853
+ return;
1854
+ }
1855
+ await fetcher();
1856
+ this.initialLoad.value = false;
1857
+ this.loading.value = false;
1858
+ }
1859
+ async setAPIUrl(url) {
1860
+ this.loading.value = true;
1861
+ this.apiUrl.value = url;
1862
+ this.setContextKey(url);
1863
+ if (this.allData.value.length == 0)
1864
+ await this.refreshData();
1865
+ }
1866
+ async create(item) {
1867
+ if (!this.apiUrl.value) return;
1868
+ const result = await this.requestProvider.registerRequest(this.apiUrl.value, {
1869
+ method: "POST",
1870
+ body: item,
1871
+ nuxtApp: this.nuxtApp
1872
+ });
1873
+ if (this.refreshOnMutation.value) {
1874
+ await this.refresh(true);
1875
+ } else {
1876
+ if (result && result.item) {
1877
+ this.allData.value.push(result.item);
1878
+ this.loadPageData();
1879
+ await this.refresh(true);
1880
+ }
1881
+ if (this.requestProvider.cacheProvider) {
1882
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
1883
+ }
1884
+ if (this.contextKey.value) {
1885
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
1886
+ }
1887
+ }
1888
+ }
1889
+ async update(item) {
1890
+ if (!this.apiUrl.value) return;
1891
+ const result = await this.requestProvider.registerRequest(this.apiUrl.value, {
1892
+ method: "PUT",
1893
+ body: item,
1894
+ nuxtApp: this.nuxtApp
1895
+ });
1896
+ if (this.refreshOnMutation.value) {
1897
+ await this.refresh(true);
1898
+ } else {
1899
+ const index = this.allData.value.findIndex((row) => row["id"] === item["id"]);
1900
+ if (index !== -1) {
1901
+ if (result && result.item) {
1902
+ this.allData.value[index] = result.item;
1903
+ } else {
1904
+ this.allData.value[index] = { ...this.allData.value[index], ...item };
1905
+ }
1906
+ this.loadPageData();
1907
+ }
1908
+ if (this.requestProvider.cacheProvider) {
1909
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
1910
+ }
1911
+ if (this.contextKey.value) {
1912
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
1913
+ }
1914
+ }
1915
+ }
1916
+ async delete(items) {
1917
+ if (!this.apiUrl.value) return;
1918
+ if (!items || items.length === 0) return;
1919
+ const ids = items.map((i) => i.id);
1920
+ await this.requestProvider.registerRequest(this.apiUrl.value, {
1921
+ method: "DELETE",
1922
+ body: { id: ids },
1923
+ nuxtApp: this.nuxtApp
1924
+ });
1925
+ if (this.refreshOnMutation.value) {
1926
+ await this.refresh(true);
1927
+ } else {
1928
+ const idsToDelete = new Set(ids);
1929
+ this.allData.value = this.allData.value.filter((row) => !idsToDelete.has(row["id"]));
1930
+ if (this.requestProvider.cacheProvider) {
1931
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
1932
+ }
1933
+ if (this.contextKey.value) {
1934
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
1935
+ }
1936
+ }
1937
+ }
1938
+ }
1939
+
1940
+ class CFlatServerDataProvider extends ADataProvider {
1941
+ pageDataHandler = vue.ref((currentPage, pageSize, filter, sortList) => {
1942
+ return {
1943
+ rows: [],
1944
+ rowCount: 0
1945
+ };
1946
+ });
1947
+ contextKey = vue.ref("");
1948
+ initialLoad = vue.ref(true);
1949
+ constructor(options) {
1950
+ super(options);
1951
+ }
1952
+ setContextKey(key) {
1953
+ this.contextKey.value = key;
1954
+ }
1955
+ async setPageDataHandler(handler) {
1956
+ this.pageDataHandler.value = handler;
1957
+ await this.loadPageData();
1958
+ }
1959
+ async loadPageData(options) {
1960
+ if (!this.pageDataHandler.value || !this.SSR.value && undefined) return;
1961
+ const stableStringify = (val) => JSON.stringify(val === void 0 ? "" : val);
1962
+ const key = [
1963
+ this.contextKey.value,
1964
+ this.currentPage.value,
1965
+ this.pageSize.value,
1966
+ stableStringify(this.filter.value),
1967
+ stableStringify(this.sortList.value)
1968
+ ].join("-");
1969
+ const fetcher = async () => await this.pageDataHandler.value(this.currentPage.value, this.pageSize.value, this.filter.value, this.sortList.value, options);
1970
+ if (!options?.disableCache && this.SSR.value && this.contextKey.value && this.initialLoad.value) {
1971
+ const { data } = nuxtAppCompat.getNuxtData(key, this.nuxtApp);
1972
+ if (data.value) {
1973
+ const result = data.value;
1974
+ this.pageData.value = result.rows;
1975
+ this.rowCount.value = result.rowCount;
1976
+ this.initialLoad.value = false;
1977
+ this.loading.value = false;
1978
+ return;
1979
+ }
1980
+ }
1981
+ if (this.SSR.value && this.contextKey.value && !options?.disableCache && (undefined || this.initialLoad.value)) {
1982
+ this.loading.value = true;
1983
+ const { data } = await nuxtAppCompat.getAsyncData(key, fetcher, this.nuxtApp);
1984
+ if (data.value) {
1985
+ const result = data.value;
1986
+ this.pageData.value = result.rows;
1987
+ this.rowCount.value = result.rowCount;
1988
+ this.initialLoad.value = false;
1989
+ this.loading.value = false;
1990
+ return;
1991
+ }
1992
+ }
1993
+ if (!this.SSR.value) {
1994
+ nuxtAppCompat.onNuxtReadyCallback(() => {
1995
+ this.loading.value = true;
1996
+ fetcher().then((returnedData2) => {
1997
+ this.pageData.value = returnedData2.rows;
1998
+ this.rowCount.value = returnedData2.rowCount;
1999
+ this.initialLoad.value = false;
2000
+ this.loading.value = false;
2001
+ }).catch(() => {
2002
+ this.initialLoad.value = false;
2003
+ this.loading.value = false;
2004
+ });
2005
+ });
2006
+ return;
2007
+ }
2008
+ this.loading.value = true;
2009
+ const returnedData = await fetcher();
2010
+ this.pageData.value = returnedData.rows;
2011
+ this.rowCount.value = returnedData.rowCount;
2012
+ this.initialLoad.value = false;
2013
+ this.loading.value = false;
2014
+ }
2015
+ async refresh(hardRefresh = false) {
2016
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2017
+ }
2018
+ }
2019
+
2020
+ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
2021
+ apiUrl = vue.ref("");
2022
+ requestProvider = new RequestProvider();
2023
+ cacheStrategy = vue.ref(null);
2024
+ cacheLifetime = vue.ref(0);
2025
+ refreshOnMutation = vue.ref(true);
2026
+ // Default true for server
2027
+ constructor(options) {
2028
+ super(options);
2029
+ if (options?.cacheStrategy) this.cacheStrategy.value = options.cacheStrategy;
2030
+ if (options?.cacheLifetime) this.cacheLifetime.value = options.cacheLifetime;
2031
+ if (options?.refreshOnMutation !== void 0) this.refreshOnMutation.value = options.refreshOnMutation;
2032
+ this.requestProvider.onDataReceived((data) => {
2033
+ if (data) {
2034
+ this.pageData.value = data.rows || data;
2035
+ if (data.rowCount !== void 0) {
2036
+ this.rowCount.value = data.rowCount;
2037
+ }
2038
+ }
2039
+ });
2040
+ }
2041
+ async refresh(hardRefresh = false) {
2042
+ if (hardRefresh && this.requestProvider.cacheProvider) {
2043
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2044
+ }
2045
+ this.loading.value = true;
2046
+ try {
2047
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2048
+ } finally {
2049
+ this.loading.value = false;
2050
+ }
2051
+ }
2052
+ async refreshData(options) {
2053
+ await this.refresh(options?.disableCache ?? false);
2054
+ }
2055
+ async setAPIUrl(url) {
2056
+ this.apiUrl.value = url;
2057
+ this.setContextKey(url);
2058
+ if (this.cacheStrategy.value) this.requestProvider.setCacheProvider(this.cacheStrategy.value);
2059
+ if (this.cacheLifetime.value) this.requestProvider.setCacheLifetime(this.cacheLifetime.value);
2060
+ await this.setPageDataHandler(
2061
+ async (currentPage, pageSize, filter, sortList, options) => {
2062
+ return await this.requestProvider.registerRequest(this.apiUrl.value, {
2063
+ query: {
2064
+ pageNumber: currentPage,
2065
+ pageSize,
2066
+ filter,
2067
+ sortList
2068
+ },
2069
+ deduplicate: this.deduplicate.value,
2070
+ nuxtApp: this.nuxtApp,
2071
+ disableCache: options?.disableCache
2072
+ });
2073
+ }
2074
+ );
2075
+ }
2076
+ async delete(items) {
2077
+ if (!this.apiUrl.value) return;
2078
+ if (!items || items.length === 0) return;
2079
+ const ids = items.map((i) => i.id);
2080
+ await this.requestProvider.registerRequest(this.apiUrl.value, {
2081
+ method: "DELETE",
2082
+ body: { id: ids },
2083
+ nuxtApp: this.nuxtApp
2084
+ });
2085
+ if (this.refreshOnMutation.value !== false) {
2086
+ if (this.requestProvider.cacheProvider) {
2087
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2088
+ }
2089
+ await this.refresh(true);
2090
+ }
2091
+ }
2092
+ }
2093
+
2094
+ class AAPIDataProvider {
2095
+ apiUrl = vue.ref("");
2096
+ cacheStrategy = vue.ref(null);
2097
+ cacheLifetime = vue.ref(60 * 1e3);
2098
+ requestProvider = new RequestProvider();
2099
+ refreshOnMutation = vue.ref(void 0);
2100
+ constructor(options) {
2101
+ if (options?.cacheStrategy) this.cacheStrategy.value = options.cacheStrategy;
2102
+ if (options?.cacheLifetime) this.cacheLifetime.value = options.cacheLifetime;
2103
+ if (options?.refreshOnMutation !== void 0) this.refreshOnMutation.value = options.refreshOnMutation;
2104
+ }
2105
+ }
2106
+
2107
+ const { filterData } = useFilterLogic();
2108
+ class CTreeClientDataProvider extends CFlatClientDataProvider {
2109
+ // Tree configuration
2110
+ parentKey = "parentId";
2111
+ idKey = "id";
2112
+ expandedByDefault = false;
2113
+ paginateBy = "all";
2114
+ // Tree state
2115
+ expandedNodes = vue.ref(/* @__PURE__ */ new Set());
2116
+ // Internal: static tree structure (only rebuilds when data changes)
2117
+ _staticNodes;
2118
+ _nodeMap;
2119
+ _sortedNodeIds;
2120
+ constructor(options) {
2121
+ super(options);
2122
+ if (options?.parentKey) this.parentKey = options.parentKey;
2123
+ if (options?.idKey) this.idKey = options.idKey;
2124
+ if (options?.expandedByDefault) this.expandedByDefault = options.expandedByDefault;
2125
+ if (options?.paginateBy) this.paginateBy = options.paginateBy;
2126
+ this._staticNodes = vue.computed(() => this.buildStaticNodes());
2127
+ this._nodeMap = vue.computed(() => new Map(this._staticNodes.value.map((n) => [n.id, n])));
2128
+ this._sortedNodeIds = vue.computed(() => this.computeSortedIds());
2129
+ vue.watch([this.expandedNodes, this._staticNodes], () => {
2130
+ this.updatePageData();
2131
+ }, { immediate: true });
2132
+ }
2133
+ buildStaticNodes() {
2134
+ const allData = this.allData.value || [];
2135
+ const nodeMap = /* @__PURE__ */ new Map();
2136
+ const childrenMap = /* @__PURE__ */ new Map();
2137
+ allData.forEach((item) => {
2138
+ const id = item[this.idKey];
2139
+ const parentId = item[this.parentKey] || null;
2140
+ nodeMap.set(id, {
2141
+ data: item,
2142
+ id,
2143
+ parentId,
2144
+ depth: 0,
2145
+ hasChildren: false
2146
+ });
2147
+ if (parentId !== null) {
2148
+ if (!childrenMap.has(parentId)) {
2149
+ childrenMap.set(parentId, []);
2150
+ }
2151
+ childrenMap.get(parentId).push(item);
2152
+ }
2153
+ });
2154
+ const calculateDepth = (nodeId, depth = 0) => {
2155
+ const node = nodeMap.get(nodeId);
2156
+ if (!node) return;
2157
+ node.depth = depth;
2158
+ const children = childrenMap.get(nodeId);
2159
+ if (children && children.length > 0) {
2160
+ node.hasChildren = true;
2161
+ children.forEach((child) => {
2162
+ calculateDepth(child[this.idKey], depth + 1);
2163
+ });
2164
+ }
2165
+ };
2166
+ nodeMap.forEach((node) => {
2167
+ if (node.parentId === null) {
2168
+ calculateDepth(node.id, 0);
2169
+ }
2170
+ });
2171
+ return Array.from(nodeMap.values());
2172
+ }
2173
+ // Pre-compute sorted order once (only when data changes)
2174
+ computeSortedIds() {
2175
+ const nodes = this._staticNodes.value;
2176
+ new Map(nodes.map((n) => [n.id, n]));
2177
+ const sortedIds = [];
2178
+ const rootNodes = nodes.filter((n) => n.parentId === null);
2179
+ const childrenMap = /* @__PURE__ */ new Map();
2180
+ nodes.forEach((n) => {
2181
+ if (n.parentId !== null) {
2182
+ if (!childrenMap.has(n.parentId)) {
2183
+ childrenMap.set(n.parentId, []);
2184
+ }
2185
+ childrenMap.get(n.parentId).push(n);
2186
+ }
2187
+ });
2188
+ const collectNodes = (node) => {
2189
+ sortedIds.push(node.id);
2190
+ const children = childrenMap.get(node.id) || [];
2191
+ children.forEach((child) => collectNodes(child));
2192
+ };
2193
+ rootNodes.forEach((root) => collectNodes(root));
2194
+ return sortedIds;
2195
+ }
2196
+ // Fast visibility check and page data update
2197
+ updatePageData() {
2198
+ const nodeMap = this._nodeMap.value;
2199
+ const sortedIds = this._sortedNodeIds.value;
2200
+ const visibleNodes = [];
2201
+ if (this.filter.value && this.filter.value.active) {
2202
+ const { results: filtered, expandedNodes: expandedResults } = filterData(
2203
+ this._staticNodes.value,
2204
+ this.filter.value,
2205
+ {
2206
+ treeOptions: {
2207
+ idKey: this.idKey,
2208
+ parentKey: this.parentKey
2209
+ }
2210
+ }
2211
+ );
2212
+ const expandedSet = expandedResults || /* @__PURE__ */ new Set();
2213
+ for (const node of filtered) {
2214
+ visibleNodes.push({
2215
+ ...node,
2216
+ isExpanded: expandedSet.has(node.id)
2217
+ });
2218
+ }
2219
+ } else {
2220
+ for (const id of sortedIds) {
2221
+ const staticNode = nodeMap.get(id);
2222
+ if (!staticNode) continue;
2223
+ if (this.isNodeVisible(staticNode, nodeMap)) {
2224
+ const isExpanded = this.expandedByDefault ? !this.expandedNodes.value.has(id) : this.expandedNodes.value.has(id);
2225
+ visibleNodes.push({
2226
+ ...staticNode,
2227
+ isExpanded
2228
+ });
2229
+ }
2230
+ }
2231
+ }
2232
+ const paginatedNodes = this.paginateNodes(visibleNodes);
2233
+ this.pageData.value = paginatedNodes.map((node) => ({
2234
+ ...node.data,
2235
+ __treeNode: node
2236
+ }));
2237
+ }
2238
+ isNodeVisible(node, nodeMap) {
2239
+ if (node.parentId === null) return true;
2240
+ let currentId = node.parentId;
2241
+ while (currentId !== null) {
2242
+ const parent = nodeMap.get(currentId);
2243
+ if (!parent) return false;
2244
+ const parentExpanded = this.expandedByDefault ? !this.expandedNodes.value.has(currentId) : this.expandedNodes.value.has(currentId);
2245
+ if (!parentExpanded) return false;
2246
+ currentId = parent.parentId;
2247
+ }
2248
+ return true;
2249
+ }
2250
+ paginateNodes(visible) {
2251
+ const pageSize = this.pageSize.value;
2252
+ const currentPage = this.currentPage.value;
2253
+ if (pageSize <= 0) {
2254
+ this.rowCount.value = visible.length;
2255
+ return visible;
2256
+ }
2257
+ if (this.paginateBy === "root") {
2258
+ const rootNodes = visible.filter((n) => n.parentId === null);
2259
+ const startIndex = (currentPage - 1) * pageSize;
2260
+ const endIndex = startIndex + pageSize;
2261
+ const paginatedRoots = rootNodes.slice(startIndex, endIndex);
2262
+ const paginatedRootIds = new Set(paginatedRoots.map((n) => n.id));
2263
+ const nodeMap = new Map(visible.map((n) => [n.id, n]));
2264
+ const getRootId = (node) => {
2265
+ let current = node;
2266
+ while (current.parentId !== null) {
2267
+ const parent = nodeMap.get(current.parentId);
2268
+ if (!parent) break;
2269
+ current = parent;
2270
+ }
2271
+ return current.id;
2272
+ };
2273
+ const result = visible.filter((node) => paginatedRootIds.has(getRootId(node)));
2274
+ this.rowCount.value = rootNodes.length;
2275
+ return result;
2276
+ } else {
2277
+ const startIndex = (currentPage - 1) * pageSize;
2278
+ const endIndex = startIndex + pageSize;
2279
+ this.rowCount.value = visible.length;
2280
+ return visible.slice(startIndex, endIndex);
2281
+ }
2282
+ }
2283
+ // Override loadPageData
2284
+ async loadPageData() {
2285
+ this.updatePageData();
2286
+ }
2287
+ // Public API
2288
+ get treeNodes() {
2289
+ return this._staticNodes.value.map((node) => ({
2290
+ ...node,
2291
+ isExpanded: this.expandedByDefault ? !this.expandedNodes.value.has(node.id) : this.expandedNodes.value.has(node.id)
2292
+ }));
2293
+ }
2294
+ get visibleRows() {
2295
+ const nodeMap = this._nodeMap.value;
2296
+ const sortedIds = this._sortedNodeIds.value;
2297
+ const visibleNodes = [];
2298
+ for (const id of sortedIds) {
2299
+ const staticNode = nodeMap.get(id);
2300
+ if (!staticNode) continue;
2301
+ if (this.isNodeVisible(staticNode, nodeMap)) {
2302
+ visibleNodes.push({
2303
+ ...staticNode,
2304
+ isExpanded: this.expandedByDefault ? !this.expandedNodes.value.has(id) : this.expandedNodes.value.has(id)
2305
+ });
2306
+ }
2307
+ }
2308
+ return this.paginateNodes(visibleNodes);
2309
+ }
2310
+ toggleNode(nodeId) {
2311
+ if (this.expandedNodes.value.has(nodeId)) {
2312
+ this.expandedNodes.value.delete(nodeId);
2313
+ } else {
2314
+ this.expandedNodes.value.add(nodeId);
2315
+ }
2316
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2317
+ }
2318
+ expand(nodeId) {
2319
+ this.expandedNodes.value.add(nodeId);
2320
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2321
+ }
2322
+ collapse(nodeId) {
2323
+ this.expandedNodes.value.delete(nodeId);
2324
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2325
+ }
2326
+ expandAll() {
2327
+ const allIds = this._staticNodes.value.filter((n) => n.hasChildren).map((n) => n.id);
2328
+ this.expandedNodes.value = new Set(allIds);
2329
+ }
2330
+ collapseAll() {
2331
+ this.expandedNodes.value = /* @__PURE__ */ new Set();
2332
+ }
2333
+ getNode(nodeId) {
2334
+ const staticNode = this._nodeMap.value.get(nodeId);
2335
+ if (!staticNode) return void 0;
2336
+ return {
2337
+ ...staticNode,
2338
+ isExpanded: this.expandedByDefault ? !this.expandedNodes.value.has(nodeId) : this.expandedNodes.value.has(nodeId)
2339
+ };
2340
+ }
2341
+ getChildren(nodeId) {
2342
+ return this.treeNodes.filter((n) => n.parentId === nodeId);
2343
+ }
2344
+ getParent(nodeId) {
2345
+ const node = this.getNode(nodeId);
2346
+ if (!node || node.parentId === null) return void 0;
2347
+ return this.getNode(node.parentId);
2348
+ }
2349
+ }
2350
+
2351
+ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2352
+ apiUrl = vue.ref("");
2353
+ contextKey = vue.ref("");
2354
+ initialLoad = vue.ref(true);
2355
+ requestProvider = new RequestProvider();
2356
+ cacheStrategy = vue.ref(null);
2357
+ cacheLifetime = vue.ref(0);
2358
+ refreshOnMutation = vue.ref(void 0);
2359
+ constructor(options) {
2360
+ super(options);
2361
+ if (options?.cacheStrategy) this.cacheStrategy.value = options.cacheStrategy;
2362
+ if (options?.cacheLifetime) this.cacheLifetime.value = options.cacheLifetime;
2363
+ if (options?.refreshOnMutation !== void 0) this.refreshOnMutation.value = options.refreshOnMutation;
2364
+ this.requestProvider.onDataReceived((data) => {
2365
+ if (data) {
2366
+ this.setData(data.rows || data);
2367
+ }
2368
+ });
2369
+ }
2370
+ setContextKey(key) {
2371
+ this.contextKey.value = key;
2372
+ this.requestProvider.cacheKey = key;
2373
+ if (this.cacheStrategy.value) this.requestProvider.setCacheProvider(this.cacheStrategy.value);
2374
+ if (this.cacheLifetime.value) this.requestProvider.setCacheLifetime(this.cacheLifetime.value);
2375
+ }
2376
+ async refresh(hardRefresh = false) {
2377
+ await this.refreshData({ disableCache: hardRefresh });
2378
+ }
2379
+ async refreshData(options) {
2380
+ if (!this.requestProvider.hasLastUrl()) {
2381
+ await this._initialFetch(options?.disableCache ?? false);
2382
+ return;
2383
+ }
2384
+ this.loading.value = true;
2385
+ try {
2386
+ await this.requestProvider.refresh(options?.disableCache ?? false);
2387
+ } finally {
2388
+ this.loading.value = false;
2389
+ }
2390
+ }
2391
+ async _initialFetch(disableCache = false) {
2392
+ if (!this.SSR.value && undefined) return;
2393
+ const fetcher = async () => {
2394
+ const promise = this.requestProvider.registerRequest(this.apiUrl.value, {
2395
+ deduplicate: this.deduplicate.value,
2396
+ nuxtApp: this.nuxtApp,
2397
+ disableCache
2398
+ });
2399
+ if (this.SSR.value && undefined) return await promise;
2400
+ return promise;
2401
+ };
2402
+ const key = `${this.contextKey.value}`;
2403
+ if (this.contextKey.value && this.initialLoad.value && !disableCache) {
2404
+ const { data } = nuxtAppCompat.getNuxtData(key, this.nuxtApp);
2405
+ if (data.value) {
2406
+ const result = data.value;
2407
+ this.setData(result.rows);
2408
+ this.initialLoad.value = false;
2409
+ this.loading.value = false;
2410
+ return;
2411
+ }
2412
+ }
2413
+ if (undefined && this.contextKey.value) {
2414
+ if (disableCache) {
2415
+ nuxtAppCompat.clearNuxtDataKey(key, this.nuxtApp);
2416
+ }
2417
+ const { data } = await nuxtAppCompat.getAsyncData(key, fetcher, this.nuxtApp);
2418
+ if (data.value) {
2419
+ const result = data.value;
2420
+ this.setData(result.rows);
2421
+ this.initialLoad.value = false;
2422
+ this.loading.value = false;
2423
+ return;
2424
+ }
2425
+ }
2426
+ if (!this.SSR.value) {
2427
+ const promise = this.requestProvider.registerRequest(this.apiUrl.value, {
2428
+ deduplicate: this.deduplicate.value,
2429
+ nuxtApp: this.nuxtApp,
2430
+ disableCache
2431
+ });
2432
+ promise.then(() => {
2433
+ this.initialLoad.value = false;
2434
+ this.loading.value = false;
2435
+ }).catch(() => {
2436
+ this.initialLoad.value = false;
2437
+ this.loading.value = false;
2438
+ });
2439
+ return;
2440
+ }
2441
+ await fetcher();
2442
+ this.initialLoad.value = false;
2443
+ this.loading.value = false;
2444
+ }
2445
+ async setAPIUrl(url) {
2446
+ this.loading.value = true;
2447
+ this.apiUrl.value = url;
2448
+ this.setContextKey(url);
2449
+ if (this.allData.value.length == 0)
2450
+ await this.refreshData();
2451
+ }
2452
+ async create(item) {
2453
+ if (!this.apiUrl.value) return;
2454
+ const result = await this.requestProvider.registerRequest(this.apiUrl.value, {
2455
+ method: "POST",
2456
+ body: item,
2457
+ nuxtApp: this.nuxtApp
2458
+ });
2459
+ if (this.refreshOnMutation.value) {
2460
+ await this.refresh(true);
2461
+ } else {
2462
+ if (result && result.item) {
2463
+ this.allData.value.push(result.item);
2464
+ } else {
2465
+ await this.refresh(true);
2466
+ }
2467
+ if (this.requestProvider.cacheProvider) {
2468
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2469
+ }
2470
+ if (this.contextKey.value) {
2471
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
2472
+ }
2473
+ }
2474
+ }
2475
+ async update(item) {
2476
+ if (!this.apiUrl.value) return;
2477
+ const result = await this.requestProvider.registerRequest(this.apiUrl.value, {
2478
+ method: "PUT",
2479
+ body: item,
2480
+ nuxtApp: this.nuxtApp
2481
+ });
2482
+ if (this.refreshOnMutation.value) {
2483
+ await this.refresh(true);
2484
+ } else {
2485
+ const index = this.allData.value.findIndex((row) => row[this.idKey] === item[this.idKey]);
2486
+ if (index !== -1) {
2487
+ if (result && result.item) {
2488
+ this.allData.value[index] = result.item;
2489
+ } else {
2490
+ this.allData.value[index] = { ...this.allData.value[index], ...item };
2491
+ }
2492
+ this.allData.value = [...this.allData.value];
2493
+ }
2494
+ if (this.requestProvider.cacheProvider) {
2495
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2496
+ }
2497
+ if (this.contextKey.value) {
2498
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
2499
+ }
2500
+ }
2501
+ }
2502
+ async delete(items) {
2503
+ if (!this.apiUrl.value) return;
2504
+ if (!items || items.length === 0) return;
2505
+ const ids = items.map((i) => i.id);
2506
+ await this.requestProvider.registerRequest(this.apiUrl.value, {
2507
+ method: "DELETE",
2508
+ body: { id: ids },
2509
+ nuxtApp: this.nuxtApp
2510
+ });
2511
+ if (this.refreshOnMutation.value) {
2512
+ await this.refresh(true);
2513
+ } else {
2514
+ const idsToDelete = new Set(ids);
2515
+ this.allData.value = this.allData.value.filter((row) => !idsToDelete.has(row[this.idKey]));
2516
+ if (this.requestProvider.cacheProvider) {
2517
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2518
+ }
2519
+ if (this.contextKey.value) {
2520
+ nuxtAppCompat.clearNuxtDataKey(this.contextKey.value, this.nuxtApp);
2521
+ }
2522
+ }
2523
+ }
2524
+ }
2525
+
2526
+ class CTreeServerDataProvider extends ADataProvider {
2527
+ // Tree configuration (sent to server)
2528
+ parentKey = "parentId";
2529
+ idKey = "id";
2530
+ expandedByDefault = false;
2531
+ paginateBy = "all";
2532
+ // Tree state - toggled nodes (sent to server for visibility calculation)
2533
+ expandedNodes = vue.ref(/* @__PURE__ */ new Set());
2534
+ // Server-side data handler
2535
+ pageDataHandler = vue.ref(null);
2536
+ contextKey = vue.ref("");
2537
+ initialLoad = vue.ref(true);
2538
+ constructor(options) {
2539
+ super(options);
2540
+ if (options?.parentKey) this.parentKey = options.parentKey;
2541
+ if (options?.idKey) this.idKey = options.idKey;
2542
+ if (options?.expandedByDefault) this.expandedByDefault = options.expandedByDefault;
2543
+ if (options?.paginateBy) this.paginateBy = options.paginateBy;
2544
+ vue.watch([this.expandedNodes, this.currentPage, this.pageSize], () => {
2545
+ if (this.pageDataHandler.value && !this.initialLoad.value) {
2546
+ this.loadPageData();
2547
+ }
2548
+ });
2549
+ }
2550
+ setContextKey(key) {
2551
+ this.contextKey.value = key;
2552
+ }
2553
+ async setPageDataHandler(handler) {
2554
+ this.pageDataHandler.value = handler;
2555
+ await this.loadPageData();
2556
+ }
2557
+ /**
2558
+ * Load page data from server
2559
+ * Server handles tree building, visibility, and pagination
2560
+ */
2561
+ async loadPageData(options) {
2562
+ if (!this.pageDataHandler.value || !this.SSR.value && undefined) return;
2563
+ const expandedArray = Array.from(this.expandedNodes.value);
2564
+ const stableStringify = (val) => JSON.stringify(val === void 0 ? "" : val);
2565
+ const key = [
2566
+ this.contextKey.value,
2567
+ this.currentPage.value,
2568
+ this.pageSize.value,
2569
+ stableStringify(this.filter.value),
2570
+ stableStringify(this.sortList.value),
2571
+ stableStringify(expandedArray)
2572
+ ].join("-");
2573
+ const treeParams = {
2574
+ expandedNodes: expandedArray,
2575
+ parentKey: this.parentKey,
2576
+ idKey: this.idKey,
2577
+ paginateBy: this.paginateBy,
2578
+ expandedByDefault: this.expandedByDefault
2579
+ };
2580
+ const fetcher = async () => await this.pageDataHandler.value(
2581
+ this.currentPage.value,
2582
+ this.pageSize.value,
2583
+ this.filter.value,
2584
+ this.sortList.value,
2585
+ treeParams,
2586
+ options
2587
+ );
2588
+ if (!options?.disableCache && this.SSR.value && this.contextKey.value && this.initialLoad.value) {
2589
+ const { data } = nuxtAppCompat.getNuxtData(key, this.nuxtApp);
2590
+ if (data.value) {
2591
+ const result = data.value;
2592
+ this.pageData.value = result.rows;
2593
+ this.rowCount.value = result.rowCount;
2594
+ this.initialLoad.value = false;
2595
+ this.loading.value = false;
2596
+ return;
2597
+ }
2598
+ }
2599
+ if (this.SSR.value && this.contextKey.value && !options?.disableCache && (undefined || this.initialLoad.value)) {
2600
+ this.loading.value = true;
2601
+ const { data } = await nuxtAppCompat.getAsyncData(key, fetcher, this.nuxtApp);
2602
+ if (data.value) {
2603
+ const result = data.value;
2604
+ this.pageData.value = result.rows;
2605
+ this.rowCount.value = result.rowCount;
2606
+ this.initialLoad.value = false;
2607
+ this.loading.value = false;
2608
+ return;
2609
+ }
2610
+ }
2611
+ if (!this.SSR.value) {
2612
+ nuxtAppCompat.onNuxtReadyCallback(() => {
2613
+ this.loading.value = true;
2614
+ fetcher().then((returnedData2) => {
2615
+ this.pageData.value = returnedData2.rows;
2616
+ this.rowCount.value = returnedData2.rowCount;
2617
+ this.initialLoad.value = false;
2618
+ this.loading.value = false;
2619
+ }).catch(() => {
2620
+ this.initialLoad.value = false;
2621
+ this.loading.value = false;
2622
+ });
2623
+ });
2624
+ return;
2625
+ }
2626
+ this.loading.value = true;
2627
+ const returnedData = await fetcher();
2628
+ this.pageData.value = returnedData.rows;
2629
+ this.rowCount.value = returnedData.rowCount;
2630
+ this.initialLoad.value = false;
2631
+ this.loading.value = false;
2632
+ }
2633
+ async refresh(hardRefresh = false) {
2634
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2635
+ }
2636
+ // ============================================
2637
+ // Expand/Collapse API
2638
+ // ============================================
2639
+ toggleNode(nodeId) {
2640
+ if (this.expandedNodes.value.has(nodeId)) {
2641
+ this.expandedNodes.value.delete(nodeId);
2642
+ } else {
2643
+ this.expandedNodes.value.add(nodeId);
2644
+ }
2645
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2646
+ }
2647
+ expand(nodeId) {
2648
+ this.expandedNodes.value.add(nodeId);
2649
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2650
+ }
2651
+ collapse(nodeId) {
2652
+ this.expandedNodes.value.delete(nodeId);
2653
+ this.expandedNodes.value = new Set(this.expandedNodes.value);
2654
+ }
2655
+ collapseAll() {
2656
+ this.expandedNodes.value = /* @__PURE__ */ new Set();
2657
+ }
2658
+ isExpanded(nodeId) {
2659
+ const isToggled = this.expandedNodes.value.has(nodeId);
2660
+ return this.expandedByDefault ? !isToggled : isToggled;
2661
+ }
2662
+ }
2663
+
2664
+ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2665
+ apiUrl = vue.ref("");
2666
+ requestProvider = new RequestProvider();
2667
+ cacheStrategy = vue.ref(null);
2668
+ cacheLifetime = vue.ref(0);
2669
+ refreshOnMutation = vue.ref(true);
2670
+ // Default true for server
2671
+ constructor(options) {
2672
+ super(options);
2673
+ if (options?.cacheStrategy) this.cacheStrategy.value = options.cacheStrategy;
2674
+ if (options?.cacheLifetime) this.cacheLifetime.value = options.cacheLifetime;
2675
+ if (options?.refreshOnMutation !== void 0) this.refreshOnMutation.value = options.refreshOnMutation;
2676
+ this.requestProvider.onDataReceived((data) => {
2677
+ if (data) {
2678
+ this.pageData.value = data.rows || data;
2679
+ if (data.rowCount !== void 0) {
2680
+ this.rowCount.value = data.rowCount;
2681
+ }
2682
+ }
2683
+ });
2684
+ }
2685
+ async refresh(hardRefresh = false) {
2686
+ if (hardRefresh && this.requestProvider.cacheProvider) {
2687
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2688
+ }
2689
+ this.loading.value = true;
2690
+ try {
2691
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2692
+ } finally {
2693
+ this.loading.value = false;
2694
+ }
2695
+ }
2696
+ async refreshData(options) {
2697
+ await this.refresh(options?.disableCache ?? false);
2698
+ }
2699
+ async setAPIUrl(url) {
2700
+ this.apiUrl.value = url;
2701
+ this.setContextKey(url);
2702
+ if (this.cacheStrategy.value) this.requestProvider.setCacheProvider(this.cacheStrategy.value);
2703
+ if (this.cacheLifetime.value) this.requestProvider.setCacheLifetime(this.cacheLifetime.value);
2704
+ await this.setPageDataHandler(
2705
+ async (currentPage, pageSize, filter, sortList, treeParams, options) => {
2706
+ return await this.requestProvider.registerRequest(this.apiUrl.value, {
2707
+ query: {
2708
+ pageNumber: currentPage,
2709
+ pageSize,
2710
+ filter,
2711
+ sortList,
2712
+ // Tree-specific params for server-side processing
2713
+ expandedNodes: JSON.stringify(treeParams.expandedNodes),
2714
+ parentKey: treeParams.parentKey,
2715
+ idKey: treeParams.idKey,
2716
+ paginateBy: treeParams.paginateBy,
2717
+ expandedByDefault: treeParams.expandedByDefault
2718
+ },
2719
+ deduplicate: this.deduplicate.value,
2720
+ nuxtApp: this.nuxtApp,
2721
+ disableCache: options?.disableCache
2722
+ });
2723
+ }
2724
+ );
2725
+ }
2726
+ async delete(items) {
2727
+ if (!this.apiUrl.value) return;
2728
+ if (!items || items.length === 0) return;
2729
+ const ids = items.map((i) => i.id);
2730
+ await this.requestProvider.registerRequest(this.apiUrl.value, {
2731
+ method: "DELETE",
2732
+ body: { id: ids },
2733
+ nuxtApp: this.nuxtApp
2734
+ });
2735
+ if (this.refreshOnMutation.value !== false) {
2736
+ if (this.requestProvider.cacheProvider) {
2737
+ await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl.value);
2738
+ }
2739
+ await this.refresh(true);
2740
+ }
2741
+ }
2742
+ }
2743
+
2744
+ exports.AAPIDataProvider = AAPIDataProvider;
2745
+ exports.ADataProvider = ADataProvider;
2746
+ exports.CAPIFlatClientDataProvider = CAPIFlatClientDataProvider;
2747
+ exports.CAPIFlatServerDataProvider = CAPIFlatServerDataProvider;
2748
+ exports.CAPITreeClientDataProvider = CAPITreeClientDataProvider;
2749
+ exports.CAPITreeServerDataProvider = CAPITreeServerDataProvider;
2750
+ exports.CApplicationCache = CApplicationCache;
2751
+ exports.CCookieCache = CCookieCache;
2752
+ exports.CFlatClientDataProvider = CFlatClientDataProvider;
2753
+ exports.CFlatServerDataProvider = CFlatServerDataProvider;
2754
+ exports.CIndexedDBCache = CIndexedDBCache;
2755
+ exports.CLocalStorageCache = CLocalStorageCache;
2756
+ exports.CMemoryCache = CMemoryCache;
2757
+ exports.CSessionCache = CSessionCache;
2758
+ exports.CTreeClientDataProvider = CTreeClientDataProvider;
2759
+ exports.CTreeServerDataProvider = CTreeServerDataProvider;
2760
+ exports.CacheProviderFactory = CacheProviderFactory;
2761
+ exports.ECacheStrategy = ECacheStrategy;
2762
+ exports.EDataFilterOperator = EDataFilterOperator;
2763
+ exports.RequestProvider = RequestProvider;