@katlux/providers 0.1.1-alpha.100 → 0.1.1-alpha.102

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const index = require('./shared/providers.CxZeMH3Y.cjs');
4
3
  const ofetch = require('ofetch');
5
4
  const h3 = require('h3');
6
5
 
6
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
7
7
  var EDataFilterOperator = /* @__PURE__ */ ((EDataFilterOperator2) => {
8
8
  EDataFilterOperator2["Equal"] = "==";
9
9
  EDataFilterOperator2["NotEqual"] = "!=";
@@ -21,7 +21,8 @@ var EDataFilterOperator = /* @__PURE__ */ ((EDataFilterOperator2) => {
21
21
  })(EDataFilterOperator || {});
22
22
  var ECacheStrategy = /* @__PURE__ */ ((ECacheStrategy2) => {
23
23
  ECacheStrategy2["Application"] = "Application";
24
- ECacheStrategy2["Session"] = "Session";
24
+ ECacheStrategy2["ServerSession"] = "ServerSession";
25
+ ECacheStrategy2["BrowserSession"] = "BrowserSession";
25
26
  ECacheStrategy2["Memory"] = "Memory";
26
27
  ECacheStrategy2["LocalStorage"] = "LocalStorage";
27
28
  ECacheStrategy2["IndexedDB"] = "IndexedDB";
@@ -37,36 +38,213 @@ var EQueueStorage = /* @__PURE__ */ ((EQueueStorage2) => {
37
38
 
38
39
  const useDebounce = (callback, delay) => {
39
40
  let timeoutId = null;
40
- return function(...args) {
41
+ const debounced = function(...args) {
41
42
  if (timeoutId !== null) {
42
43
  clearTimeout(timeoutId);
43
44
  }
44
45
  timeoutId = setTimeout(() => {
46
+ timeoutId = null;
45
47
  callback.apply(this, args);
46
48
  }, delay);
47
49
  };
50
+ debounced.cancel = () => {
51
+ if (timeoutId !== null) {
52
+ clearTimeout(timeoutId);
53
+ timeoutId = null;
54
+ }
55
+ };
56
+ return debounced;
48
57
  };
49
58
  const debounce = useDebounce;
50
59
 
60
+ class DefaultHydrationAdapter {
61
+ getSSRData(key, context) {
62
+ const contextData = context?.payload?.data?.[key] ?? context?.ssrContext?.payload?.data?.[key];
63
+ if (contextData !== void 0 && contextData !== null) {
64
+ return contextData;
65
+ }
66
+ if (typeof window !== "undefined") {
67
+ const win = window;
68
+ const clientData = win.__KATLUX_DATA__?.[key] ?? win.__SSR_DATA__?.[key] ?? win.__INITIAL_DATA__?.[key] ?? win.__NEXT_DATA__?.props?.pageProps?.[key];
69
+ if (clientData !== void 0 && clientData !== null) {
70
+ return clientData;
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+ async fetchWithSSR(key, fetcher, context) {
76
+ const cached = this.getSSRData(key, context);
77
+ if (cached !== null) {
78
+ return cached;
79
+ }
80
+ const result = await fetcher();
81
+ if (context?.payload?.data) {
82
+ context.payload.data[key] = result;
83
+ } else if (context?.ssrContext?.payload?.data) {
84
+ context.ssrContext.payload.data[key] = result;
85
+ }
86
+ return result;
87
+ }
88
+ clearSSRData(key, context) {
89
+ if (context?.payload?.data) {
90
+ delete context.payload.data[key];
91
+ }
92
+ if (context?.ssrContext?.payload?.data) {
93
+ delete context.ssrContext.payload.data[key];
94
+ }
95
+ if (typeof window !== "undefined") {
96
+ const win = window;
97
+ if (win.__KATLUX_DATA__?.payload?.data) delete win.__KATLUX_DATA__.payload.data[key];
98
+ if (win.__SSR_DATA__?.payload?.data) delete win.__SSR_DATA__.payload.data[key];
99
+ if (win.__INITIAL_DATA__?.payload?.data) delete win.__INITIAL_DATA__.payload.data[key];
100
+ }
101
+ }
102
+ getSSRPayload(context) {
103
+ if (context?.payload?.data) return context.payload.data;
104
+ if (context?.ssrContext?.payload?.data) return context.ssrContext.payload.data;
105
+ if (typeof window !== "undefined") {
106
+ const win = window;
107
+ return win.__KATLUX_DATA__?.payload?.data || win.__KATLUX_DATA__ || win.__SSR_DATA__?.payload?.data || win.__SSR_DATA__ || win.__INITIAL_DATA__?.payload?.data || win.__INITIAL_DATA__ || null;
108
+ }
109
+ return null;
110
+ }
111
+ }
112
+
113
+ let currentAdapter = null;
114
+ function getHydrationAdapter() {
115
+ if (!currentAdapter) {
116
+ currentAdapter = new DefaultHydrationAdapter();
117
+ }
118
+ return currentAdapter;
119
+ }
120
+ function setHydrationAdapter(adapter) {
121
+ currentAdapter = adapter;
122
+ }
123
+ function getSSRData(key, context) {
124
+ return getHydrationAdapter().getSSRData(key, context);
125
+ }
126
+ async function fetchWithSSR(key, fetcher, context) {
127
+ return await getHydrationAdapter().fetchWithSSR(key, fetcher, context);
128
+ }
129
+ function clearSSRData(key, context) {
130
+ getHydrationAdapter().clearSSRData?.(key, context);
131
+ }
132
+ function getSSRPayload(context) {
133
+ return getHydrationAdapter().getSSRPayload?.(context) ?? null;
134
+ }
135
+ function getPlatformApp() {
136
+ if (typeof globalThis.__KATLUX_APP__ !== "undefined") {
137
+ return globalThis.__KATLUX_APP__;
138
+ }
139
+ return null;
140
+ }
141
+ function getAppRoute() {
142
+ if (typeof window !== "undefined") {
143
+ const searchParams = new URLSearchParams(window.location.search);
144
+ const query = {};
145
+ searchParams.forEach((val, key) => {
146
+ query[key] = val;
147
+ });
148
+ return { query, path: window.location.pathname };
149
+ }
150
+ return null;
151
+ }
152
+ function getAppRouter() {
153
+ if (typeof window !== "undefined") {
154
+ return {
155
+ replace: (options) => {
156
+ const url = new URL(window.location.href);
157
+ url.search = "";
158
+ if (options.query) {
159
+ for (const [k, v] of Object.entries(options.query)) {
160
+ if (v !== void 0 && v !== null) {
161
+ url.searchParams.set(k, String(v));
162
+ }
163
+ }
164
+ }
165
+ window.history.replaceState({}, "", url.toString());
166
+ }
167
+ };
168
+ }
169
+ return null;
170
+ }
171
+ function onPlatformReady(cb) {
172
+ if (typeof window !== "undefined") {
173
+ if (document.readyState === "complete") {
174
+ setTimeout(cb, 0);
175
+ } else {
176
+ window.addEventListener("DOMContentLoaded", cb, { once: true });
177
+ }
178
+ } else {
179
+ setTimeout(cb, 0);
180
+ }
181
+ }
182
+
51
183
  class ADataProvider {
52
184
  idKey = "id";
53
185
  pageData = [];
54
- rowCount = 0;
55
- loading = false;
56
- initialLoad = true;
57
- error = null;
186
+ _rowCount = 0;
187
+ get rowCount() {
188
+ return this._rowCount;
189
+ }
190
+ set rowCount(val) {
191
+ if (this._rowCount !== val) {
192
+ this._rowCount = val;
193
+ this.notify();
194
+ }
195
+ }
196
+ _loading = false;
197
+ get loading() {
198
+ return this._loading;
199
+ }
200
+ set loading(val) {
201
+ if (this._loading !== val) {
202
+ this._loading = val;
203
+ this.notify();
204
+ }
205
+ }
206
+ _initialLoad = true;
207
+ get initialLoad() {
208
+ return this._initialLoad;
209
+ }
210
+ set initialLoad(val) {
211
+ if (this._initialLoad !== val) {
212
+ this._initialLoad = val;
213
+ this.notify();
214
+ }
215
+ }
216
+ _error = null;
217
+ get error() {
218
+ return this._error;
219
+ }
220
+ set error(val) {
221
+ if (this._error !== val) {
222
+ this._error = val;
223
+ this.notify();
224
+ }
225
+ }
58
226
  SSR = false;
59
227
  deduplicate = true;
60
228
  context = null;
61
- get nuxtApp() {
62
- return this.context;
229
+ urlPageParam = "";
230
+ _selectedRows = [];
231
+ get selectedRows() {
232
+ return this._selectedRows;
233
+ }
234
+ set selectedRows(val) {
235
+ this._selectedRows = Array.isArray(val) ? val : [];
236
+ this.notify();
63
237
  }
64
- set nuxtApp(val) {
65
- this.context = val;
238
+ _selectAll = false;
239
+ get selectAll() {
240
+ return this._selectAll;
241
+ }
242
+ set selectAll(val) {
243
+ if (this._selectAll !== val) {
244
+ this._selectAll = val;
245
+ this.notify();
246
+ }
66
247
  }
67
- urlPageParam = "";
68
- selectedRows = [];
69
- selectAll = false;
70
248
  _currentPage = 1;
71
249
  _pageSize = 10;
72
250
  _filter = null;
@@ -97,6 +275,7 @@ class ADataProvider {
97
275
  }
98
276
  _listeners = /* @__PURE__ */ new Set();
99
277
  _debouncedFilterLoad;
278
+ _debouncedSortLoad;
100
279
  constructor(options) {
101
280
  Object.defineProperty(this, "__v_skip", { value: true, enumerable: false });
102
281
  if (options?.idKey) {
@@ -112,17 +291,15 @@ class ADataProvider {
112
291
  this.urlPageParam = options?.urlPageParam || "";
113
292
  if (options?.context) {
114
293
  this.context = options.context;
115
- } else if (options?.nuxtApp) {
116
- this.context = options.nuxtApp;
117
294
  } else {
118
295
  try {
119
- this.context = index.getPlatformApp();
296
+ this.context = getPlatformApp();
120
297
  } catch {
121
298
  }
122
299
  }
123
300
  if (options?.urlPageParam && typeof window !== "undefined") {
124
301
  try {
125
- const route = index.getAppRoute();
302
+ const route = getAppRoute();
126
303
  if (route) {
127
304
  const pageFromUrl = route.query[options.urlPageParam];
128
305
  if (pageFromUrl) {
@@ -135,11 +312,16 @@ class ADataProvider {
135
312
  } catch {
136
313
  }
137
314
  }
315
+ const filterDebounceTime = typeof options?.filterDebounce === "number" ? options.filterDebounce : 300;
316
+ const sortDebounceTime = typeof options?.sortDebounce === "number" ? options.sortDebounce : 200;
138
317
  this._debouncedFilterLoad = useDebounce(() => {
139
318
  this._currentPage = 1;
140
319
  this.loadPageData();
141
- this.notify();
142
- }, 300);
320
+ }, filterDebounceTime);
321
+ this._debouncedSortLoad = useDebounce(() => {
322
+ this._currentPage = 1;
323
+ this.loadPageData();
324
+ }, sortDebounceTime);
143
325
  this.setFilter = this.setFilter.bind(this);
144
326
  this.setSortList = this.setSortList.bind(this);
145
327
  this.setCurrentPage = this.setCurrentPage.bind(this);
@@ -149,21 +331,71 @@ class ADataProvider {
149
331
  this.loadPageData = this.loadPageData.bind(this);
150
332
  this.refresh = this.refresh.bind(this);
151
333
  this.subscribe = this.subscribe.bind(this);
152
- this.notify = this.notify.bind(this);
334
+ this.batchUpdates = this.batchUpdates.bind(this);
153
335
  this.getState = this.getState.bind(this);
336
+ this.cancelPending = this.cancelPending.bind(this);
337
+ }
338
+ _batchDepth = 0;
339
+ _pendingNotify = false;
340
+ _isNotifying = false;
341
+ /**
342
+ * Batches multiple state updates so notify() fires exactly once upon completion.
343
+ */
344
+ batchUpdates(fn) {
345
+ this._batchDepth++;
346
+ let isAsync = false;
347
+ try {
348
+ const res = fn();
349
+ if (res instanceof Promise || res && typeof res.then === "function") {
350
+ isAsync = true;
351
+ return Promise.resolve(res).finally(() => {
352
+ this._batchDepth = Math.max(0, this._batchDepth - 1);
353
+ if (this._batchDepth === 0 && this._pendingNotify) {
354
+ this._pendingNotify = false;
355
+ this.notify();
356
+ }
357
+ });
358
+ }
359
+ return res;
360
+ } finally {
361
+ if (!isAsync) {
362
+ this._batchDepth = Math.max(0, this._batchDepth - 1);
363
+ if (this._batchDepth === 0 && this._pendingNotify) {
364
+ this._pendingNotify = false;
365
+ this.notify();
366
+ }
367
+ }
368
+ }
154
369
  }
155
370
  subscribe(listener) {
156
371
  this._listeners.add(listener);
157
372
  return () => this._listeners.delete(listener);
158
373
  }
159
374
  notify() {
160
- this._listeners.forEach((listener) => {
161
- try {
162
- listener(this);
163
- } catch (e) {
164
- console.error("[Katlux Providers] Listener error:", e);
375
+ if (this._batchDepth > 0) {
376
+ this._pendingNotify = true;
377
+ return;
378
+ }
379
+ if (this._isNotifying) {
380
+ this._pendingNotify = true;
381
+ return;
382
+ }
383
+ this._isNotifying = true;
384
+ try {
385
+ this._listeners.forEach((listener) => {
386
+ try {
387
+ listener(this);
388
+ } catch (e) {
389
+ console.error("[Katlux Providers] Listener error:", e);
390
+ }
391
+ });
392
+ } finally {
393
+ this._isNotifying = false;
394
+ if (this._pendingNotify && this._batchDepth === 0) {
395
+ this._pendingNotify = false;
396
+ this.notify();
165
397
  }
166
- });
398
+ }
167
399
  }
168
400
  getState() {
169
401
  return {
@@ -180,24 +412,35 @@ class ADataProvider {
180
412
  selectAll: this.selectAll
181
413
  };
182
414
  }
183
- setFilter(filter) {
415
+ setFilter(filter, immediate = false) {
184
416
  this._filter = filter;
185
- this._debouncedFilterLoad();
417
+ this._currentPage = 1;
418
+ if (immediate) {
419
+ this._debouncedFilterLoad?.cancel?.();
420
+ this.loadPageData();
421
+ } else {
422
+ this._debouncedFilterLoad();
423
+ }
186
424
  }
187
- setSortList(sortList) {
425
+ setSortList(sortList, immediate = false) {
188
426
  this._sortList = sortList;
189
427
  this._currentPage = 1;
190
- this.loadPageData();
191
- this.notify();
428
+ if (immediate) {
429
+ this._debouncedSortLoad?.cancel?.();
430
+ this.loadPageData();
431
+ } else {
432
+ this._debouncedSortLoad();
433
+ }
192
434
  }
193
435
  setCurrentPage(currentPage) {
194
436
  this._currentPage = currentPage;
437
+ this._selectAll = false;
195
438
  this.loadPageData();
196
439
  if (typeof window !== "undefined" && this.urlPageParam) {
197
440
  try {
198
- const router = index.getAppRouter();
441
+ const router = getAppRouter();
199
442
  if (router) {
200
- const currentRoute = router.currentRoute?.value || index.getAppRoute();
443
+ const currentRoute = router.currentRoute?.value || getAppRoute();
201
444
  const currentQuery = { ...currentRoute?.query || {} };
202
445
  if (currentPage === 1) {
203
446
  delete currentQuery[this.urlPageParam];
@@ -226,6 +469,10 @@ class ADataProvider {
226
469
  async refresh(hardRefresh = false) {
227
470
  await this.loadPageData({ disableCache: hardRefresh });
228
471
  }
472
+ cancelPending() {
473
+ this._debouncedFilterLoad?.cancel?.();
474
+ this._debouncedSortLoad?.cancel?.();
475
+ }
229
476
  }
230
477
 
231
478
  const compareIn = (rowValue, filterValue) => {
@@ -259,22 +506,38 @@ const compareValues = (rowValue, filterValue) => {
259
506
  return String(rowValue).localeCompare(String(filterValue));
260
507
  };
261
508
  const compareAnd = (row, nested) => {
262
- const subFilters = Array.isArray(nested) ? nested : nested && typeof nested === "object" ? Object.values(nested) : [];
263
- const validFilters = subFilters.filter((f) => f && typeof f === "object" && "operator" in f && "field" in f);
264
- if (validFilters.length === 0) return true;
265
- return validFilters.every((f) => {
266
- const active = f.active !== false;
267
- return active ? evaluateFilter(f, row) : true;
268
- });
509
+ if (!nested) return true;
510
+ const subFilters = Array.isArray(nested) ? nested : typeof nested === "object" ? Object.values(nested) : [];
511
+ const len = subFilters.length;
512
+ for (let i = 0; i < len; i++) {
513
+ const f = subFilters[i];
514
+ if (f && typeof f === "object" && "operator" in f && "field" in f) {
515
+ const active = f.active !== false;
516
+ if (active && !evaluateFilter(f, row)) {
517
+ return false;
518
+ }
519
+ }
520
+ }
521
+ return true;
269
522
  };
270
523
  const compareOr = (row, nested) => {
271
- const subFilters = Array.isArray(nested) ? nested : nested && typeof nested === "object" ? Object.values(nested) : [];
272
- const validFilters = subFilters.filter((f) => f && typeof f === "object" && "operator" in f && "field" in f);
273
- const activeFilters = validFilters.filter((f) => f.active !== false);
274
- if (activeFilters.length === 0) return true;
275
- return activeFilters.some((f) => {
276
- return evaluateFilter(f, row);
277
- });
524
+ if (!nested) return true;
525
+ const subFilters = Array.isArray(nested) ? nested : typeof nested === "object" ? Object.values(nested) : [];
526
+ const len = subFilters.length;
527
+ let hasActive = false;
528
+ for (let i = 0; i < len; i++) {
529
+ const f = subFilters[i];
530
+ if (f && typeof f === "object" && "operator" in f && "field" in f) {
531
+ const active = f.active !== false;
532
+ if (active) {
533
+ hasActive = true;
534
+ if (evaluateFilter(f, row)) {
535
+ return true;
536
+ }
537
+ }
538
+ }
539
+ }
540
+ return !hasActive;
278
541
  };
279
542
  const applyOperator = (operator, rowValue, filterValue) => {
280
543
  switch (operator) {
@@ -307,20 +570,26 @@ const applyOperator = (operator, rowValue, filterValue) => {
307
570
  }
308
571
  };
309
572
  const evaluateFilter = (filter, row) => {
310
- if (!filter || !filter.operator) return true;
311
- if (filter.operator === EDataFilterOperator.And || filter.operator === EDataFilterOperator.Or || filter.operator === EDataFilterOperator.Nand || filter.operator === EDataFilterOperator.Nor) {
312
- return !filter.active || applyOperator(filter.operator, row, filter.field);
573
+ if (!filter || !filter.operator || filter.active === false) return true;
574
+ const op = filter.operator;
575
+ if (op === EDataFilterOperator.And || op === EDataFilterOperator.Or || op === EDataFilterOperator.Nand || op === EDataFilterOperator.Nor) {
576
+ return applyOperator(op, row, filter.field);
313
577
  }
314
578
  if (filter.field && typeof filter.field === "object" && "operator" in filter.field && "field" in filter.field) {
315
- return !filter.active || evaluateFilter(filter.field, row);
579
+ return evaluateFilter(filter.field, row);
316
580
  }
317
581
  const field = filter.field;
318
- const fieldKeys = Object.keys(field);
319
- return !filter.active || fieldKeys.every((key) => {
320
- const filterValue = field[key];
321
- const rowValue = row[key];
322
- return applyOperator(filter.operator, rowValue, filterValue);
323
- });
582
+ if (!field || typeof field !== "object") return true;
583
+ for (const key in field) {
584
+ if (Object.prototype.hasOwnProperty.call(field, key)) {
585
+ const filterValue = field[key];
586
+ const rowValue = row ? row[key] : void 0;
587
+ if (!applyOperator(op, rowValue, filterValue)) {
588
+ return false;
589
+ }
590
+ }
591
+ }
592
+ return true;
324
593
  };
325
594
  const filterTreeData = (nodes, filter, options) => {
326
595
  const { idKey, parentKey } = options;
@@ -388,7 +657,13 @@ const filterData = (data, filter, options) => {
388
657
  );
389
658
  return { results: visibleNodes, expandedNodes };
390
659
  }
391
- const results = data.filter((row) => evaluateFilter(filter, row));
660
+ const len = data.length;
661
+ const results = [];
662
+ for (let i = 0; i < len; i++) {
663
+ if (evaluateFilter(filter, data[i])) {
664
+ results.push(data[i]);
665
+ }
666
+ }
392
667
  return { results };
393
668
  };
394
669
  const useFilterLogic = () => {
@@ -456,50 +731,94 @@ const useSortLogic = () => {
456
731
  };
457
732
 
458
733
  class CFlatClientDataProvider extends ADataProvider {
459
- allData = [];
734
+ _allData = [];
460
735
  filteredData = [];
736
+ // Reference map array holding active sorted & filtered row references
737
+ _rowMap = [];
738
+ _filterDirty = true;
739
+ _sortDirty = true;
461
740
  constructor(options) {
462
741
  super(options);
463
742
  }
743
+ get allData() {
744
+ return this._allData;
745
+ }
746
+ set allData(data) {
747
+ this._allData = Array.isArray(data) ? data : [];
748
+ this._filterDirty = true;
749
+ this._sortDirty = true;
750
+ }
751
+ get rowMap() {
752
+ return this._rowMap;
753
+ }
464
754
  setData(data) {
465
755
  this.allData = Array.isArray(data) ? data : [];
466
756
  this.loadPageData();
467
757
  }
758
+ setFilter(filter, immediate = false) {
759
+ this._filterDirty = true;
760
+ this._sortDirty = true;
761
+ super.setFilter(filter, immediate);
762
+ }
763
+ setSortList(sortList, immediate = false) {
764
+ this._sortDirty = true;
765
+ super.setSortList(sortList, immediate);
766
+ }
767
+ /**
768
+ * Explicitly rebuilds the reference map array if row properties inside allData were mutated in-place.
769
+ */
770
+ updateMap() {
771
+ this._filterDirty = true;
772
+ this._sortDirty = true;
773
+ this.loadPageData();
774
+ }
468
775
  async refreshData(options) {
776
+ this._filterDirty = true;
777
+ this._sortDirty = true;
469
778
  await this.loadPageData();
470
779
  }
471
780
  async refresh(hardRefresh = false) {
472
781
  await this.refreshData({ disableCache: hardRefresh });
473
782
  }
474
783
  async loadPageData() {
475
- this.loading = true;
476
- this.error = null;
477
- try {
478
- if (!this.filter) {
479
- this.filteredData = this.allData;
480
- } else {
481
- const { results } = filterData(this.allData, this.filter);
482
- this.filteredData = results;
483
- }
484
- this.rowCount = this.filteredData.length;
485
- if (this.sortList.length > 0) {
486
- this.filteredData = sortData(this.sortList, this.filteredData);
487
- }
488
- if (this.pageSize <= 0) {
489
- this.pageData = this.filteredData;
490
- } else {
491
- const startIndex = (this.currentPage - 1) * this.pageSize;
492
- const endIndex = startIndex + this.pageSize;
493
- this.pageData = this.filteredData.slice(startIndex, endIndex);
784
+ this.batchUpdates(() => {
785
+ this.loading = true;
786
+ this.error = null;
787
+ try {
788
+ if (this._filterDirty) {
789
+ if (!this.filter || !this.filter.active) {
790
+ this.filteredData = this.allData;
791
+ } else {
792
+ const { results } = filterData(this.allData, this.filter);
793
+ this.filteredData = results;
794
+ }
795
+ this.rowCount = this.filteredData.length;
796
+ this._filterDirty = false;
797
+ this._sortDirty = true;
798
+ }
799
+ if (this._sortDirty) {
800
+ if (this.sortList.length > 0) {
801
+ this._rowMap = sortData(this.sortList, this.filteredData);
802
+ } else {
803
+ this._rowMap = this.filteredData;
804
+ }
805
+ this._sortDirty = false;
806
+ }
807
+ if (this.pageSize <= 0) {
808
+ this.pageData = this._rowMap;
809
+ } else {
810
+ const startIndex = (this.currentPage - 1) * this.pageSize;
811
+ const endIndex = startIndex + this.pageSize;
812
+ this.pageData = this._rowMap.slice(startIndex, endIndex);
813
+ }
814
+ } catch (err) {
815
+ this.error = err;
816
+ console.warn("[Katlux Providers] CFlatClientDataProvider loadPageData error", err);
817
+ } finally {
818
+ this.loading = false;
819
+ this.initialLoad = false;
494
820
  }
495
- } catch (err) {
496
- this.error = err;
497
- console.warn("[Katlux Providers] CFlatClientDataProvider loadPageData error", err);
498
- } finally {
499
- this.loading = false;
500
- this.initialLoad = false;
501
- this.notify();
502
- }
821
+ });
503
822
  }
504
823
  }
505
824
 
@@ -508,7 +827,8 @@ class CacheProviderFactory {
508
827
  static customDrivers = /* @__PURE__ */ new Map();
509
828
  static defaultLoaders = {
510
829
  [ECacheStrategy.Application]: () => Promise.resolve().then(function () { return CApplicationCache$1; }).then((m) => m.CApplicationCache),
511
- [ECacheStrategy.Session]: () => Promise.resolve().then(function () { return CSessionCache$1; }).then((m) => m.CSessionCache),
830
+ [ECacheStrategy.ServerSession]: () => Promise.resolve().then(function () { return CServerSessionCache$1; }).then((m) => m.CServerSessionCache),
831
+ [ECacheStrategy.BrowserSession]: () => Promise.resolve().then(function () { return CBrowserSessionCache$1; }).then((m) => m.CBrowserSessionCache),
512
832
  [ECacheStrategy.Memory]: () => Promise.resolve().then(function () { return CMemoryCache$1; }).then((m) => m.CMemoryCache),
513
833
  [ECacheStrategy.LocalStorage]: () => Promise.resolve().then(function () { return CLocalStorageCache$1; }).then((m) => m.CLocalStorageCache),
514
834
  [ECacheStrategy.IndexedDB]: () => Promise.resolve().then(function () { return CIndexedDBCache$1; }).then((m) => m.CIndexedDBCache),
@@ -569,118 +889,444 @@ class ACacheProvider {
569
889
  }
570
890
  }
571
891
 
572
- class KatluxIndexedDB {
573
- static db = null;
574
- static openPromise = null;
575
- static currentVersion = 3;
576
- static customStores = /* @__PURE__ */ new Set();
577
- static DB_NAME = "KatluxDB";
578
- static get DB_VERSION() {
579
- return KatluxIndexedDB.currentVersion;
580
- }
581
- /**
582
- * Opens (or returns the existing) shared IDBDatabase connection.
583
- * Safe to call multiple times — always resolves to the same instance.
584
- */
585
- static open() {
586
- if (this.db) return Promise.resolve(this.db);
587
- if (this.openPromise) return this.openPromise;
588
- this.openPromise = new Promise((resolve, reject) => {
589
- if (typeof indexedDB === "undefined") {
590
- return reject(new Error("IndexedDB is not available in this environment"));
591
- }
592
- const req = indexedDB.open(KatluxIndexedDB.DB_NAME, KatluxIndexedDB.currentVersion);
593
- req.onupgradeneeded = (event) => {
594
- const db = event.target.result;
595
- if (!db.objectStoreNames.contains("cache")) db.createObjectStore("cache");
596
- if (!db.objectStoreNames.contains("queue")) db.createObjectStore("queue");
597
- if (!db.objectStoreNames.contains("dead_letter")) db.createObjectStore("dead_letter");
598
- for (const store of KatluxIndexedDB.customStores) {
599
- if (!db.objectStoreNames.contains(store)) {
600
- db.createObjectStore(store);
601
- }
602
- }
603
- };
604
- req.onsuccess = () => {
605
- KatluxIndexedDB.db = req.result;
606
- if (req.result.version) {
607
- KatluxIndexedDB.currentVersion = req.result.version;
608
- }
609
- req.result.onversionchange = () => {
610
- req.result.close();
611
- KatluxIndexedDB.db = null;
612
- KatluxIndexedDB.openPromise = null;
613
- console.warn("[KatluxIndexedDB] Database closed due to version change. Will reopen on next access.");
614
- };
615
- resolve(KatluxIndexedDB.db);
616
- };
617
- req.onerror = () => {
618
- KatluxIndexedDB.openPromise = null;
619
- reject(req.error);
620
- };
621
- req.onblocked = () => {
622
- console.warn("[KatluxIndexedDB] Database upgrade blocked by another open connection.");
623
- };
624
- });
625
- return this.openPromise;
892
+ class CApplicationCache extends ACacheProvider {
893
+ static instance = null;
894
+ static _storage = null;
895
+ static get storage() {
896
+ if (!this._storage) {
897
+ this._storage = /* @__PURE__ */ new Map();
898
+ }
899
+ return this._storage;
626
900
  }
627
- /**
628
- * Dynamically ensures that an object store exists in the database.
629
- * If not present, performs a database version bump and creates the store.
630
- */
631
- static async ensureStore(storeName) {
632
- KatluxIndexedDB.customStores.add(storeName);
633
- let db = await KatluxIndexedDB.open();
634
- if (!db.objectStoreNames.contains(storeName)) {
635
- const newVersion = (db.version || KatluxIndexedDB.currentVersion) + 1;
636
- KatluxIndexedDB.currentVersion = newVersion;
637
- if (KatluxIndexedDB.db) {
638
- KatluxIndexedDB.db.close();
639
- KatluxIndexedDB.db = null;
640
- }
641
- KatluxIndexedDB.openPromise = null;
642
- db = await new Promise((resolve, reject) => {
643
- const req = indexedDB.open(KatluxIndexedDB.DB_NAME, newVersion);
644
- req.onupgradeneeded = (event) => {
645
- const upgradedDb = event.target.result;
646
- if (!upgradedDb.objectStoreNames.contains("cache")) upgradedDb.createObjectStore("cache");
647
- if (!upgradedDb.objectStoreNames.contains("queue")) upgradedDb.createObjectStore("queue");
648
- if (!upgradedDb.objectStoreNames.contains("dead_letter")) upgradedDb.createObjectStore("dead_letter");
649
- for (const s of KatluxIndexedDB.customStores) {
650
- if (!upgradedDb.objectStoreNames.contains(s)) {
651
- upgradedDb.createObjectStore(s);
652
- }
653
- }
654
- };
655
- req.onsuccess = () => {
656
- KatluxIndexedDB.db = req.result;
657
- KatluxIndexedDB.currentVersion = req.result.version;
658
- resolve(req.result);
659
- };
660
- req.onerror = () => {
661
- KatluxIndexedDB.openPromise = null;
662
- reject(req.error);
663
- };
664
- });
901
+ static getInstance() {
902
+ if (!this.instance) {
903
+ this.instance = new CApplicationCache();
665
904
  }
666
- return db;
905
+ return this.instance;
906
+ }
907
+ static MAX_ENTRIES = 1e4;
908
+ static getSnapshot() {
909
+ return this.storage;
667
910
  }
668
911
  /**
669
- * Returns a transaction-bound object store.
670
- * Convenience wrapper used by CIndexedDBCache, QueueStorage adapters, etc.
912
+ * Purges expired entries when storage size reaches MAX_ENTRIES watermark.
913
+ * Avoids persistent background setInterval timers on Node.js/SSR.
671
914
  */
672
- static async getStore(storeName, mode) {
673
- let db = await KatluxIndexedDB.open();
674
- if (!db.objectStoreNames.contains(storeName)) {
675
- db = await KatluxIndexedDB.ensureStore(storeName);
915
+ static purgeExpiredEntries() {
916
+ const now = Date.now();
917
+ const storage = this.storage;
918
+ for (const [key, entry] of storage.entries()) {
919
+ if (now - entry.timestamp > entry.lifetime) {
920
+ storage.delete(key);
921
+ }
676
922
  }
677
- return db.transaction(storeName, mode).objectStore(storeName);
678
923
  }
679
924
  /**
680
- * For testing only — resets the singleton so tests can start fresh.
925
+ * Clears all cached entries (used for test isolation).
681
926
  */
682
- static _reset() {
683
- if (this.db) {
927
+ static clear() {
928
+ this._storage?.clear();
929
+ }
930
+ constructor() {
931
+ super();
932
+ }
933
+ isServer(context) {
934
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
935
+ return typeof window === "undefined" || !!event || !!context?.ssrContext || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && !!undefined;
936
+ }
937
+ async getKeyList(context) {
938
+ if (!this.isServer(context)) return [];
939
+ const prefix = "cache:";
940
+ const storage = CApplicationCache.storage;
941
+ return Array.from(storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
942
+ }
943
+ async get(key, context) {
944
+ if (this.isServer(context)) {
945
+ const prefixedKey = "cache:" + key;
946
+ const storage = CApplicationCache.storage;
947
+ const entry = storage.get(prefixedKey);
948
+ if (!entry) return null;
949
+ if (Date.now() - entry.timestamp > entry.lifetime) {
950
+ storage.delete(prefixedKey);
951
+ return null;
952
+ }
953
+ return entry.data;
954
+ }
955
+ return null;
956
+ }
957
+ async set(key, data, lifetime, context) {
958
+ if (this.isServer(context)) {
959
+ const storage = CApplicationCache.storage;
960
+ if (storage.size >= CApplicationCache.MAX_ENTRIES) {
961
+ CApplicationCache.purgeExpiredEntries();
962
+ }
963
+ const prefixedKey = "cache:" + key;
964
+ storage.set(prefixedKey, {
965
+ data,
966
+ timestamp: Date.now(),
967
+ lifetime
968
+ });
969
+ }
970
+ }
971
+ async remove(key, context) {
972
+ if (this.isServer(context)) {
973
+ const prefixedKey = "cache:" + key;
974
+ CApplicationCache.storage.delete(prefixedKey);
975
+ }
976
+ }
977
+ async removeByPrefix(prefix, context) {
978
+ if (this.isServer(context)) {
979
+ const fullPrefix = "cache:" + prefix;
980
+ const storage = CApplicationCache.storage;
981
+ const keysToDelete = [];
982
+ for (const key of storage.keys()) {
983
+ if (key.startsWith(fullPrefix)) {
984
+ keysToDelete.push(key);
985
+ }
986
+ }
987
+ for (const key of keysToDelete) {
988
+ storage.delete(key);
989
+ }
990
+ }
991
+ }
992
+ async getRemainingTime(key, context) {
993
+ if (this.isServer(context)) {
994
+ const prefixedKey = "cache:" + key;
995
+ const storage = CApplicationCache.storage;
996
+ const entry = storage.get(prefixedKey);
997
+ if (!entry) return null;
998
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
999
+ }
1000
+ return null;
1001
+ }
1002
+ async cleanupExpired(context) {
1003
+ if (this.isServer(context)) {
1004
+ CApplicationCache.purgeExpiredEntries();
1005
+ }
1006
+ }
1007
+ }
1008
+
1009
+ const CApplicationCache$1 = {
1010
+ __proto__: null,
1011
+ CApplicationCache: CApplicationCache
1012
+ };
1013
+
1014
+ class CMemoryCache extends ACacheProvider {
1015
+ static instance = null;
1016
+ static _storage = null;
1017
+ static get storage() {
1018
+ if (!this._storage) this._storage = /* @__PURE__ */ new Map();
1019
+ return this._storage;
1020
+ }
1021
+ static getInstance() {
1022
+ if (!this.instance) {
1023
+ this.instance = new CMemoryCache();
1024
+ }
1025
+ return this.instance;
1026
+ }
1027
+ constructor() {
1028
+ super();
1029
+ const isClient = typeof window !== "undefined" || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && !!undefined;
1030
+ if (isClient && CMemoryCache.storage.size === 0) {
1031
+ this._hydrateFromPayload();
1032
+ }
1033
+ }
1034
+ async _hydrateFromPayload() {
1035
+ try {
1036
+ const payloadData = getSSRPayload();
1037
+ if (!payloadData) return;
1038
+ for (const key in payloadData) {
1039
+ const value = payloadData[key];
1040
+ if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
1041
+ if (typeof value.lifetime === "number") {
1042
+ CMemoryCache.storage.set(key, value);
1043
+ }
1044
+ }
1045
+ }
1046
+ } catch (e) {
1047
+ console.warn("[Katlux Cache] CMemoryCache payload hydration failed", e);
1048
+ }
1049
+ }
1050
+ async getKeyList(context) {
1051
+ const prefix = "cache:";
1052
+ if (this.isServer(context)) {
1053
+ const payload = getSSRPayload(context);
1054
+ if (!payload) return [];
1055
+ return Object.keys(payload).filter((k) => k.startsWith(prefix)).map((k) => k.substring(prefix.length));
1056
+ }
1057
+ return Array.from(CMemoryCache.storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
1058
+ }
1059
+ async get(key, context) {
1060
+ const prefixedKey = "cache:" + key;
1061
+ if (this.isServer(context)) {
1062
+ try {
1063
+ const payloadData = getSSRPayload(context);
1064
+ if (payloadData && payloadData[prefixedKey]) {
1065
+ const entry2 = payloadData[prefixedKey];
1066
+ if (Date.now() - entry2.timestamp <= entry2.lifetime) {
1067
+ return entry2.data;
1068
+ }
1069
+ }
1070
+ } catch (e) {
1071
+ console.warn("[Katlux Cache] CMemoryCache error reading SSR payload for key: " + key, e);
1072
+ }
1073
+ return null;
1074
+ }
1075
+ const entry = CMemoryCache.storage.get(prefixedKey);
1076
+ if (entry) {
1077
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
1078
+ return entry.data;
1079
+ } else {
1080
+ CMemoryCache.storage.delete(prefixedKey);
1081
+ }
1082
+ }
1083
+ try {
1084
+ const payloadData = getSSRPayload(context);
1085
+ if (payloadData && payloadData[prefixedKey]) {
1086
+ const entry2 = payloadData[prefixedKey];
1087
+ if (Date.now() - entry2.timestamp <= entry2.lifetime) {
1088
+ CMemoryCache.storage.set(prefixedKey, entry2);
1089
+ return entry2.data;
1090
+ }
1091
+ }
1092
+ } catch (e) {
1093
+ console.warn("[Katlux Cache] CMemoryCache error reading SSR payload for key: " + key, e);
1094
+ }
1095
+ return null;
1096
+ }
1097
+ isServer(context) {
1098
+ return typeof window === "undefined" || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && !!undefined || !!context?.event || !!context?.ssrContext || !!context?.node;
1099
+ }
1100
+ async set(key, data, lifetime, context) {
1101
+ const prefixedKey = "cache:" + key;
1102
+ const entry = {
1103
+ data,
1104
+ timestamp: Date.now(),
1105
+ lifetime
1106
+ };
1107
+ if (this.isServer(context)) {
1108
+ if (context) {
1109
+ try {
1110
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
1111
+ if (payload) {
1112
+ payload[prefixedKey] = entry;
1113
+ }
1114
+ } catch (e) {
1115
+ console.warn("[Katlux Cache] CMemoryCache error writing SSR payload for key: " + key, e);
1116
+ }
1117
+ }
1118
+ return;
1119
+ }
1120
+ CMemoryCache.storage.set(prefixedKey, entry);
1121
+ }
1122
+ async remove(key, context) {
1123
+ const prefixedKey = "cache:" + key;
1124
+ if (this.isServer(context)) {
1125
+ if (context) {
1126
+ try {
1127
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
1128
+ if (payload && payload[prefixedKey]) {
1129
+ delete payload[prefixedKey];
1130
+ }
1131
+ } catch (e) {
1132
+ console.warn("[Katlux Cache] CMemoryCache error deleting key from SSR payload: " + key, e);
1133
+ }
1134
+ }
1135
+ return;
1136
+ }
1137
+ CMemoryCache.storage.delete(prefixedKey);
1138
+ }
1139
+ async removeByPrefix(prefix, context) {
1140
+ const fullPrefix = "cache:" + prefix;
1141
+ if (this.isServer(context)) {
1142
+ if (context) {
1143
+ try {
1144
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
1145
+ if (payload) {
1146
+ for (const key in payload) {
1147
+ if (key.startsWith(fullPrefix)) {
1148
+ delete payload[key];
1149
+ }
1150
+ }
1151
+ }
1152
+ } catch (e) {
1153
+ console.warn("[Katlux Cache] CMemoryCache error removing by prefix from SSR payload: " + prefix, e);
1154
+ }
1155
+ }
1156
+ return;
1157
+ }
1158
+ const keysToDelete = [];
1159
+ for (const key of CMemoryCache.storage.keys()) {
1160
+ if (key.startsWith(fullPrefix)) {
1161
+ keysToDelete.push(key);
1162
+ }
1163
+ }
1164
+ for (const key of keysToDelete) {
1165
+ CMemoryCache.storage.delete(key);
1166
+ }
1167
+ }
1168
+ async getRemainingTime(key, context) {
1169
+ const prefixedKey = "cache:" + key;
1170
+ if (this.isServer(context)) {
1171
+ const payload = getSSRPayload(context);
1172
+ if (payload && payload[prefixedKey]) {
1173
+ const entry2 = payload[prefixedKey];
1174
+ return Math.max(0, entry2.timestamp + entry2.lifetime - Date.now());
1175
+ }
1176
+ return null;
1177
+ }
1178
+ const entry = CMemoryCache.storage.get(prefixedKey);
1179
+ if (!entry) return null;
1180
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
1181
+ }
1182
+ async cleanupExpired() {
1183
+ if (typeof window === "undefined") return;
1184
+ const prefix = "cache:";
1185
+ const now = Date.now();
1186
+ const keysToDelete = [];
1187
+ for (const [key, entry] of CMemoryCache.storage.entries()) {
1188
+ if (key.startsWith(prefix)) {
1189
+ if (now - entry.timestamp > entry.lifetime) {
1190
+ keysToDelete.push(key);
1191
+ }
1192
+ }
1193
+ }
1194
+ for (const key of keysToDelete) {
1195
+ CMemoryCache.storage.delete(key);
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ const CMemoryCache$1 = {
1201
+ __proto__: null,
1202
+ CMemoryCache: CMemoryCache
1203
+ };
1204
+
1205
+ class KatluxIndexedDB {
1206
+ static db = null;
1207
+ static openPromise = null;
1208
+ static currentVersion = 3;
1209
+ static customStores = /* @__PURE__ */ new Set();
1210
+ static DB_NAME = "KatluxDB";
1211
+ static get DB_VERSION() {
1212
+ return KatluxIndexedDB.currentVersion;
1213
+ }
1214
+ /**
1215
+ * Opens (or returns the existing) shared IDBDatabase connection.
1216
+ * Safe to call multiple times — always resolves to the same instance.
1217
+ */
1218
+ static open() {
1219
+ if (this.db) return Promise.resolve(this.db);
1220
+ if (this.openPromise) return this.openPromise;
1221
+ this.openPromise = new Promise((resolve, reject) => {
1222
+ if (typeof indexedDB === "undefined") {
1223
+ return reject(new Error("IndexedDB is not available in this environment"));
1224
+ }
1225
+ const req = indexedDB.open(KatluxIndexedDB.DB_NAME);
1226
+ req.onupgradeneeded = (event) => {
1227
+ const db = event.target.result;
1228
+ if (!db.objectStoreNames.contains("cache")) db.createObjectStore("cache");
1229
+ if (!db.objectStoreNames.contains("queue")) db.createObjectStore("queue");
1230
+ if (!db.objectStoreNames.contains("dead_letter")) db.createObjectStore("dead_letter");
1231
+ for (const store of KatluxIndexedDB.customStores) {
1232
+ if (!db.objectStoreNames.contains(store)) {
1233
+ db.createObjectStore(store);
1234
+ }
1235
+ }
1236
+ };
1237
+ req.onsuccess = async () => {
1238
+ const db = req.result;
1239
+ KatluxIndexedDB.db = db;
1240
+ if (db.version) {
1241
+ KatluxIndexedDB.currentVersion = db.version;
1242
+ }
1243
+ db.onversionchange = () => {
1244
+ db.close();
1245
+ KatluxIndexedDB.db = null;
1246
+ KatluxIndexedDB.openPromise = null;
1247
+ console.warn("[KatluxIndexedDB] Database closed due to version change. Will reopen on next access.");
1248
+ };
1249
+ const missingStandards = ["cache", "queue", "dead_letter"].some((s) => !db.objectStoreNames.contains(s));
1250
+ if (missingStandards) {
1251
+ try {
1252
+ const upgraded = await KatluxIndexedDB.upgradeToVersion((db.version || 1) + 1);
1253
+ resolve(upgraded);
1254
+ return;
1255
+ } catch (e) {
1256
+ }
1257
+ }
1258
+ resolve(KatluxIndexedDB.db);
1259
+ };
1260
+ req.onerror = () => {
1261
+ KatluxIndexedDB.openPromise = null;
1262
+ reject(req.error);
1263
+ };
1264
+ req.onblocked = () => {
1265
+ console.warn("[KatluxIndexedDB] Database upgrade blocked by another open connection.");
1266
+ };
1267
+ });
1268
+ return this.openPromise;
1269
+ }
1270
+ static async upgradeToVersion(newVersion) {
1271
+ KatluxIndexedDB.currentVersion = newVersion;
1272
+ if (KatluxIndexedDB.db) {
1273
+ KatluxIndexedDB.db.close();
1274
+ KatluxIndexedDB.db = null;
1275
+ }
1276
+ KatluxIndexedDB.openPromise = null;
1277
+ return new Promise((resolve, reject) => {
1278
+ const req = indexedDB.open(KatluxIndexedDB.DB_NAME, newVersion);
1279
+ req.onupgradeneeded = (event) => {
1280
+ const upgradedDb = event.target.result;
1281
+ if (!upgradedDb.objectStoreNames.contains("cache")) upgradedDb.createObjectStore("cache");
1282
+ if (!upgradedDb.objectStoreNames.contains("queue")) upgradedDb.createObjectStore("queue");
1283
+ if (!upgradedDb.objectStoreNames.contains("dead_letter")) upgradedDb.createObjectStore("dead_letter");
1284
+ for (const s of KatluxIndexedDB.customStores) {
1285
+ if (!upgradedDb.objectStoreNames.contains(s)) {
1286
+ upgradedDb.createObjectStore(s);
1287
+ }
1288
+ }
1289
+ };
1290
+ req.onsuccess = () => {
1291
+ KatluxIndexedDB.db = req.result;
1292
+ KatluxIndexedDB.currentVersion = req.result.version;
1293
+ resolve(req.result);
1294
+ };
1295
+ req.onerror = () => {
1296
+ KatluxIndexedDB.openPromise = null;
1297
+ reject(req.error);
1298
+ };
1299
+ });
1300
+ }
1301
+ /**
1302
+ * Dynamically ensures that an object store exists in the database.
1303
+ * If not present, performs a database version bump and creates the store.
1304
+ */
1305
+ static async ensureStore(storeName) {
1306
+ KatluxIndexedDB.customStores.add(storeName);
1307
+ let db = await KatluxIndexedDB.open();
1308
+ if (!db.objectStoreNames.contains(storeName)) {
1309
+ const newVersion = (db.version || KatluxIndexedDB.currentVersion) + 1;
1310
+ db = await KatluxIndexedDB.upgradeToVersion(newVersion);
1311
+ }
1312
+ return db;
1313
+ }
1314
+ /**
1315
+ * Returns a transaction-bound object store.
1316
+ * Convenience wrapper used by CIndexedDBCache, QueueStorage adapters, etc.
1317
+ */
1318
+ static async getStore(storeName, mode) {
1319
+ let db = await KatluxIndexedDB.open();
1320
+ if (!db.objectStoreNames.contains(storeName)) {
1321
+ db = await KatluxIndexedDB.ensureStore(storeName);
1322
+ }
1323
+ return db.transaction(storeName, mode).objectStore(storeName);
1324
+ }
1325
+ /**
1326
+ * For testing only — resets the singleton so tests can start fresh.
1327
+ */
1328
+ static _reset() {
1329
+ if (this.db) {
684
1330
  this.db.close();
685
1331
  this.db = null;
686
1332
  }
@@ -814,8 +1460,11 @@ class RequestProviderRegistry {
814
1460
  /**
815
1461
  * Register a provider with one or more tags.
816
1462
  * If the provider is already registered, its tags are updated.
1463
+ * In SSR (Node.js), registration is skipped to prevent process-global memory leaks
1464
+ * and cross-user multi-tenant invalidation.
817
1465
  */
818
1466
  static register(provider, tags) {
1467
+ if (typeof window === "undefined") return;
819
1468
  const existing = this.entries.find((e) => e.provider === provider);
820
1469
  if (existing) {
821
1470
  existing.tags = tags;
@@ -835,7 +1484,7 @@ class RequestProviderRegistry {
835
1484
  */
836
1485
  static async refreshByTag(tag, hardRefresh = true) {
837
1486
  const matched = this.entries.filter((e) => e.tags.includes(tag));
838
- await Promise.all(matched.map((e) => e.provider.refresh(hardRefresh)));
1487
+ await Promise.allSettled(matched.map((e) => e.provider.refresh(hardRefresh)));
839
1488
  }
840
1489
  /**
841
1490
  * Called internally by RequestProvider (after non-GET success) and by
@@ -853,7 +1502,12 @@ class RequestProviderRegistry {
853
1502
  toRefresh.add(entry.provider);
854
1503
  }
855
1504
  }
856
- await Promise.all([...toRefresh].map((p) => p.refresh(true)));
1505
+ const results = await Promise.allSettled([...toRefresh].map((p) => p.refresh(true)));
1506
+ for (const res of results) {
1507
+ if (res.status === "rejected") {
1508
+ console.warn("[RequestProviderRegistry] Provider refresh failed during mutation notification:", res.reason);
1509
+ }
1510
+ }
857
1511
  }
858
1512
  /**
859
1513
  * Returns a copy of all registry entries.
@@ -872,13 +1526,96 @@ class RequestProviderRegistry {
872
1526
  }
873
1527
 
874
1528
  function generateId() {
1529
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1530
+ return crypto.randomUUID();
1531
+ }
1532
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
1533
+ const bytes = new Uint8Array(8);
1534
+ crypto.getRandomValues(bytes);
1535
+ return Date.now().toString(36) + Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
1536
+ }
875
1537
  return Date.now().toString(36) + Math.random().toString(36).slice(2);
876
1538
  }
1539
+ const SENSITIVE_HEADER_KEYS = ["authorization", "cookie", "set-cookie", "x-csrf-token"];
877
1540
  class RequestQueue {
878
1541
  // ── State ──────────────────────────────────────────────────────────────────
879
1542
  static queue = [];
880
1543
  static deadLetterQueue = [];
881
1544
  static isFlushing = false;
1545
+ // ── Capacity & Size Limits ────────────────────────────────────────────────
1546
+ static MAX_PAYLOAD_SIZE_BYTES = 5 * 1024 * 1024;
1547
+ // 5 MB default
1548
+ static MAX_QUEUE_SIZE = 500;
1549
+ static MAX_DEAD_LETTER_SIZE = 200;
1550
+ static setMaxPayloadSize(bytes) {
1551
+ this.MAX_PAYLOAD_SIZE_BYTES = bytes;
1552
+ }
1553
+ static setMaxQueueSize(limit) {
1554
+ this.MAX_QUEUE_SIZE = limit;
1555
+ }
1556
+ static setMaxDeadLetterSize(limit) {
1557
+ this.MAX_DEAD_LETTER_SIZE = limit;
1558
+ }
1559
+ /**
1560
+ * Strips sensitive headers (e.g., authorization, cookie, x-csrf-token) before persisting
1561
+ * request options to persistent storage (IndexedDB / LocalStorage).
1562
+ * Sensitive credentials must never be stored in plaintext in browser storage, and are
1563
+ * instead regenerated dynamically at execution time.
1564
+ */
1565
+ static sanitizeOptions(options) {
1566
+ if (!options) return {};
1567
+ const sanitized = {
1568
+ method: options.method
1569
+ };
1570
+ if (options.headers) {
1571
+ const headersObj = {};
1572
+ const sensitiveSet = new Set(SENSITIVE_HEADER_KEYS.map((k) => k.toLowerCase()));
1573
+ if (typeof options.headers.forEach === "function") {
1574
+ options.headers.forEach((value, key) => {
1575
+ if (!sensitiveSet.has(String(key).toLowerCase())) {
1576
+ headersObj[String(key)] = String(value);
1577
+ }
1578
+ });
1579
+ } else if (Array.isArray(options.headers)) {
1580
+ for (const [key, value] of options.headers) {
1581
+ if (!sensitiveSet.has(String(key).toLowerCase())) {
1582
+ headersObj[String(key)] = String(value);
1583
+ }
1584
+ }
1585
+ } else if (typeof options.headers === "object") {
1586
+ for (const [key, value] of Object.entries(options.headers)) {
1587
+ if (!sensitiveSet.has(key.toLowerCase())) {
1588
+ headersObj[key] = value;
1589
+ }
1590
+ }
1591
+ }
1592
+ sanitized.headers = headersObj;
1593
+ }
1594
+ if (options.query) {
1595
+ try {
1596
+ sanitized.query = JSON.parse(JSON.stringify(options.query));
1597
+ } catch (err) {
1598
+ throw new Error(`[RequestQueue] Failed to serialize request query parameters: ${err?.message || "circular structure"}`);
1599
+ }
1600
+ }
1601
+ if (options.body !== void 0) {
1602
+ try {
1603
+ const serialized = JSON.stringify(options.body);
1604
+ if (serialized && serialized.length > this.MAX_PAYLOAD_SIZE_BYTES) {
1605
+ throw new Error(
1606
+ `[RequestQueue] Payload size (${(serialized.length / (1024 * 1024)).toFixed(2)} MB) exceeds maximum allowed size (${(this.MAX_PAYLOAD_SIZE_BYTES / (1024 * 1024)).toFixed(2)} MB)`
1607
+ );
1608
+ }
1609
+ sanitized.body = JSON.parse(serialized);
1610
+ } catch (err) {
1611
+ if (err.message?.includes("exceeds maximum allowed size")) {
1612
+ throw err;
1613
+ }
1614
+ throw new Error(`[RequestQueue] Failed to serialize request body: ${err?.message || "circular structure"}`);
1615
+ }
1616
+ }
1617
+ return sanitized;
1618
+ }
882
1619
  // ── Subscribers ────────────────────────────────────────────────────────────
883
1620
  static _subscribers = /* @__PURE__ */ new Set();
884
1621
  static subscribe(listener) {
@@ -899,6 +1636,7 @@ class RequestQueue {
899
1636
  // ── Internal ──────────────────────────────────────────────────────────────
900
1637
  static adapter = QueueStorageFactory.getAdapter("IndexedDB");
901
1638
  static initialized = false;
1639
+ static initPromise = null;
902
1640
  static _onDeadLetter = null;
903
1641
  static _onFlushComplete = null;
904
1642
  static _onNetworkError = null;
@@ -909,10 +1647,24 @@ class RequestQueue {
909
1647
  */
910
1648
  static async init() {
911
1649
  if (this.initialized) return;
912
- this.initialized = true;
913
- this.queue = await this.adapter.loadQueue();
914
- this.deadLetterQueue = await this.adapter.loadDeadLetter();
915
- this.notify();
1650
+ if (this.initPromise) return this.initPromise;
1651
+ this.initPromise = (async () => {
1652
+ try {
1653
+ const loadedQueue = await this.adapter.loadQueue();
1654
+ const loadedDeadLetter = await this.adapter.loadDeadLetter();
1655
+ const existingIds = new Set(this.queue.map((i) => i.id));
1656
+ const mergedQueue = [...loadedQueue.filter((i) => !existingIds.has(i.id)), ...this.queue];
1657
+ const existingDlIds = new Set(this.deadLetterQueue.map((i) => i.id));
1658
+ const mergedDl = [...loadedDeadLetter.filter((i) => !existingDlIds.has(i.id)), ...this.deadLetterQueue];
1659
+ this.queue = mergedQueue;
1660
+ this.deadLetterQueue = mergedDl;
1661
+ this.initialized = true;
1662
+ this.notify();
1663
+ } finally {
1664
+ this.initPromise = null;
1665
+ }
1666
+ })();
1667
+ return this.initPromise;
916
1668
  }
917
1669
  /**
918
1670
  * Set the storage backend. Call before init().
@@ -921,6 +1673,7 @@ class RequestQueue {
921
1673
  static setStorageBackend(backend) {
922
1674
  this.adapter = QueueStorageFactory.getAdapter(backend);
923
1675
  this.initialized = false;
1676
+ this.initPromise = null;
924
1677
  }
925
1678
  // ── Hooks ─────────────────────────────────────────────────────────────────
926
1679
  static onDeadLetter(cb) {
@@ -940,8 +1693,13 @@ class RequestQueue {
940
1693
  */
941
1694
  static async enqueue(operation) {
942
1695
  await this.init();
1696
+ const sanitizedOptions = this.sanitizeOptions(operation.options);
1697
+ if (this.queue.length >= this.MAX_QUEUE_SIZE) {
1698
+ this.queue = this.queue.slice(1);
1699
+ }
943
1700
  const item = {
944
1701
  ...operation,
1702
+ options: sanitizedOptions,
945
1703
  id: generateId(),
946
1704
  createdAt: Date.now(),
947
1705
  flushAttempts: 0,
@@ -1094,12 +1852,33 @@ class RequestQueue {
1094
1852
  this.notify();
1095
1853
  }
1096
1854
  // ── Internal helpers ──────────────────────────────────────────────────────
1855
+ static regenerateHeaders(existingHeaders) {
1856
+ const headers = {};
1857
+ if (existingHeaders) {
1858
+ if (typeof existingHeaders.forEach === "function") {
1859
+ existingHeaders.forEach((val, key) => {
1860
+ headers[String(key)] = String(val);
1861
+ });
1862
+ } else if (Array.isArray(existingHeaders)) {
1863
+ for (const [key, val] of existingHeaders) {
1864
+ headers[String(key)] = String(val);
1865
+ }
1866
+ } else if (typeof existingHeaders === "object") {
1867
+ Object.assign(headers, existingHeaders);
1868
+ }
1869
+ }
1870
+ if (typeof document !== "undefined" && document.cookie && !headers["cookie"] && !headers["Cookie"]) {
1871
+ headers["cookie"] = document.cookie;
1872
+ }
1873
+ return headers;
1874
+ }
1097
1875
  static async executeRequest(item) {
1098
1876
  const { url, options } = item;
1877
+ const headers = this.regenerateHeaders(options.headers);
1099
1878
  const fetchOptions = {
1100
1879
  method: item.method,
1101
1880
  body: options.body,
1102
- headers: options.headers,
1881
+ headers,
1103
1882
  query: options.query
1104
1883
  };
1105
1884
  const fetchFn = globalThis.$fetch || ofetch.$fetch;
@@ -1113,6 +1892,9 @@ class RequestQueue {
1113
1892
  httpStatus
1114
1893
  };
1115
1894
  this.queue = this.queue.filter((i) => i.id !== item.id);
1895
+ if (this.deadLetterQueue.length >= this.MAX_DEAD_LETTER_SIZE) {
1896
+ this.deadLetterQueue = this.deadLetterQueue.slice(1);
1897
+ }
1116
1898
  this.deadLetterQueue = [...this.deadLetterQueue, deadItem];
1117
1899
  await this.persistQueue();
1118
1900
  await this.persistDeadLetter();
@@ -1134,11 +1916,45 @@ class RequestQueue {
1134
1916
  this._onDeadLetter = null;
1135
1917
  this._onFlushComplete = null;
1136
1918
  this._onNetworkError = null;
1919
+ this.MAX_PAYLOAD_SIZE_BYTES = 5 * 1024 * 1024;
1920
+ this.MAX_QUEUE_SIZE = 500;
1921
+ this.MAX_DEAD_LETTER_SIZE = 200;
1137
1922
  this._subscribers.clear();
1138
1923
  QueueStorageFactory._reset();
1139
1924
  }
1140
1925
  }
1141
1926
 
1927
+ function hashIdentity(str) {
1928
+ if (typeof globalThis.process !== "undefined" && globalThis.process.versions?.node) {
1929
+ try {
1930
+ const getBuiltin = globalThis.process.getBuiltinModule;
1931
+ if (typeof getBuiltin === "function") {
1932
+ const crypto = getBuiltin("node:crypto");
1933
+ if (crypto?.createHash) {
1934
+ return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
1935
+ }
1936
+ }
1937
+ const req = typeof require !== "undefined" ? require : globalThis.__non_webpack_require__;
1938
+ if (req) {
1939
+ const crypto = req("node:crypto");
1940
+ if (crypto?.createHash) {
1941
+ return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
1942
+ }
1943
+ }
1944
+ } catch {
1945
+ }
1946
+ }
1947
+ let h1 = 3735928559 ^ 5381;
1948
+ let h2 = 1103547991 ^ 5381;
1949
+ for (let i = 0; i < str.length; i++) {
1950
+ const ch = str.charCodeAt(i);
1951
+ h1 = Math.imul(h1 ^ ch, 2654435761);
1952
+ h2 = Math.imul(h2 ^ ch, 1597334677);
1953
+ }
1954
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
1955
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
1956
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16);
1957
+ }
1142
1958
  class RequestProvider {
1143
1959
  cacheProvider = null;
1144
1960
  cacheStrategy;
@@ -1189,6 +2005,15 @@ class RequestProvider {
1189
2005
  onDataReceived(callback) {
1190
2006
  this.dataReceivedCallback = callback;
1191
2007
  }
2008
+ invokeDataReceivedCallback(data, generation) {
2009
+ if (this.dataReceivedCallback) {
2010
+ try {
2011
+ this.dataReceivedCallback(data, generation);
2012
+ } catch (err) {
2013
+ console.error("[RequestProvider] dataReceivedCallback threw an error:", err);
2014
+ }
2015
+ }
2016
+ }
1192
2017
  hasLastUrl() {
1193
2018
  return !!this.lastUrl;
1194
2019
  }
@@ -1206,18 +2031,79 @@ class RequestProvider {
1206
2031
  }
1207
2032
  return this.request(this.lastUrl, options);
1208
2033
  }
2034
+ resolveContext(options) {
2035
+ if (options?.context) return options.context;
2036
+ try {
2037
+ const getReqEvent = globalThis.useRequestEvent;
2038
+ if (typeof getReqEvent === "function") {
2039
+ const evt = getReqEvent();
2040
+ if (evt) return { event: evt };
2041
+ }
2042
+ const app = globalThis.__KATLUX_APP__ || (globalThis.useNuxtApp ? globalThis.useNuxtApp() : null);
2043
+ if (app?.ssrContext?.event) {
2044
+ return { event: app.ssrContext.event };
2045
+ }
2046
+ } catch {
2047
+ }
2048
+ return null;
2049
+ }
2050
+ getInFlightMap(options) {
2051
+ const ctx = this.resolveContext(options);
2052
+ const isServer = typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined || !!ctx?.event || !!ctx?.ssrContext || !!ctx?.node;
2053
+ if (isServer) {
2054
+ const event = ctx?.event ?? ctx?.ssrContext?.event ?? (ctx?.node ? ctx : null);
2055
+ if (event) {
2056
+ if (!event.context) event.context = {};
2057
+ if (!event.context.__katluxRequestsInFlight) {
2058
+ event.context.__katluxRequestsInFlight = /* @__PURE__ */ new Map();
2059
+ }
2060
+ return event.context.__katluxRequestsInFlight;
2061
+ }
2062
+ }
2063
+ return RequestProvider.requestsInFlight;
2064
+ }
1209
2065
  getUniqueKey(url, options) {
1210
2066
  const namespace = options?.cacheKey || this.cacheKey;
1211
- if (options?.key) return namespace ? `${namespace}:${options.key}` : options.key;
1212
2067
  const { query, body, headers, method } = options || {};
1213
2068
  const stableStringify = (val) => JSON.stringify(val === void 0 ? null : val);
1214
- const baseKey = [
2069
+ let serverAuthIdentity = "";
2070
+ const ctx = this.resolveContext(options);
2071
+ const isServer = typeof window === "undefined" || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined || !!ctx?.event || !!ctx?.ssrContext || !!ctx?.node;
2072
+ if (isServer) {
2073
+ const event = ctx?.event ?? ctx?.ssrContext?.event ?? (ctx?.node ? ctx : null);
2074
+ if (event?.headers?.get) {
2075
+ serverAuthIdentity = event.headers.get("cookie") || event.headers.get("authorization") || "";
2076
+ } else if (event?.node?.req?.headers) {
2077
+ const reqH = event.node.req.headers;
2078
+ serverAuthIdentity = reqH["cookie"] || reqH["authorization"] || "";
2079
+ }
2080
+ }
2081
+ if (options?.key) {
2082
+ const authSuffix = serverAuthIdentity ? `|${hashIdentity(serverAuthIdentity)}` : "";
2083
+ const fullKey = `${options.key}${authSuffix}`;
2084
+ return namespace ? `${namespace}:${fullKey}` : fullKey;
2085
+ }
2086
+ let headersForCache = headers || {};
2087
+ if (!isServer && headers) {
2088
+ headersForCache = {};
2089
+ for (const [k, v] of Object.entries(headers)) {
2090
+ const lower = k.toLowerCase();
2091
+ if (lower !== "authorization" && lower !== "cookie") {
2092
+ headersForCache[k] = v;
2093
+ }
2094
+ }
2095
+ }
2096
+ const parts = [
1215
2097
  url,
1216
2098
  stableStringify(query || {}),
1217
2099
  stableStringify(body || null),
1218
- stableStringify(headers || {}),
1219
- method || "GET"
1220
- ].join("|");
2100
+ stableStringify(headersForCache)
2101
+ ];
2102
+ if (serverAuthIdentity) {
2103
+ parts.push(hashIdentity(serverAuthIdentity));
2104
+ }
2105
+ parts.push(method || "GET");
2106
+ const baseKey = parts.join("|");
1221
2107
  return namespace ? `${namespace}:${baseKey}` : baseKey;
1222
2108
  }
1223
2109
  registerRequest(url, options) {
@@ -1234,15 +2120,16 @@ class RequestProvider {
1234
2120
  label
1235
2121
  });
1236
2122
  }
2123
+ const inFlightMap = this.getInFlightMap(options);
1237
2124
  const uniqueKey = this.getUniqueKey(url, options);
1238
- const shouldDeduplicate = options?.deduplicate ?? this.deduplicate;
1239
- if (shouldDeduplicate && RequestProvider.requestsInFlight.has(uniqueKey)) {
1240
- const inflightPromise = RequestProvider.requestsInFlight.get(uniqueKey);
2125
+ const shouldDeduplicate = (options?.deduplicate ?? this.deduplicate) && method === "GET";
2126
+ if (shouldDeduplicate && inFlightMap.has(uniqueKey)) {
2127
+ const inflightPromise = inFlightMap.get(uniqueKey);
1241
2128
  return inflightPromise.then((result) => {
1242
2129
  this.lastUrl = url;
1243
2130
  this.lastOptions = options;
1244
- if (this.dataReceivedCallback && method === "GET") {
1245
- this.dataReceivedCallback(result);
2131
+ if (method === "GET") {
2132
+ this.invokeDataReceivedCallback(result, options?._generation);
1246
2133
  }
1247
2134
  return result;
1248
2135
  });
@@ -1258,11 +2145,11 @@ class RequestProvider {
1258
2145
  RequestProvider.executeAll();
1259
2146
  }).finally(() => {
1260
2147
  if (shouldDeduplicate) {
1261
- RequestProvider.requestsInFlight.delete(uniqueKey);
2148
+ inFlightMap.delete(uniqueKey);
1262
2149
  }
1263
2150
  });
1264
2151
  if (shouldDeduplicate) {
1265
- RequestProvider.requestsInFlight.set(uniqueKey, promise);
2152
+ inFlightMap.set(uniqueKey, promise);
1266
2153
  }
1267
2154
  return promise;
1268
2155
  }
@@ -1282,18 +2169,45 @@ class RequestProvider {
1282
2169
  }
1283
2170
  });
1284
2171
  }
2172
+ isSameOriginUrl(url, context) {
2173
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
2174
+ return true;
2175
+ }
2176
+ try {
2177
+ const targetUrl = new URL(url);
2178
+ if (typeof window !== "undefined" && typeof window.location !== "undefined") {
2179
+ return targetUrl.origin === window.location.origin;
2180
+ }
2181
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2182
+ const host = event?.node?.req?.headers?.host || event?.headers?.get?.("host");
2183
+ if (host) {
2184
+ return targetUrl.host === host;
2185
+ }
2186
+ } catch {
2187
+ return false;
2188
+ }
2189
+ return false;
2190
+ }
1285
2191
  async request(url, options) {
1286
2192
  const { cacheStrategy, lifetime, query, body, headers, method } = options || {};
1287
2193
  const uniqueKey = this.getUniqueKey(url, options);
1288
- const nuxtApp = options?.nuxtApp;
2194
+ const context = this.resolveContext(options);
1289
2195
  let serverHeaders = {};
1290
- if (nuxtApp && undefined) {
1291
- const event = nuxtApp.ssrContext?.event;
2196
+ const isServer = typeof window === "undefined" || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined || !!context?.event || !!context?.ssrContext || !!context?.node;
2197
+ if (context && isServer && this.isSameOriginUrl(url, context)) {
2198
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
1292
2199
  if (event) {
1293
- const { getRequestHeader } = await import('h3');
1294
- const cookieHeader = getRequestHeader(event, "cookie");
1295
- if (cookieHeader) {
1296
- serverHeaders = { cookie: cookieHeader };
2200
+ try {
2201
+ const { getRequestHeader } = await import('h3');
2202
+ const cookieHeader = getRequestHeader(event, "cookie");
2203
+ if (cookieHeader) {
2204
+ serverHeaders = { cookie: cookieHeader };
2205
+ }
2206
+ } catch {
2207
+ const cookieHeader = event.node?.req?.headers?.cookie || event.headers?.get?.("cookie");
2208
+ if (cookieHeader) {
2209
+ serverHeaders = { cookie: cookieHeader };
2210
+ }
1297
2211
  }
1298
2212
  }
1299
2213
  }
@@ -1301,49 +2215,72 @@ class RequestProvider {
1301
2215
  const cacheLifetime = lifetime || this.cacheLifetime;
1302
2216
  const requestMethod = method || "GET";
1303
2217
  const isGetRequest = requestMethod === "GET";
1304
- if (provider && isGetRequest && !options?.disableCache) {
1305
- const cached = await provider.get(uniqueKey, nuxtApp);
1306
- if (cached) {
2218
+ const effectiveHeaders = { ...headers, ...serverHeaders };
2219
+ const hasCookieOrAuth = !!serverHeaders.cookie || !!headers?.cookie || !!headers?.Cookie || !!headers?.authorization || !!headers?.Authorization;
2220
+ const isAppCache = provider instanceof CApplicationCache || provider?.constructor?.name === "CApplicationCache" || cacheStrategy === ECacheStrategy.Application;
2221
+ const isServerMemoryCache = typeof window === "undefined" && (provider instanceof CMemoryCache || provider?.constructor?.name === "CMemoryCache" || cacheStrategy === ECacheStrategy.Memory);
2222
+ const canReadFromCache = provider && isGetRequest && !options?.disableCache && !((isAppCache || isServerMemoryCache) && hasCookieOrAuth);
2223
+ if (canReadFromCache) {
2224
+ const cached = await provider.get(uniqueKey, context);
2225
+ if (cached !== null && cached !== void 0) {
1307
2226
  this.lastUrl = url;
1308
2227
  this.lastOptions = options;
1309
- if (this.dataReceivedCallback) {
1310
- this.dataReceivedCallback(cached);
1311
- }
2228
+ this.invokeDataReceivedCallback(cached, options?._generation);
1312
2229
  return cached;
1313
2230
  }
1314
2231
  }
1315
2232
  const fetchOptions = {
1316
2233
  method: requestMethod,
1317
2234
  body,
1318
- headers: { ...headers, ...serverHeaders },
2235
+ headers: effectiveHeaders,
1319
2236
  query,
2237
+ ...options?.signal ? { signal: options.signal } : {},
1320
2238
  ...options?.disableCache ? { cache: "no-store" } : {}
1321
2239
  };
1322
2240
  const fetchFn = globalThis.$fetch || ofetch.$fetch;
1323
2241
  const responseData = await fetchFn(url, fetchOptions);
1324
2242
  let finalData = responseData;
1325
- if (!finalData && provider && isGetRequest) {
1326
- const cached = await provider.get(uniqueKey, nuxtApp);
1327
- if (cached) {
2243
+ if ((finalData === void 0 || finalData === null) && canReadFromCache) {
2244
+ const cached = await provider.get(uniqueKey, context);
2245
+ if (cached !== null && cached !== void 0) {
1328
2246
  finalData = cached;
1329
2247
  }
1330
2248
  }
1331
- if (provider && cacheLifetime && finalData && isGetRequest) {
1332
- await provider.set(uniqueKey, finalData, cacheLifetime, nuxtApp);
2249
+ const canWriteToCache = provider && cacheLifetime && (finalData !== void 0 && finalData !== null) && isGetRequest && !((isAppCache || isServerMemoryCache) && hasCookieOrAuth);
2250
+ if (canWriteToCache) {
2251
+ await provider.set(uniqueKey, finalData, cacheLifetime, context);
1333
2252
  }
1334
2253
  this.lastUrl = url;
1335
2254
  this.lastOptions = options;
1336
- if (this.dataReceivedCallback && isGetRequest && finalData) {
1337
- this.dataReceivedCallback(finalData);
2255
+ if (isGetRequest && (finalData !== void 0 && finalData !== null)) {
2256
+ this.invokeDataReceivedCallback(finalData, options?._generation);
1338
2257
  }
1339
2258
  const requestTags = options?.tags || this.tags;
1340
2259
  if (requestTags.length > 0 && requestMethod !== "GET") {
1341
- RequestProviderRegistry.notifyMutation(requestTags);
2260
+ try {
2261
+ await RequestProviderRegistry.notifyMutation(requestTags);
2262
+ } catch (err) {
2263
+ console.warn("[RequestProvider] notifyMutation failed:", err);
2264
+ }
1342
2265
  }
1343
2266
  return finalData;
1344
2267
  }
1345
2268
  }
1346
2269
 
2270
+ function normalizeDataResult(result) {
2271
+ if (result === null || result === void 0) return null;
2272
+ if (Array.isArray(result)) {
2273
+ return { rows: result, rowCount: result.length };
2274
+ }
2275
+ if (typeof result === "object") {
2276
+ const rows = Array.isArray(result.rows) ? result.rows : Array.isArray(result.data) ? result.data : Array.isArray(result.items) ? result.items : null;
2277
+ if (rows !== null) {
2278
+ return { rows, rowCount: result.rowCount ?? result.total ?? rows.length };
2279
+ }
2280
+ }
2281
+ return null;
2282
+ }
2283
+
1347
2284
  class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1348
2285
  apiUrl = "";
1349
2286
  contextKey = "";
@@ -1356,78 +2293,73 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1356
2293
  if (options?.cacheStrategy) this.cacheStrategy = options.cacheStrategy;
1357
2294
  if (options?.cacheLifetime) this.cacheLifetime = options.cacheLifetime;
1358
2295
  if (options?.refreshOnMutation !== void 0) this.refreshOnMutation = options.refreshOnMutation;
2296
+ if (options?.contextKey) this.contextKey = options.contextKey;
1359
2297
  this.requestProvider.onDataReceived((data) => {
1360
2298
  if (data) {
1361
- this.setData(data.rows || data);
2299
+ const normalized = normalizeDataResult(data);
2300
+ this.setData(normalized ? normalized.rows : data.rows || data);
1362
2301
  }
1363
2302
  });
1364
2303
  }
1365
2304
  setContextKey(key) {
1366
2305
  this.contextKey = key;
1367
- this.requestProvider.cacheKey = key;
1368
- if (this.cacheStrategy) this.requestProvider.setCacheProvider(this.cacheStrategy);
1369
- if (this.cacheLifetime) this.requestProvider.setCacheLifetime(this.cacheLifetime);
1370
2306
  }
1371
- async refresh(hardRefresh = false) {
1372
- await this.refreshData({ disableCache: hardRefresh });
2307
+ setCacheStrategy(strategy) {
2308
+ this.cacheStrategy = strategy;
2309
+ this.requestProvider.setCacheProvider(strategy);
2310
+ }
2311
+ setCacheLifetime(lifetime) {
2312
+ this.cacheLifetime = lifetime;
2313
+ this.requestProvider.setCacheLifetime(lifetime);
1373
2314
  }
1374
2315
  async refreshData(options) {
1375
- if (!this.requestProvider.hasLastUrl()) {
1376
- await this._initialFetch(options?.disableCache ?? false);
1377
- return;
1378
- }
1379
2316
  this.loading = true;
1380
2317
  this.error = null;
1381
- try {
1382
- await this.requestProvider.refresh(options?.disableCache ?? false);
1383
- } catch (err) {
1384
- this.error = err;
1385
- throw err;
1386
- } finally {
1387
- this.loading = false;
1388
- }
1389
- }
1390
- async _initialFetch(disableCache = false) {
1391
- if (!this.SSR && undefined) return;
2318
+ this.notify();
2319
+ const disableCache = options?.disableCache ?? false;
1392
2320
  const fetcher = async () => {
1393
2321
  const promise = this.requestProvider.registerRequest(this.apiUrl, {
1394
2322
  deduplicate: this.deduplicate,
1395
- nuxtApp: this.context,
1396
2323
  context: this.context,
1397
2324
  disableCache
1398
2325
  });
1399
- if (this.SSR && undefined) return await promise;
2326
+ if (this.SSR && typeof window === "undefined") return await promise;
1400
2327
  return promise;
1401
2328
  };
1402
2329
  const key = `${this.contextKey}`;
1403
2330
  if (this.contextKey && this.initialLoad && !disableCache) {
1404
- const result = index.getSSRData(key, this.context);
1405
- if (result && result.rows) {
1406
- this.setData(result.rows);
2331
+ const result = getSSRData(key, this.context);
2332
+ const normalized = normalizeDataResult(result);
2333
+ if (normalized) {
2334
+ this.setData(normalized.rows);
1407
2335
  this.initialLoad = false;
1408
2336
  this.loading = false;
1409
2337
  this.notify();
1410
2338
  return;
1411
2339
  }
1412
2340
  }
1413
- if (undefined && this.contextKey) {
2341
+ if (typeof window === "undefined" && this.contextKey) {
1414
2342
  if (disableCache) {
1415
- index.clearSSRData(key, this.context);
2343
+ clearSSRData(key, this.context);
1416
2344
  }
1417
- const result = await index.fetchWithSSR(key, fetcher, this.context);
1418
- if (result && result.rows) {
1419
- this.setData(result.rows);
2345
+ try {
2346
+ const result = await fetchWithSSR(key, fetcher, this.context);
2347
+ const normalized = normalizeDataResult(result);
2348
+ if (normalized) {
2349
+ this.setData(normalized.rows);
2350
+ return;
2351
+ }
2352
+ } finally {
1420
2353
  this.initialLoad = false;
1421
2354
  this.loading = false;
1422
2355
  this.notify();
1423
- return;
1424
2356
  }
1425
2357
  }
1426
2358
  if (!this.SSR) {
1427
2359
  try {
1428
2360
  await this.requestProvider.registerRequest(this.apiUrl, {
1429
2361
  deduplicate: this.deduplicate,
1430
- nuxtApp: this.nuxtApp,
2362
+ context: this.context,
1431
2363
  disableCache
1432
2364
  });
1433
2365
  this.error = null;
@@ -1452,28 +2384,33 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1452
2384
  }
1453
2385
  async setAPIUrl(url) {
1454
2386
  this.apiUrl = url;
1455
- this.setContextKey(url);
2387
+ if (!this.contextKey) {
2388
+ this.setContextKey(this.urlPageParam ? `${url}:${this.urlPageParam}` : url);
2389
+ }
1456
2390
  if (this.SSR && this.initialLoad) {
1457
- const ssrData = index.getSSRData(url, this.context);
1458
- if (ssrData && ssrData.rows) {
1459
- this.setData(ssrData.rows);
2391
+ const ssrData = getSSRData(this.contextKey, this.context);
2392
+ const normalized = normalizeDataResult(ssrData);
2393
+ if (normalized) {
2394
+ this.setData(normalized.rows);
1460
2395
  this.initialLoad = false;
1461
2396
  this.loading = false;
1462
2397
  this.notify();
1463
2398
  return;
1464
2399
  }
1465
2400
  }
1466
- this.loading = true;
1467
- this.error = null;
1468
- if (this.allData.length === 0)
2401
+ if (this.allData.length === 0) {
1469
2402
  await this.refreshData();
2403
+ } else {
2404
+ this.loading = false;
2405
+ this.notify();
2406
+ }
1470
2407
  }
1471
2408
  async create(item) {
1472
2409
  if (!this.apiUrl) return;
1473
2410
  const result = await this.requestProvider.registerRequest(this.apiUrl, {
1474
2411
  method: "POST",
1475
2412
  body: item,
1476
- nuxtApp: this.nuxtApp
2413
+ context: this.context
1477
2414
  });
1478
2415
  if (this.refreshOnMutation) {
1479
2416
  await this.refresh(true);
@@ -1488,7 +2425,7 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1488
2425
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
1489
2426
  }
1490
2427
  if (this.contextKey) {
1491
- index.clearSSRData(this.contextKey, this.context);
2428
+ clearSSRData(this.contextKey, this.context);
1492
2429
  }
1493
2430
  }
1494
2431
  }
@@ -1497,26 +2434,25 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1497
2434
  const result = await this.requestProvider.registerRequest(this.apiUrl, {
1498
2435
  method: "PUT",
1499
2436
  body: item,
1500
- nuxtApp: this.context,
1501
2437
  context: this.context
1502
2438
  });
1503
2439
  if (this.refreshOnMutation) {
1504
2440
  await this.refresh(true);
1505
2441
  } else {
1506
- const index$1 = this.allData.findIndex((row) => row[this.idKey] === item[this.idKey]);
1507
- if (index$1 !== -1) {
2442
+ const index = this.allData.findIndex((row) => row[this.idKey] === item[this.idKey]);
2443
+ if (index !== -1) {
1508
2444
  if (result && result.item) {
1509
- this.allData[index$1] = result.item;
2445
+ this.allData[index] = result.item;
1510
2446
  } else {
1511
- this.allData[index$1] = { ...this.allData[index$1], ...item };
2447
+ this.allData[index] = { ...this.allData[index], ...item };
1512
2448
  }
1513
- this.loadPageData();
2449
+ this.updateMap();
1514
2450
  }
1515
2451
  if (this.requestProvider.cacheProvider) {
1516
2452
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
1517
2453
  }
1518
2454
  if (this.contextKey) {
1519
- index.clearSSRData(this.contextKey, this.context);
2455
+ clearSSRData(this.contextKey, this.context);
1520
2456
  }
1521
2457
  }
1522
2458
  }
@@ -1527,7 +2463,6 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1527
2463
  await this.requestProvider.registerRequest(this.apiUrl, {
1528
2464
  method: "DELETE",
1529
2465
  body: { id: ids },
1530
- nuxtApp: this.context,
1531
2466
  context: this.context
1532
2467
  });
1533
2468
  if (this.refreshOnMutation) {
@@ -1540,7 +2475,7 @@ class CAPIFlatClientDataProvider extends CFlatClientDataProvider {
1540
2475
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
1541
2476
  }
1542
2477
  if (this.contextKey) {
1543
- index.clearSSRData(this.contextKey, this.context);
2478
+ clearSSRData(this.contextKey, this.context);
1544
2479
  }
1545
2480
  }
1546
2481
  }
@@ -1594,21 +2529,23 @@ class CFlatServerDataProvider extends ADataProvider {
1594
2529
  );
1595
2530
  try {
1596
2531
  if (!options?.disableCache && this.SSR && this.contextKey && this.initialLoad) {
1597
- const result = index.getSSRData(key, this.context);
1598
- if (result && result.rows && result.rows.length > 0) {
2532
+ const result = getSSRData(key, this.context);
2533
+ const normalized = normalizeDataResult(result);
2534
+ if (normalized) {
1599
2535
  if (requestId !== this.latestRequestId) return;
1600
- this.pageData = result.rows || [];
1601
- this.rowCount = result.rowCount ?? 0;
2536
+ this.pageData = normalized.rows;
2537
+ this.rowCount = normalized.rowCount;
1602
2538
  this.initialLoad = false;
1603
2539
  return;
1604
2540
  }
1605
2541
  }
1606
- if (this.SSR && this.contextKey && !options?.disableCache && (undefined || this.initialLoad)) {
1607
- const result = await index.fetchWithSSR(key, fetcher, this.context);
1608
- if (result && result.rows && result.rows.length > 0) {
2542
+ if (this.SSR && this.contextKey && !options?.disableCache && (typeof window === "undefined" || this.initialLoad)) {
2543
+ const result = await fetchWithSSR(key, fetcher, this.context);
2544
+ const normalized = normalizeDataResult(result);
2545
+ if (normalized) {
1609
2546
  if (requestId !== this.latestRequestId) return;
1610
- this.pageData = result.rows || [];
1611
- this.rowCount = result.rowCount ?? 0;
2547
+ this.pageData = normalized.rows;
2548
+ this.rowCount = normalized.rowCount;
1612
2549
  this.initialLoad = false;
1613
2550
  return;
1614
2551
  }
@@ -1616,8 +2553,14 @@ class CFlatServerDataProvider extends ADataProvider {
1616
2553
  const returnedData = await fetcher();
1617
2554
  if (requestId !== this.latestRequestId) return;
1618
2555
  if (returnedData) {
1619
- this.pageData = returnedData.rows || [];
1620
- this.rowCount = returnedData.rowCount ?? 0;
2556
+ const normalized = normalizeDataResult(returnedData);
2557
+ if (normalized) {
2558
+ this.pageData = normalized.rows;
2559
+ this.rowCount = normalized.rowCount;
2560
+ } else {
2561
+ this.pageData = returnedData.rows || [];
2562
+ this.rowCount = returnedData.rowCount ?? 0;
2563
+ }
1621
2564
  }
1622
2565
  this.initialLoad = false;
1623
2566
  } catch (err) {
@@ -1646,12 +2589,15 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1646
2589
  cacheLifetime = 0;
1647
2590
  refreshOnMutation = true;
1648
2591
  // Default true for server
2592
+ /** Incremented on every new request; stale onDataReceived callbacks are discarded. */
2593
+ _requestGeneration = 0;
1649
2594
  constructor(options) {
1650
2595
  super(options);
1651
2596
  if (options?.cacheStrategy) this.cacheStrategy = options.cacheStrategy;
1652
2597
  if (options?.cacheLifetime) this.cacheLifetime = options.cacheLifetime;
1653
2598
  if (options?.refreshOnMutation !== void 0) this.refreshOnMutation = options.refreshOnMutation;
1654
- this.requestProvider.onDataReceived((data) => {
2599
+ this.requestProvider.onDataReceived((data, generation) => {
2600
+ if (generation !== void 0 && generation !== this._requestGeneration) return;
1655
2601
  if (data) {
1656
2602
  this.pageData = data.rows || data;
1657
2603
  if (data.rowCount !== void 0) {
@@ -1664,23 +2610,21 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1664
2610
  if (hardRefresh && this.requestProvider.cacheProvider) {
1665
2611
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
1666
2612
  }
1667
- this.loading = true;
1668
- try {
1669
- await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
1670
- } finally {
1671
- this.loading = false;
1672
- }
2613
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
1673
2614
  }
1674
2615
  async refreshData(options) {
1675
2616
  await this.refresh(options?.disableCache ?? false);
1676
2617
  }
1677
2618
  async setAPIUrl(url) {
1678
2619
  this.apiUrl = url;
1679
- this.setContextKey(url);
2620
+ if (!this.contextKey) {
2621
+ this.setContextKey(this.urlPageParam ? `${url}:${this.urlPageParam}` : url);
2622
+ }
1680
2623
  if (this.cacheStrategy) this.requestProvider.setCacheProvider(this.cacheStrategy);
1681
2624
  if (this.cacheLifetime) this.requestProvider.setCacheLifetime(this.cacheLifetime);
1682
2625
  await this.setPageDataHandler(
1683
2626
  async (currentPage, pageSize, filter, sortList, options) => {
2627
+ const generation = ++this._requestGeneration;
1684
2628
  const queryParams = {
1685
2629
  pageNumber: currentPage,
1686
2630
  pageSize
@@ -1691,13 +2635,16 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1691
2635
  if (sortList && sortList.length > 0) {
1692
2636
  queryParams.sortList = sortList;
1693
2637
  }
1694
- return await this.requestProvider.registerRequest(this.apiUrl, {
2638
+ const result = await this.requestProvider.registerRequest(this.apiUrl, {
1695
2639
  query: queryParams,
1696
2640
  deduplicate: this.deduplicate,
1697
- nuxtApp: this.context,
1698
2641
  context: this.context,
1699
- disableCache: options?.disableCache
2642
+ disableCache: options?.disableCache,
2643
+ signal: options?.signal,
2644
+ _generation: generation
1700
2645
  });
2646
+ if (generation !== this._requestGeneration) return { rows: [], rowCount: 0 };
2647
+ return result;
1701
2648
  }
1702
2649
  );
1703
2650
  }
@@ -1708,7 +2655,6 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1708
2655
  await this.requestProvider.registerRequest(this.apiUrl, {
1709
2656
  method: "DELETE",
1710
2657
  body: { id: ids },
1711
- nuxtApp: this.context,
1712
2658
  context: this.context
1713
2659
  });
1714
2660
  if (this.refreshOnMutation !== false) {
@@ -1723,7 +2669,6 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1723
2669
  await this.requestProvider.registerRequest(this.apiUrl, {
1724
2670
  method: "POST",
1725
2671
  body: item,
1726
- nuxtApp: this.context,
1727
2672
  context: this.context
1728
2673
  });
1729
2674
  if (this.refreshOnMutation !== false) {
@@ -1738,7 +2683,6 @@ class CAPIFlatServerDataProvider extends CFlatServerDataProvider {
1738
2683
  await this.requestProvider.registerRequest(this.apiUrl, {
1739
2684
  method: "PUT",
1740
2685
  body: item,
1741
- nuxtApp: this.context,
1742
2686
  context: this.context
1743
2687
  });
1744
2688
  if (this.refreshOnMutation !== false) {
@@ -1775,10 +2719,16 @@ class CTreeClientDataProvider extends CFlatClientDataProvider {
1775
2719
  _staticNodesCache = null;
1776
2720
  _nodeMapCache = null;
1777
2721
  _sortedNodeIdsCache = null;
2722
+ _filteredNodesCache = null;
1778
2723
  invalidateStaticCache() {
1779
2724
  this._staticNodesCache = null;
1780
2725
  this._nodeMapCache = null;
1781
2726
  this._sortedNodeIdsCache = null;
2727
+ this._filteredNodesCache = null;
2728
+ }
2729
+ setFilter(filter, immediate = false) {
2730
+ this._filteredNodesCache = null;
2731
+ super.setFilter(filter, immediate);
1782
2732
  }
1783
2733
  get _staticNodes() {
1784
2734
  if (!this._staticNodesCache) {
@@ -1906,22 +2856,46 @@ class CTreeClientDataProvider extends CFlatClientDataProvider {
1906
2856
  }
1907
2857
  return sortedIds;
1908
2858
  }
1909
- isNodeVisible(node, nodeMap) {
1910
- if (node.parentId === null || !nodeMap.has(node.parentId)) return true;
2859
+ isNodeVisible(node, nodeMap, visibilityCache) {
2860
+ if (visibilityCache?.has(node.id)) {
2861
+ return visibilityCache.get(node.id);
2862
+ }
2863
+ if (node.parentId === null || !nodeMap.has(node.parentId)) {
2864
+ visibilityCache?.set(node.id, true);
2865
+ return true;
2866
+ }
2867
+ if (visibilityCache?.has(node.parentId)) {
2868
+ const parentVisible = visibilityCache.get(node.parentId);
2869
+ const isVisible2 = parentVisible && this.expandedNodes.has(node.parentId);
2870
+ visibilityCache.set(node.id, isVisible2);
2871
+ return isVisible2;
2872
+ }
1911
2873
  const visited = /* @__PURE__ */ new Set([node.id]);
1912
2874
  let currentId = node.parentId;
2875
+ let isVisible = true;
1913
2876
  while (currentId !== null) {
1914
2877
  if (visited.has(currentId)) {
1915
- return true;
2878
+ break;
1916
2879
  }
1917
2880
  visited.add(currentId);
2881
+ if (visibilityCache?.has(currentId)) {
2882
+ const ancestorVisible = visibilityCache.get(currentId);
2883
+ if (!ancestorVisible) {
2884
+ isVisible = false;
2885
+ break;
2886
+ }
2887
+ }
1918
2888
  const parent = nodeMap.get(currentId);
1919
- if (!parent) return true;
2889
+ if (!parent) break;
1920
2890
  const parentExpanded = this.expandedNodes.has(currentId);
1921
- if (!parentExpanded) return false;
2891
+ if (!parentExpanded) {
2892
+ isVisible = false;
2893
+ break;
2894
+ }
1922
2895
  currentId = parent.parentId !== null && nodeMap.has(parent.parentId) ? parent.parentId : null;
1923
2896
  }
1924
- return true;
2897
+ visibilityCache?.set(node.id, isVisible);
2898
+ return isVisible;
1925
2899
  }
1926
2900
  paginateNodes(visible) {
1927
2901
  const pageSize = this.pageSize;
@@ -1961,41 +2935,48 @@ class CTreeClientDataProvider extends CFlatClientDataProvider {
1961
2935
  }
1962
2936
  }
1963
2937
  updatePageData() {
1964
- if (!this._staticNodesCache || this._staticNodesCache.length !== this.allData.length) {
1965
- this.invalidateStaticCache();
1966
- }
1967
- const nodeMap = this._nodeMap;
1968
- const sortedIds = this._sortedNodeIds;
1969
- if (this.filter && this.filter.active) {
1970
- const matchingNodes = this._staticNodes.filter((node) => evaluateFilter(this.filter, node.data));
1971
- const matchingIds = new Set(matchingNodes.map((node) => node.id));
1972
- const visibleIds = /* @__PURE__ */ new Set();
1973
- matchingIds.forEach((id) => {
1974
- let current = nodeMap.get(id);
1975
- while (current) {
1976
- visibleIds.add(current.id);
1977
- current = current.parentId != null ? nodeMap.get(current.parentId) : void 0;
1978
- }
1979
- });
1980
- visibleIds.forEach((id) => {
1981
- if (nodeMap.get(id)?.hasChildren) {
1982
- this.expandedNodes.add(id);
1983
- }
1984
- });
1985
- const filteredNodes = sortedIds.filter((id) => visibleIds.has(id)).map((id) => {
1986
- const node = nodeMap.get(id);
1987
- return {
1988
- ...node,
1989
- isExpanded: this.expandedNodes.has(id)
1990
- };
1991
- });
2938
+ if (!this._staticNodesCache || this._staticNodesCache.length !== this.allData.length) {
2939
+ this.invalidateStaticCache();
2940
+ }
2941
+ const nodeMap = this._nodeMap;
2942
+ const sortedIds = this._sortedNodeIds;
2943
+ if (this.filter && this.filter.active) {
2944
+ if (!this._filteredNodesCache) {
2945
+ const matchingNodes = this._staticNodes.filter((node) => evaluateFilter(this.filter, node.data));
2946
+ const matchingIds = new Set(matchingNodes.map((node) => node.id));
2947
+ const visibleIds = /* @__PURE__ */ new Set();
2948
+ matchingIds.forEach((id) => {
2949
+ let current = nodeMap.get(id);
2950
+ while (current) {
2951
+ visibleIds.add(current.id);
2952
+ current = current.parentId != null ? nodeMap.get(current.parentId) : void 0;
2953
+ }
2954
+ });
2955
+ const filterExpanded = new Set(this.expandedNodes);
2956
+ visibleIds.forEach((id) => {
2957
+ if (nodeMap.get(id)?.hasChildren) {
2958
+ filterExpanded.add(id);
2959
+ }
2960
+ });
2961
+ this._filteredNodesCache = sortedIds.filter((id) => visibleIds.has(id)).map((id) => {
2962
+ const node = nodeMap.get(id);
2963
+ return {
2964
+ ...node,
2965
+ isExpanded: filterExpanded.has(id)
2966
+ };
2967
+ });
2968
+ }
2969
+ const filteredNodes = this._filteredNodesCache;
1992
2970
  this.filteredData = filteredNodes;
1993
- this.pageData = filteredNodes.map((node) => ({
2971
+ const paginated = this.paginateNodes(filteredNodes);
2972
+ this.pageData = paginated.map((node) => ({
1994
2973
  ...node.data,
1995
2974
  ...node,
1996
2975
  __treeNode: node
1997
2976
  }));
1998
- this.rowCount = filteredNodes.length;
2977
+ if (this.allData.length > 0) {
2978
+ this.initialLoad = false;
2979
+ }
1999
2980
  return;
2000
2981
  }
2001
2982
  const visible = this.visibleRows;
@@ -2033,10 +3014,11 @@ class CTreeClientDataProvider extends CFlatClientDataProvider {
2033
3014
  const nodeMap = this._nodeMap;
2034
3015
  const sortedIds = this._sortedNodeIds;
2035
3016
  const visibleNodes = [];
3017
+ const visibilityCache = /* @__PURE__ */ new Map();
2036
3018
  for (const id of sortedIds) {
2037
3019
  const staticNode = nodeMap.get(id);
2038
3020
  if (!staticNode) continue;
2039
- if (this.isNodeVisible(staticNode, nodeMap)) {
3021
+ if (this.isNodeVisible(staticNode, nodeMap, visibilityCache)) {
2040
3022
  visibleNodes.push({
2041
3023
  ...staticNode,
2042
3024
  isExpanded: this.expandedNodes.has(id)
@@ -2117,9 +3099,11 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2117
3099
  if (options?.cacheStrategy) this.cacheStrategy = options.cacheStrategy;
2118
3100
  if (options?.cacheLifetime) this.cacheLifetime = options.cacheLifetime;
2119
3101
  if (options?.refreshOnMutation !== void 0) this.refreshOnMutation = options.refreshOnMutation;
3102
+ if (options?.contextKey) this.contextKey = options.contextKey;
2120
3103
  this.requestProvider.onDataReceived((data) => {
2121
3104
  if (data) {
2122
- this.setData(data.rows || data);
3105
+ const normalized = normalizeDataResult(data);
3106
+ this.setData(normalized ? normalized.rows : data.rows || data);
2123
3107
  }
2124
3108
  });
2125
3109
  }
@@ -2150,46 +3134,50 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2150
3134
  }
2151
3135
  }
2152
3136
  async _initialFetch(disableCache = false) {
2153
- if (!this.SSR && undefined) return;
3137
+ if (!this.SSR && typeof window === "undefined") return;
2154
3138
  const fetcher = async () => {
2155
3139
  const promise = this.requestProvider.registerRequest(this.apiUrl, {
2156
3140
  deduplicate: this.deduplicate,
2157
- nuxtApp: this.context,
2158
3141
  context: this.context,
2159
3142
  disableCache
2160
3143
  });
2161
- if (this.SSR && undefined) return await promise;
3144
+ if (this.SSR && typeof window === "undefined") return await promise;
2162
3145
  return promise;
2163
3146
  };
2164
3147
  const key = `${this.contextKey}`;
2165
3148
  if (this.contextKey && this.initialLoad && !disableCache) {
2166
- const result = index.getSSRData(key, this.context);
2167
- if (result && result.rows) {
2168
- this.setData(result.rows);
3149
+ const result = getSSRData(key, this.context);
3150
+ const normalized = normalizeDataResult(result);
3151
+ if (normalized) {
3152
+ this.setData(normalized.rows);
2169
3153
  this.initialLoad = false;
2170
3154
  this.loading = false;
2171
3155
  this.notify();
2172
3156
  return;
2173
3157
  }
2174
3158
  }
2175
- if (undefined && this.contextKey) {
3159
+ if (typeof window === "undefined" && this.contextKey) {
2176
3160
  if (disableCache) {
2177
- index.clearSSRData(key, this.context);
3161
+ clearSSRData(key, this.context);
2178
3162
  }
2179
- const result = await index.fetchWithSSR(key, fetcher, this.context);
2180
- if (result && result.rows) {
2181
- this.setData(result.rows);
3163
+ try {
3164
+ const result = await fetchWithSSR(key, fetcher, this.context);
3165
+ const normalized = normalizeDataResult(result);
3166
+ if (normalized) {
3167
+ this.setData(normalized.rows);
3168
+ return;
3169
+ }
3170
+ } finally {
2182
3171
  this.initialLoad = false;
2183
3172
  this.loading = false;
2184
3173
  this.notify();
2185
- return;
2186
3174
  }
2187
3175
  }
2188
3176
  if (!this.SSR) {
2189
3177
  try {
2190
3178
  await this.requestProvider.registerRequest(this.apiUrl, {
2191
3179
  deduplicate: this.deduplicate,
2192
- nuxtApp: this.nuxtApp,
3180
+ context: this.context,
2193
3181
  disableCache
2194
3182
  });
2195
3183
  this.error = null;
@@ -2213,19 +3201,34 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2213
3201
  }
2214
3202
  }
2215
3203
  async setAPIUrl(url) {
2216
- this.loading = true;
2217
- this.error = null;
2218
3204
  this.apiUrl = url;
2219
- this.setContextKey(url);
2220
- if (this.allData.length === 0)
3205
+ if (!this.contextKey) {
3206
+ this.setContextKey(this.urlPageParam ? `${url}:${this.urlPageParam}` : url);
3207
+ }
3208
+ if (this.SSR && this.initialLoad) {
3209
+ const ssrData = getSSRData(this.contextKey, this.context);
3210
+ const normalized = normalizeDataResult(ssrData);
3211
+ if (normalized) {
3212
+ this.setData(normalized.rows);
3213
+ this.initialLoad = false;
3214
+ this.loading = false;
3215
+ this.notify();
3216
+ return;
3217
+ }
3218
+ }
3219
+ if (this.allData.length === 0) {
2221
3220
  await this.refreshData();
3221
+ } else {
3222
+ this.loading = false;
3223
+ this.notify();
3224
+ }
2222
3225
  }
2223
3226
  async create(item) {
2224
3227
  if (!this.apiUrl) return;
2225
3228
  const result = await this.requestProvider.registerRequest(this.apiUrl, {
2226
3229
  method: "POST",
2227
3230
  body: item,
2228
- nuxtApp: this.nuxtApp
3231
+ context: this.context
2229
3232
  });
2230
3233
  if (this.refreshOnMutation) {
2231
3234
  await this.refresh(true);
@@ -2241,7 +3244,7 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2241
3244
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
2242
3245
  }
2243
3246
  if (this.contextKey) {
2244
- index.clearSSRData(this.contextKey, this.context);
3247
+ clearSSRData(this.contextKey, this.context);
2245
3248
  }
2246
3249
  }
2247
3250
  }
@@ -2250,18 +3253,17 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2250
3253
  const result = await this.requestProvider.registerRequest(this.apiUrl, {
2251
3254
  method: "PUT",
2252
3255
  body: item,
2253
- nuxtApp: this.context,
2254
3256
  context: this.context
2255
3257
  });
2256
3258
  if (this.refreshOnMutation) {
2257
3259
  await this.refresh(true);
2258
3260
  } else {
2259
- const index$1 = this.allData.findIndex((row) => row[this.idKey] === item[this.idKey]);
2260
- if (index$1 !== -1) {
3261
+ const index = this.allData.findIndex((row) => row[this.idKey] === item[this.idKey]);
3262
+ if (index !== -1) {
2261
3263
  if (result && result.item) {
2262
- this.allData[index$1] = result.item;
3264
+ this.allData[index] = result.item;
2263
3265
  } else {
2264
- this.allData[index$1] = { ...this.allData[index$1], ...item };
3266
+ this.allData[index] = { ...this.allData[index], ...item };
2265
3267
  }
2266
3268
  this.invalidateStaticCache();
2267
3269
  this.loadPageData();
@@ -2270,7 +3272,7 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2270
3272
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
2271
3273
  }
2272
3274
  if (this.contextKey) {
2273
- index.clearSSRData(this.contextKey, this.context);
3275
+ clearSSRData(this.contextKey, this.context);
2274
3276
  }
2275
3277
  }
2276
3278
  }
@@ -2281,7 +3283,6 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2281
3283
  await this.requestProvider.registerRequest(this.apiUrl, {
2282
3284
  method: "DELETE",
2283
3285
  body: { id: ids },
2284
- nuxtApp: this.context,
2285
3286
  context: this.context
2286
3287
  });
2287
3288
  if (this.refreshOnMutation) {
@@ -2295,7 +3296,7 @@ class CAPITreeClientDataProvider extends CTreeClientDataProvider {
2295
3296
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
2296
3297
  }
2297
3298
  if (this.contextKey) {
2298
- index.clearSSRData(this.contextKey, this.context);
3299
+ clearSSRData(this.contextKey, this.context);
2299
3300
  }
2300
3301
  }
2301
3302
  }
@@ -2374,21 +3375,23 @@ class CTreeServerDataProvider extends ADataProvider {
2374
3375
  );
2375
3376
  try {
2376
3377
  if (!options?.disableCache && this.SSR && this.contextKey && this.initialLoad) {
2377
- const result = index.getSSRData(key, this.context);
2378
- if (result && result.rows && result.rows.length > 0) {
3378
+ const result = getSSRData(key, this.context);
3379
+ const normalized = normalizeDataResult(result);
3380
+ if (normalized) {
2379
3381
  if (requestId !== this.latestRequestId) return;
2380
- this.pageData = result.rows || [];
2381
- this.rowCount = result.rowCount ?? 0;
3382
+ this.pageData = normalized.rows;
3383
+ this.rowCount = normalized.rowCount;
2382
3384
  this.initialLoad = false;
2383
3385
  return;
2384
3386
  }
2385
3387
  }
2386
- if (this.SSR && this.contextKey && !options?.disableCache && (undefined || this.initialLoad)) {
2387
- const result = await index.fetchWithSSR(key, fetcher, this.context);
2388
- if (result && result.rows && result.rows.length > 0) {
3388
+ if (this.SSR && this.contextKey && !options?.disableCache && (typeof window === "undefined" || this.initialLoad)) {
3389
+ const result = await fetchWithSSR(key, fetcher, this.context);
3390
+ const normalized = normalizeDataResult(result);
3391
+ if (normalized) {
2389
3392
  if (requestId !== this.latestRequestId) return;
2390
- this.pageData = result.rows || [];
2391
- this.rowCount = result.rowCount ?? 0;
3393
+ this.pageData = normalized.rows;
3394
+ this.rowCount = normalized.rowCount;
2392
3395
  this.initialLoad = false;
2393
3396
  return;
2394
3397
  }
@@ -2396,8 +3399,14 @@ class CTreeServerDataProvider extends ADataProvider {
2396
3399
  const returnedData = await fetcher();
2397
3400
  if (requestId !== this.latestRequestId) return;
2398
3401
  if (returnedData) {
2399
- this.pageData = returnedData.rows || [];
2400
- this.rowCount = returnedData.rowCount ?? 0;
3402
+ const normalized = normalizeDataResult(returnedData);
3403
+ if (normalized) {
3404
+ this.pageData = normalized.rows;
3405
+ this.rowCount = normalized.rowCount;
3406
+ } else {
3407
+ this.pageData = returnedData.rows || [];
3408
+ this.rowCount = returnedData.rowCount ?? 0;
3409
+ }
2401
3410
  }
2402
3411
  this.initialLoad = false;
2403
3412
  } catch (err) {
@@ -2469,12 +3478,15 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2469
3478
  cacheLifetime = 0;
2470
3479
  refreshOnMutation = true;
2471
3480
  // Default true for server
3481
+ /** Incremented on every new request; stale onDataReceived callbacks are discarded. */
3482
+ _requestGeneration = 0;
2472
3483
  constructor(options) {
2473
3484
  super(options);
2474
3485
  if (options?.cacheStrategy) this.cacheStrategy = options.cacheStrategy;
2475
3486
  if (options?.cacheLifetime) this.cacheLifetime = options.cacheLifetime;
2476
3487
  if (options?.refreshOnMutation !== void 0) this.refreshOnMutation = options.refreshOnMutation;
2477
- this.requestProvider.onDataReceived((data) => {
3488
+ this.requestProvider.onDataReceived((data, generation) => {
3489
+ if (generation !== void 0 && generation !== this._requestGeneration) return;
2478
3490
  if (data) {
2479
3491
  this.pageData = data.rows || data;
2480
3492
  if (data.rowCount !== void 0) {
@@ -2488,24 +3500,22 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2488
3500
  if (hardRefresh && this.requestProvider.cacheProvider) {
2489
3501
  await this.requestProvider.cacheProvider.removeByPrefix(this.apiUrl);
2490
3502
  }
2491
- this.loading = true;
2492
- try {
2493
- await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2494
- } finally {
2495
- this.loading = false;
2496
- }
3503
+ await this.loadPageData(hardRefresh ? { disableCache: true } : void 0);
2497
3504
  }
2498
3505
  async refreshData(options) {
2499
3506
  await this.refresh(options?.disableCache ?? false);
2500
3507
  }
2501
3508
  async setAPIUrl(url) {
2502
3509
  this.apiUrl = url;
2503
- this.setContextKey(url);
3510
+ if (!this.contextKey) {
3511
+ this.setContextKey(this.urlPageParam ? `${url}:${this.urlPageParam}` : url);
3512
+ }
2504
3513
  if (this.cacheStrategy) this.requestProvider.setCacheProvider(this.cacheStrategy);
2505
3514
  if (this.cacheLifetime) this.requestProvider.setCacheLifetime(this.cacheLifetime);
2506
3515
  await this.setPageDataHandler(
2507
3516
  async (currentPage, pageSize, filter, sortList, treeParams, options) => {
2508
- return await this.requestProvider.registerRequest(this.apiUrl, {
3517
+ const generation = ++this._requestGeneration;
3518
+ const result = await this.requestProvider.registerRequest(this.apiUrl, {
2509
3519
  query: {
2510
3520
  pageNumber: currentPage,
2511
3521
  pageSize,
@@ -2519,10 +3529,13 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2519
3529
  expandedByDefault: treeParams.expandedByDefault
2520
3530
  },
2521
3531
  deduplicate: this.deduplicate,
2522
- nuxtApp: this.context,
2523
3532
  context: this.context,
2524
- disableCache: options?.disableCache
3533
+ disableCache: options?.disableCache,
3534
+ signal: options?.signal,
3535
+ _generation: generation
2525
3536
  });
3537
+ if (generation !== this._requestGeneration) return { rows: [], rowCount: 0 };
3538
+ return result;
2526
3539
  }
2527
3540
  );
2528
3541
  }
@@ -2533,7 +3546,6 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2533
3546
  await this.requestProvider.registerRequest(this.apiUrl, {
2534
3547
  method: "DELETE",
2535
3548
  body: { id: ids },
2536
- nuxtApp: this.context,
2537
3549
  context: this.context
2538
3550
  });
2539
3551
  if (this.refreshOnMutation !== false) {
@@ -2548,7 +3560,6 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2548
3560
  await this.requestProvider.registerRequest(this.apiUrl, {
2549
3561
  method: "POST",
2550
3562
  body: item,
2551
- nuxtApp: this.context,
2552
3563
  context: this.context
2553
3564
  });
2554
3565
  if (this.refreshOnMutation !== false) {
@@ -2563,7 +3574,6 @@ class CAPITreeServerDataProvider extends CTreeServerDataProvider {
2563
3574
  await this.requestProvider.registerRequest(this.apiUrl, {
2564
3575
  method: "PUT",
2565
3576
  body: item,
2566
- nuxtApp: this.context,
2567
3577
  context: this.context
2568
3578
  });
2569
3579
  if (this.refreshOnMutation !== false) {
@@ -2599,11 +3609,12 @@ class CCookieCache extends ACacheProvider {
2599
3609
  }
2600
3610
  return null;
2601
3611
  }
2602
- isClient(nuxtApp) {
2603
- return typeof document !== "undefined" && !nuxtApp || !!undefined;
3612
+ isClient(context) {
3613
+ const isExplicitServer = typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined || !!context?.event || !!context?.ssrContext || !!context?.node;
3614
+ return typeof document !== "undefined" && !isExplicitServer || typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && !!undefined && !isExplicitServer;
2604
3615
  }
2605
- async getKeyList(nuxtApp) {
2606
- if (this.isClient(nuxtApp)) {
3616
+ async getKeyList(context) {
3617
+ if (this.isClient(context)) {
2607
3618
  const cookieStr = typeof document !== "undefined" ? document.cookie : "";
2608
3619
  if (!cookieStr) return [];
2609
3620
  const keys = [];
@@ -2620,8 +3631,8 @@ class CCookieCache extends ACacheProvider {
2620
3631
  }
2621
3632
  }
2622
3633
  return keys;
2623
- } else if (nuxtApp) {
2624
- const event = nuxtApp.ssrContext?.event;
3634
+ } else if (context) {
3635
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2625
3636
  if (event) {
2626
3637
  const cookies = h3.parseCookies(event);
2627
3638
  const keys = [];
@@ -2634,10 +3645,10 @@ class CCookieCache extends ACacheProvider {
2634
3645
  }
2635
3646
  return [];
2636
3647
  }
2637
- async get(key, nuxtApp) {
3648
+ async get(key, context) {
2638
3649
  const cookieKey = this.getCookieKey(key);
2639
3650
  let rawValue = null;
2640
- if (this.isClient(nuxtApp)) {
3651
+ if (this.isClient(context)) {
2641
3652
  const namePrefix = cookieKey + "=";
2642
3653
  const cookies = (typeof document !== "undefined" ? document.cookie : "").split(";");
2643
3654
  for (let i = 0; i < cookies.length; i++) {
@@ -2647,10 +3658,14 @@ class CCookieCache extends ACacheProvider {
2647
3658
  break;
2648
3659
  }
2649
3660
  }
2650
- } else if (nuxtApp) {
2651
- const event = nuxtApp.ssrContext?.event;
3661
+ } else if (context) {
3662
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2652
3663
  if (event) {
2653
- rawValue = h3.getCookie(event, cookieKey) ?? null;
3664
+ try {
3665
+ rawValue = h3.getCookie(event, cookieKey) ?? null;
3666
+ } catch {
3667
+ rawValue = null;
3668
+ }
2654
3669
  }
2655
3670
  }
2656
3671
  if (!rawValue) return null;
@@ -2666,7 +3681,7 @@ class CCookieCache extends ACacheProvider {
2666
3681
  if (Date.now() - val.timestamp <= val.lifetime) {
2667
3682
  return val.data;
2668
3683
  } else {
2669
- await this.remove(key, nuxtApp);
3684
+ await this.remove(key, context);
2670
3685
  }
2671
3686
  }
2672
3687
  return null;
@@ -2675,7 +3690,7 @@ class CCookieCache extends ACacheProvider {
2675
3690
  return null;
2676
3691
  }
2677
3692
  }
2678
- async set(key, data, lifetime, nuxtApp) {
3693
+ async set(key, data, lifetime, context) {
2679
3694
  const cookieKey = this.getCookieKey(key);
2680
3695
  const entry = {
2681
3696
  data,
@@ -2683,53 +3698,56 @@ class CCookieCache extends ACacheProvider {
2683
3698
  lifetime
2684
3699
  };
2685
3700
  const serialized = JSON.stringify(entry);
2686
- if (cookieKey.length + serialized.length > 4e3) {
2687
- console.warn(`[CCookieCache] Payload for key "${key}" exceeds cookie size limit. Skipping cookie write.`);
3701
+ const cookieValue = encodeURIComponent(serialized);
3702
+ if (cookieKey.length + cookieValue.length > 4e3) {
3703
+ console.warn(`[CCookieCache] Payload for key "${key}" exceeds cookie size limit (${cookieKey.length + cookieValue.length} bytes encoded). Skipping cookie write.`);
2688
3704
  return;
2689
3705
  }
2690
3706
  const maxAge = Math.floor(lifetime / 1e3);
2691
- const cookieValue = encodeURIComponent(serialized);
2692
- if (this.isClient(nuxtApp)) {
3707
+ if (this.isClient(context)) {
2693
3708
  if (typeof document !== "undefined") {
2694
3709
  document.cookie = `${cookieKey}=${cookieValue}; Max-Age=${maxAge}; Path=/; SameSite=Lax`;
2695
3710
  }
2696
- } else if (nuxtApp) {
2697
- const event = nuxtApp.ssrContext?.event;
3711
+ } else if (context) {
3712
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2698
3713
  if (event) {
2699
- h3.setCookie(event, cookieKey, serialized, {
2700
- maxAge,
2701
- path: "/",
2702
- sameSite: "lax",
2703
- httpOnly: true
2704
- });
3714
+ try {
3715
+ h3.setCookie(event, cookieKey, serialized, {
3716
+ maxAge,
3717
+ path: "/",
3718
+ sameSite: "lax",
3719
+ httpOnly: true
3720
+ });
3721
+ } catch {
3722
+ }
2705
3723
  }
2706
3724
  }
2707
3725
  }
2708
- async remove(key, nuxtApp) {
3726
+ async remove(key, context) {
2709
3727
  const cookieKey = this.getCookieKey(key);
2710
- if (this.isClient(nuxtApp)) {
3728
+ if (this.isClient(context)) {
2711
3729
  if (typeof document !== "undefined") {
2712
3730
  document.cookie = `${cookieKey}=; Max-Age=0; Path=/; SameSite=Lax`;
2713
3731
  }
2714
- } else if (nuxtApp) {
2715
- const event = nuxtApp.ssrContext?.event;
3732
+ } else if (context) {
3733
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2716
3734
  if (event) {
2717
3735
  h3.deleteCookie(event, cookieKey, { path: "/", sameSite: "lax", httpOnly: true });
2718
3736
  }
2719
3737
  }
2720
3738
  }
2721
- async removeByPrefix(prefix, nuxtApp) {
2722
- const keys = await this.getKeyList(nuxtApp);
3739
+ async removeByPrefix(prefix, context) {
3740
+ const keys = await this.getKeyList(context);
2723
3741
  for (const k of keys) {
2724
3742
  if (k.startsWith(prefix)) {
2725
- await this.remove(k, nuxtApp);
3743
+ await this.remove(k, context);
2726
3744
  }
2727
3745
  }
2728
3746
  }
2729
- async getRemainingTime(key, nuxtApp) {
3747
+ async getRemainingTime(key, context) {
2730
3748
  const cookieKey = this.getCookieKey(key);
2731
3749
  let rawValue = null;
2732
- if (this.isClient(nuxtApp)) {
3750
+ if (this.isClient(context)) {
2733
3751
  const namePrefix = cookieKey + "=";
2734
3752
  const cookies = (typeof document !== "undefined" ? document.cookie : "").split(";");
2735
3753
  for (let i = 0; i < cookies.length; i++) {
@@ -2739,8 +3757,8 @@ class CCookieCache extends ACacheProvider {
2739
3757
  break;
2740
3758
  }
2741
3759
  }
2742
- } else if (nuxtApp) {
2743
- const event = nuxtApp.ssrContext?.event;
3760
+ } else if (context) {
3761
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
2744
3762
  if (event) {
2745
3763
  rawValue = h3.getCookie(event, cookieKey) ?? null;
2746
3764
  }
@@ -2764,7 +3782,7 @@ class CCookieCache extends ACacheProvider {
2764
3782
  }
2765
3783
  }
2766
3784
  async cleanupExpired() {
2767
- if (undefined && typeof document !== "undefined") {
3785
+ if (this.isClient() && typeof document !== "undefined") {
2768
3786
  const now = Date.now();
2769
3787
  const cookies = document.cookie.split(";");
2770
3788
  for (let i = 0; i < cookies.length; i++) {
@@ -2796,16 +3814,16 @@ const CCookieCache$1 = {
2796
3814
  CCookieCache: CCookieCache
2797
3815
  };
2798
3816
 
2799
- class CSessionCache extends ACacheProvider {
3817
+ class CServerSessionCache extends ACacheProvider {
2800
3818
  static instance = null;
2801
3819
  static getInstance() {
2802
3820
  if (!this.instance) {
2803
- this.instance = new CSessionCache();
3821
+ this.instance = new CServerSessionCache();
2804
3822
  }
2805
3823
  return this.instance;
2806
3824
  }
2807
3825
  static get storage() {
2808
- const globalKey = Symbol.for("Katlux_CSessionCache_Storage");
3826
+ const globalKey = Symbol.for("Katlux_CServerSessionCache_Storage");
2809
3827
  const _global = globalThis;
2810
3828
  if (!_global[globalKey]) {
2811
3829
  _global[globalKey] = /* @__PURE__ */ new Map();
@@ -2815,32 +3833,62 @@ class CSessionCache extends ACacheProvider {
2815
3833
  static getSnapshot() {
2816
3834
  return this.storage;
2817
3835
  }
2818
- static cleanupTimer = null;
2819
- static initCleanupTimer() {
2820
- if (CSessionCache.cleanupTimer) return;
2821
- if (typeof window !== "undefined" && typeof setInterval !== "undefined") {
2822
- CSessionCache.cleanupTimer = setInterval(() => {
2823
- CSessionCache.getInstance().cleanupExpired().catch((err) => {
2824
- console.warn("[Katlux Cache] CSessionCache background cleanup error", err);
2825
- });
2826
- }, 5 * 60 * 1e3);
2827
- if (CSessionCache.cleanupTimer?.unref) {
2828
- CSessionCache.cleanupTimer.unref();
3836
+ static MAX_SERVER_SESSIONS = 5e3;
3837
+ /**
3838
+ * Purges expired entries across all server sessions synchronously when the storage
3839
+ * exceeds MAX_SERVER_SESSIONS. Avoids persistent background setInterval timers on Node.js/SSR.
3840
+ */
3841
+ static purgeExpiredServerSessions() {
3842
+ const now = Date.now();
3843
+ const prefix = "cache:";
3844
+ const sessionsToDelete = [];
3845
+ for (const [sessionId, sessionData] of CServerSessionCache.storage.entries()) {
3846
+ const keysToDelete = [];
3847
+ for (const [key, entry] of sessionData.entries()) {
3848
+ if (key.startsWith(prefix) && now - entry.timestamp > entry.lifetime) {
3849
+ keysToDelete.push(key);
3850
+ }
3851
+ }
3852
+ for (const key of keysToDelete) {
3853
+ sessionData.delete(key);
3854
+ }
3855
+ if (sessionData.size === 0) {
3856
+ sessionsToDelete.push(sessionId);
3857
+ }
3858
+ }
3859
+ for (const sessionId of sessionsToDelete) {
3860
+ CServerSessionCache.storage.delete(sessionId);
3861
+ }
3862
+ while (CServerSessionCache.storage.size >= CServerSessionCache.MAX_SERVER_SESSIONS && CServerSessionCache.storage.size > 0) {
3863
+ const oldestSessionKey = CServerSessionCache.storage.keys().next().value;
3864
+ if (oldestSessionKey) {
3865
+ CServerSessionCache.storage.delete(oldestSessionKey);
3866
+ } else {
3867
+ break;
2829
3868
  }
2830
3869
  }
2831
3870
  }
2832
3871
  sessionIdCache = null;
2833
- sessionId = null;
2834
3872
  SESSION_ID_KEY = "_session_id";
2835
3873
  constructor() {
2836
3874
  super();
2837
3875
  this.sessionIdCache = CCookieCache.getInstance();
2838
- CSessionCache.initCleanupTimer();
2839
3876
  }
2840
3877
  /**
2841
3878
  * Generate a UUID v4 sessionId
2842
3879
  */
2843
3880
  generateSessionId() {
3881
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3882
+ return crypto.randomUUID();
3883
+ }
3884
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
3885
+ const bytes = new Uint8Array(16);
3886
+ crypto.getRandomValues(bytes);
3887
+ bytes[6] = bytes[6] & 15 | 64;
3888
+ bytes[8] = bytes[8] & 63 | 128;
3889
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
3890
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
3891
+ }
2844
3892
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2845
3893
  const r = Math.random() * 16 | 0;
2846
3894
  const v = c === "x" ? r : r & 3 | 8;
@@ -2848,270 +3896,304 @@ class CSessionCache extends ACacheProvider {
2848
3896
  });
2849
3897
  }
2850
3898
  /**
2851
- * Get or create sessionId
3899
+ * Get or create sessionId — server-only path.
3900
+ * Returns '__no_session__' sentinel when no isolatable H3 event context is available.
2852
3901
  */
2853
- async getSessionId(nuxtApp) {
2854
- const contextSessionId = nuxtApp?.ssrContext?.event?.context?.sessionId;
3902
+ async getSessionId(context) {
3903
+ const event = context?.event ?? context?.ssrContext?.event ?? (context?.node ? context : null);
3904
+ if (!event) {
3905
+ return "__no_session__";
3906
+ }
3907
+ const contextSessionId = event?.context?.sessionId;
2855
3908
  if (contextSessionId) {
2856
3909
  return contextSessionId;
2857
3910
  }
2858
- if (this.sessionId) {
2859
- return this.sessionId;
3911
+ let existingId = null;
3912
+ const req = event.node?.req || event.req;
3913
+ const cookieHeader = req?.headers?.cookie || "";
3914
+ const match = cookieHeader.match(/(?:^|; )_session_id=([^;]*)/);
3915
+ if (match) existingId = decodeURIComponent(match[1]);
3916
+ if (!existingId && this.sessionIdCache) {
3917
+ existingId = await this.sessionIdCache.get(this.SESSION_ID_KEY, context);
2860
3918
  }
2861
- if (!this.sessionIdCache) {
2862
- return this.generateSessionId();
2863
- }
2864
- const existingId = await this.sessionIdCache.get(this.SESSION_ID_KEY, nuxtApp);
2865
3919
  if (existingId) {
2866
- this.sessionId = existingId;
3920
+ if (!event.context) event.context = {};
3921
+ event.context.sessionId = existingId;
2867
3922
  return existingId;
2868
3923
  }
2869
3924
  const newId = this.generateSessionId();
2870
- this.sessionId = newId;
3925
+ if (!event.context) event.context = {};
3926
+ event.context.sessionId = newId;
2871
3927
  if (this.sessionIdCache) {
2872
- await this.sessionIdCache.set(this.SESSION_ID_KEY, newId, 365 * 24 * 60 * 60 * 1e3, nuxtApp);
3928
+ await this.sessionIdCache.set(this.SESSION_ID_KEY, newId, 365 * 24 * 60 * 60 * 1e3, context);
2873
3929
  }
2874
3930
  return newId;
2875
3931
  }
2876
- async getKeyList(nuxtApp) {
3932
+ async getKeyList(context) {
2877
3933
  const prefix = "cache:";
2878
- if (undefined) {
2879
- return Object.keys(sessionStorage).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
2880
- }
2881
- const sessionId = await this.getSessionId(nuxtApp);
2882
- const sessionData = CSessionCache.storage.get(sessionId);
3934
+ const sessionId = await this.getSessionId(context);
3935
+ const sessionData = CServerSessionCache.storage.get(sessionId);
2883
3936
  if (!sessionData) {
2884
3937
  return [];
2885
3938
  }
2886
3939
  return Array.from(sessionData.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
2887
3940
  }
2888
- async get(key, nuxtApp) {
3941
+ async get(key, context) {
2889
3942
  const prefixedKey = "cache:" + key;
2890
- if (undefined) {
2891
- try {
2892
- const stored = sessionStorage.getItem(prefixedKey);
2893
- if (stored) {
2894
- const entry = JSON.parse(stored);
2895
- if (Date.now() - entry.timestamp <= entry.lifetime) {
2896
- return entry.data;
2897
- } else {
2898
- sessionStorage.removeItem(prefixedKey);
2899
- }
2900
- }
2901
- } catch (e) {
2902
- console.warn("[Katlux Cache] CSessionCache parse error for key: " + key, e);
2903
- }
2904
- try {
2905
- const payloadData = window.__NUXT__?.payload?.data;
2906
- if (payloadData && payloadData[prefixedKey]) {
2907
- const entry = payloadData[prefixedKey];
2908
- if (Date.now() - entry.timestamp <= entry.lifetime) {
2909
- window.sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
2910
- return entry.data;
2911
- }
2912
- }
2913
- } catch (e) {
2914
- console.warn("[Katlux Cache] CSessionCache SSR payload fallback error for key: " + key, e);
2915
- }
3943
+ const sessionId = await this.getSessionId(context);
3944
+ const sessionData = CServerSessionCache.storage.get(sessionId);
3945
+ if (!sessionData) {
2916
3946
  return null;
2917
3947
  }
2918
- if (undefined) {
2919
- const sessionId = await this.getSessionId(nuxtApp);
2920
- const sessionData = CSessionCache.storage.get(sessionId);
2921
- if (!sessionData) {
2922
- return null;
2923
- }
2924
- const entry = sessionData.get(prefixedKey);
2925
- if (!entry) {
2926
- return null;
2927
- }
2928
- if (Date.now() - entry.timestamp <= entry.lifetime) {
2929
- return entry.data;
2930
- } else {
2931
- sessionData.delete(prefixedKey);
2932
- return null;
2933
- }
3948
+ const entry = sessionData.get(prefixedKey);
3949
+ if (!entry) {
3950
+ return null;
3951
+ }
3952
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
3953
+ return entry.data;
3954
+ } else {
3955
+ sessionData.delete(prefixedKey);
3956
+ return null;
2934
3957
  }
2935
- return null;
2936
3958
  }
2937
- async set(key, data, lifetime, nuxtApp) {
3959
+ async set(key, data, lifetime, context) {
2938
3960
  const prefixedKey = "cache:" + key;
2939
3961
  const entry = {
2940
3962
  data,
2941
3963
  timestamp: Date.now(),
2942
3964
  lifetime
2943
3965
  };
2944
- if (undefined) {
2945
- try {
2946
- sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
2947
- } catch (e) {
2948
- console.warn("[Katlux Cache] CSessionCache sessionStorage setItem error (possible quota exceeded) for key: " + key, e);
3966
+ try {
3967
+ const sessionId = await this.getSessionId(context);
3968
+ if (sessionId === "__no_session__") return;
3969
+ if (CServerSessionCache.storage.size >= CServerSessionCache.MAX_SERVER_SESSIONS) {
3970
+ CServerSessionCache.purgeExpiredServerSessions();
2949
3971
  }
2950
- }
2951
- if (undefined || nuxtApp) {
2952
- try {
2953
- const sessionId = await this.getSessionId(nuxtApp);
2954
- let sessionData = CSessionCache.storage.get(sessionId);
2955
- if (!sessionData) {
2956
- sessionData = /* @__PURE__ */ new Map();
2957
- CSessionCache.storage.set(sessionId, sessionData);
2958
- }
2959
- sessionData.set(prefixedKey, entry);
2960
- if (nuxtApp) {
2961
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
2962
- if (payload) {
2963
- payload[prefixedKey] = entry;
2964
- }
2965
- }
2966
- } catch (e) {
2967
- console.warn("[Katlux Cache] CSessionCache server session storage error for key: " + key, e);
3972
+ let sessionData = CServerSessionCache.storage.get(sessionId);
3973
+ if (!sessionData) {
3974
+ sessionData = /* @__PURE__ */ new Map();
3975
+ CServerSessionCache.storage.set(sessionId, sessionData);
2968
3976
  }
3977
+ sessionData.set(prefixedKey, entry);
3978
+ } catch (e) {
3979
+ console.warn("[Katlux Cache] CServerSessionCache server session storage error for key: " + key, e);
2969
3980
  }
2970
3981
  }
2971
- async remove(key, nuxtApp) {
3982
+ async remove(key, context) {
2972
3983
  const prefixedKey = "cache:" + key;
2973
- if (undefined) {
2974
- sessionStorage.removeItem(prefixedKey);
2975
- }
2976
- if (undefined) {
2977
- try {
2978
- const sessionId = await this.getSessionId(nuxtApp);
2979
- const sessionData = CSessionCache.storage.get(sessionId);
2980
- if (sessionData) {
2981
- sessionData.delete(prefixedKey);
2982
- }
2983
- if (nuxtApp) {
2984
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
2985
- if (payload && payload[prefixedKey]) {
2986
- delete payload[prefixedKey];
2987
- }
3984
+ try {
3985
+ const sessionId = await this.getSessionId(context);
3986
+ const sessionData = CServerSessionCache.storage.get(sessionId);
3987
+ if (sessionData) {
3988
+ sessionData.delete(prefixedKey);
3989
+ }
3990
+ if (context) {
3991
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
3992
+ if (payload && payload[prefixedKey]) {
3993
+ delete payload[prefixedKey];
2988
3994
  }
2989
- } catch (e) {
2990
- console.warn("[Katlux Cache] CSessionCache remove error on server for key: " + key, e);
2991
3995
  }
3996
+ } catch (e) {
3997
+ console.warn("[Katlux Cache] CServerSessionCache remove error for key: " + key, e);
2992
3998
  }
2993
3999
  }
2994
- async removeByPrefix(prefix, nuxtApp) {
4000
+ async removeByPrefix(prefix, context) {
2995
4001
  const fullPrefix = "cache:" + prefix;
2996
- if (undefined) {
2997
- const keysToDelete = [];
2998
- for (let i = 0; i < sessionStorage.length; i++) {
2999
- const key = sessionStorage.key(i);
3000
- if (key && key.startsWith(fullPrefix)) {
3001
- keysToDelete.push(key);
4002
+ try {
4003
+ const sessionId = await this.getSessionId(context);
4004
+ const sessionData = CServerSessionCache.storage.get(sessionId);
4005
+ if (sessionData) {
4006
+ const keysToDelete = [];
4007
+ for (const key of sessionData.keys()) {
4008
+ if (key.startsWith(fullPrefix)) {
4009
+ keysToDelete.push(key);
4010
+ }
4011
+ }
4012
+ for (const key of keysToDelete) {
4013
+ sessionData.delete(key);
3002
4014
  }
3003
4015
  }
3004
- for (const key of keysToDelete) {
3005
- sessionStorage.removeItem(key);
3006
- }
3007
- }
3008
- if (undefined) {
3009
- try {
3010
- const sessionId = await this.getSessionId(nuxtApp);
3011
- const sessionData = CSessionCache.storage.get(sessionId);
3012
- if (sessionData) {
3013
- const keysToDelete = [];
3014
- for (const key of sessionData.keys()) {
4016
+ if (context) {
4017
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
4018
+ if (payload) {
4019
+ for (const key in payload) {
3015
4020
  if (key.startsWith(fullPrefix)) {
3016
- keysToDelete.push(key);
3017
- }
3018
- }
3019
- for (const key of keysToDelete) {
3020
- sessionData.delete(key);
3021
- }
3022
- }
3023
- if (nuxtApp) {
3024
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3025
- if (payload) {
3026
- for (const key in payload) {
3027
- if (key.startsWith(fullPrefix)) {
3028
- delete payload[key];
3029
- }
4021
+ delete payload[key];
3030
4022
  }
3031
4023
  }
3032
4024
  }
3033
- } catch (e) {
3034
- console.warn("[Katlux Cache] CSessionCache removeByPrefix error on server for prefix: " + prefix, e);
3035
4025
  }
4026
+ } catch (e) {
4027
+ console.warn("[Katlux Cache] CServerSessionCache removeByPrefix error for prefix: " + prefix, e);
3036
4028
  }
3037
4029
  }
3038
- async getRemainingTime(key, nuxtApp) {
4030
+ async getRemainingTime(key, context) {
3039
4031
  const prefixedKey = "cache:" + key;
3040
- if (undefined) {
3041
- const entryStr = sessionStorage.getItem(prefixedKey);
3042
- if (!entryStr) return null;
3043
- try {
3044
- const entry = JSON.parse(entryStr);
3045
- return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
3046
- } catch (e) {
3047
- console.warn("[Katlux Cache] CSessionCache getRemainingTime parse error for key: " + key, e);
3048
- return null;
3049
- }
3050
- }
3051
- if (undefined) {
3052
- const sessionId = await this.getSessionId(nuxtApp);
3053
- const sessionData = CSessionCache.storage.get(sessionId);
3054
- if (!sessionData) return null;
3055
- const entry = sessionData.get(prefixedKey);
3056
- if (!entry) return null;
3057
- return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
3058
- }
3059
- return null;
4032
+ const sessionId = await this.getSessionId(context);
4033
+ const sessionData = CServerSessionCache.storage.get(sessionId);
4034
+ if (!sessionData) return null;
4035
+ const entry = sessionData.get(prefixedKey);
4036
+ if (!entry) return null;
4037
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
3060
4038
  }
3061
4039
  async cleanupExpired() {
3062
4040
  const prefix = "cache:";
3063
4041
  const now = Date.now();
3064
- if (undefined) {
4042
+ const sessionsToDelete = [];
4043
+ for (const [sessionId, sessionData] of CServerSessionCache.storage.entries()) {
3065
4044
  const keysToDelete = [];
3066
- for (let i = 0; i < sessionStorage.length; i++) {
3067
- const key = sessionStorage.key(i);
3068
- if (key && key.startsWith(prefix)) {
3069
- const stored = sessionStorage.getItem(key);
3070
- if (stored) {
3071
- try {
3072
- const entry = JSON.parse(stored);
3073
- if (now - entry.timestamp > entry.lifetime) {
3074
- keysToDelete.push(key);
3075
- }
3076
- } catch (e) {
3077
- console.warn("[Katlux Cache] CSessionCache cleanupExpired parse error for key: " + key, e);
3078
- keysToDelete.push(key);
3079
- }
4045
+ for (const [key, entry] of sessionData.entries()) {
4046
+ if (key.startsWith(prefix)) {
4047
+ if (now - entry.timestamp > entry.lifetime) {
4048
+ keysToDelete.push(key);
3080
4049
  }
3081
4050
  }
3082
4051
  }
3083
4052
  for (const key of keysToDelete) {
3084
- sessionStorage.removeItem(key);
4053
+ sessionData.delete(key);
4054
+ }
4055
+ if (sessionData.size === 0) {
4056
+ sessionsToDelete.push(sessionId);
3085
4057
  }
3086
4058
  }
3087
- if (undefined || CSessionCache.storage.size > 0) {
3088
- const sessionsToDelete = [];
3089
- for (const [sessionId, sessionData] of CSessionCache.storage.entries()) {
3090
- const keysToDelete = [];
3091
- for (const [key, entry] of sessionData.entries()) {
3092
- if (key.startsWith(prefix)) {
4059
+ for (const sessionId of sessionsToDelete) {
4060
+ CServerSessionCache.storage.delete(sessionId);
4061
+ }
4062
+ }
4063
+ }
4064
+
4065
+ const CServerSessionCache$1 = {
4066
+ __proto__: null,
4067
+ CServerSessionCache: CServerSessionCache
4068
+ };
4069
+
4070
+ class CBrowserSessionCache extends ACacheProvider {
4071
+ static instance = null;
4072
+ static getInstance() {
4073
+ if (!this.instance) {
4074
+ this.instance = new CBrowserSessionCache();
4075
+ }
4076
+ return this.instance;
4077
+ }
4078
+ PREFIX = "bscache:";
4079
+ async getKeyList(_context) {
4080
+ if (typeof window === "undefined") return [];
4081
+ return Object.keys(sessionStorage).filter((key) => key.startsWith(this.PREFIX)).map((key) => key.substring(this.PREFIX.length));
4082
+ }
4083
+ async get(key, context) {
4084
+ if (typeof window === "undefined") return null;
4085
+ const prefixedKey = this.PREFIX + key;
4086
+ try {
4087
+ const stored = sessionStorage.getItem(prefixedKey);
4088
+ if (stored) {
4089
+ const entry = JSON.parse(stored);
4090
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
4091
+ return entry.data;
4092
+ } else {
4093
+ sessionStorage.removeItem(prefixedKey);
4094
+ }
4095
+ }
4096
+ } catch (e) {
4097
+ console.warn("[Katlux Cache] CBrowserSessionCache parse error for key: " + key, e);
4098
+ }
4099
+ try {
4100
+ const payloadData = getSSRPayload(context);
4101
+ if (payloadData && payloadData[prefixedKey]) {
4102
+ const entry = payloadData[prefixedKey];
4103
+ if (Date.now() - entry.timestamp <= entry.lifetime) {
4104
+ window.sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
4105
+ return entry.data;
4106
+ }
4107
+ }
4108
+ } catch (e) {
4109
+ console.warn("[Katlux Cache] CBrowserSessionCache SSR payload hydration error for key: " + key, e);
4110
+ }
4111
+ return null;
4112
+ }
4113
+ async set(key, data, lifetime, context) {
4114
+ const prefixedKey = this.PREFIX + key;
4115
+ const entry = {
4116
+ data,
4117
+ timestamp: Date.now(),
4118
+ lifetime
4119
+ };
4120
+ if (typeof window === "undefined") {
4121
+ try {
4122
+ const payload = context?.payload?.data ?? context?.ssrContext?.payload?.data;
4123
+ if (payload) {
4124
+ payload[prefixedKey] = entry;
4125
+ }
4126
+ } catch (e) {
4127
+ console.warn("[Katlux Cache] CBrowserSessionCache SSR payload write error for key: " + key, e);
4128
+ }
4129
+ return;
4130
+ }
4131
+ try {
4132
+ sessionStorage.setItem(prefixedKey, JSON.stringify(entry));
4133
+ } catch (e) {
4134
+ console.warn("[Katlux Cache] CBrowserSessionCache sessionStorage setItem error (possible quota exceeded) for key: " + key, e);
4135
+ }
4136
+ }
4137
+ async remove(key, _context) {
4138
+ if (typeof window === "undefined") return;
4139
+ sessionStorage.removeItem(this.PREFIX + key);
4140
+ }
4141
+ async removeByPrefix(prefix, _context) {
4142
+ if (typeof window === "undefined") return;
4143
+ const fullPrefix = this.PREFIX + prefix;
4144
+ const keysToDelete = [];
4145
+ for (let i = 0; i < sessionStorage.length; i++) {
4146
+ const key = sessionStorage.key(i);
4147
+ if (key && key.startsWith(fullPrefix)) {
4148
+ keysToDelete.push(key);
4149
+ }
4150
+ }
4151
+ for (const key of keysToDelete) {
4152
+ sessionStorage.removeItem(key);
4153
+ }
4154
+ }
4155
+ async getRemainingTime(key, _context) {
4156
+ if (typeof window === "undefined") return null;
4157
+ const stored = sessionStorage.getItem(this.PREFIX + key);
4158
+ if (!stored) return null;
4159
+ try {
4160
+ const entry = JSON.parse(stored);
4161
+ return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
4162
+ } catch (e) {
4163
+ console.warn("[Katlux Cache] CBrowserSessionCache getRemainingTime parse error for key: " + key, e);
4164
+ return null;
4165
+ }
4166
+ }
4167
+ async cleanupExpired(_context) {
4168
+ if (typeof window === "undefined") return;
4169
+ const now = Date.now();
4170
+ const keysToDelete = [];
4171
+ for (let i = 0; i < sessionStorage.length; i++) {
4172
+ const key = sessionStorage.key(i);
4173
+ if (key && key.startsWith(this.PREFIX)) {
4174
+ const stored = sessionStorage.getItem(key);
4175
+ if (stored) {
4176
+ try {
4177
+ const entry = JSON.parse(stored);
3093
4178
  if (now - entry.timestamp > entry.lifetime) {
3094
4179
  keysToDelete.push(key);
3095
4180
  }
4181
+ } catch (e) {
4182
+ console.warn("[Katlux Cache] CBrowserSessionCache cleanupExpired parse error for key: " + key, e);
4183
+ keysToDelete.push(key);
3096
4184
  }
3097
4185
  }
3098
- for (const key of keysToDelete) {
3099
- sessionData.delete(key);
3100
- }
3101
- if (sessionData.size === 0) {
3102
- sessionsToDelete.push(sessionId);
3103
- }
3104
- }
3105
- for (const sessionId of sessionsToDelete) {
3106
- CSessionCache.storage.delete(sessionId);
3107
4186
  }
3108
4187
  }
4188
+ for (const key of keysToDelete) {
4189
+ sessionStorage.removeItem(key);
4190
+ }
3109
4191
  }
3110
4192
  }
3111
4193
 
3112
- const CSessionCache$1 = {
4194
+ const CBrowserSessionCache$1 = {
3113
4195
  __proto__: null,
3114
- CSessionCache: CSessionCache
4196
+ CBrowserSessionCache: CBrowserSessionCache
3115
4197
  };
3116
4198
 
3117
4199
  class CLocalStorageCache extends ACacheProvider {
@@ -3125,13 +4207,13 @@ class CLocalStorageCache extends ACacheProvider {
3125
4207
  type = "LocalStorage";
3126
4208
  constructor() {
3127
4209
  super();
3128
- if (undefined) {
4210
+ if (typeof window !== "undefined") {
3129
4211
  this._hydrateFromPayload();
3130
4212
  }
3131
4213
  }
3132
4214
  async _hydrateFromPayload() {
3133
4215
  try {
3134
- const payloadData = index.getSSRPayload();
4216
+ const payloadData = getSSRPayload();
3135
4217
  if (!payloadData) return;
3136
4218
  const prefix = "cache:";
3137
4219
  for (const key in payloadData) {
@@ -3150,14 +4232,14 @@ class CLocalStorageCache extends ACacheProvider {
3150
4232
  console.warn("[Katlux Cache] LocalStorage payload hydration failed", e);
3151
4233
  }
3152
4234
  }
3153
- async getKeyList(nuxtApp) {
3154
- if (!undefined) return [];
4235
+ async getKeyList(context) {
4236
+ if (!(typeof window !== "undefined")) return [];
3155
4237
  const prefix = "cache:";
3156
4238
  return Object.keys(localStorage).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
3157
4239
  }
3158
- async get(key, nuxtApp) {
4240
+ async get(key, context) {
3159
4241
  const prefixedKey = "cache:" + key;
3160
- if (undefined) {
4242
+ if (typeof window !== "undefined") {
3161
4243
  try {
3162
4244
  const stored = localStorage.getItem(prefixedKey);
3163
4245
  if (stored) {
@@ -3173,11 +4255,11 @@ class CLocalStorageCache extends ACacheProvider {
3173
4255
  }
3174
4256
  }
3175
4257
  try {
3176
- const payloadData = index.getSSRPayload(nuxtApp);
4258
+ const payloadData = getSSRPayload(context);
3177
4259
  if (payloadData && payloadData[prefixedKey]) {
3178
4260
  const entry = payloadData[prefixedKey];
3179
4261
  if (Date.now() - entry.timestamp <= entry.lifetime) {
3180
- if (undefined) {
4262
+ if (typeof window !== "undefined") {
3181
4263
  localStorage.setItem(prefixedKey, JSON.stringify(entry));
3182
4264
  }
3183
4265
  return entry.data;
@@ -3188,24 +4270,14 @@ class CLocalStorageCache extends ACacheProvider {
3188
4270
  }
3189
4271
  return null;
3190
4272
  }
3191
- async set(key, data, lifetime, nuxtApp) {
4273
+ async set(key, data, lifetime, context) {
3192
4274
  const prefixedKey = "cache:" + key;
3193
4275
  const entry = {
3194
4276
  data,
3195
4277
  timestamp: Date.now(),
3196
4278
  lifetime
3197
4279
  };
3198
- if (undefined && nuxtApp) {
3199
- try {
3200
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3201
- if (payload) {
3202
- payload[prefixedKey] = entry;
3203
- }
3204
- } catch (e) {
3205
- console.warn("[Katlux Cache] LocalStorage error writing to SSR payload for key: " + key, e);
3206
- }
3207
- }
3208
- if (undefined) {
4280
+ if (typeof window !== "undefined") {
3209
4281
  try {
3210
4282
  localStorage.setItem(prefixedKey, JSON.stringify(entry));
3211
4283
  } catch (e) {
@@ -3213,14 +4285,14 @@ class CLocalStorageCache extends ACacheProvider {
3213
4285
  }
3214
4286
  }
3215
4287
  }
3216
- async remove(key, nuxtApp) {
4288
+ async remove(key, context) {
3217
4289
  const prefixedKey = "cache:" + key;
3218
- if (undefined) {
4290
+ if (typeof window !== "undefined") {
3219
4291
  localStorage.removeItem(prefixedKey);
3220
4292
  }
3221
- if (undefined && nuxtApp) {
4293
+ if (typeof window === "undefined" && context) {
3222
4294
  try {
3223
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
4295
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
3224
4296
  if (payload && payload[prefixedKey]) {
3225
4297
  delete payload[prefixedKey];
3226
4298
  }
@@ -3229,9 +4301,9 @@ class CLocalStorageCache extends ACacheProvider {
3229
4301
  }
3230
4302
  }
3231
4303
  }
3232
- async removeByPrefix(prefix, nuxtApp) {
4304
+ async removeByPrefix(prefix, context) {
3233
4305
  const fullPrefix = "cache:" + prefix;
3234
- if (undefined) {
4306
+ if (typeof window !== "undefined") {
3235
4307
  const keysToDelete = [];
3236
4308
  for (let i = 0; i < localStorage.length; i++) {
3237
4309
  const key = localStorage.key(i);
@@ -3243,9 +4315,9 @@ class CLocalStorageCache extends ACacheProvider {
3243
4315
  localStorage.removeItem(key);
3244
4316
  }
3245
4317
  }
3246
- if (undefined && nuxtApp) {
4318
+ if (typeof window === "undefined" && context) {
3247
4319
  try {
3248
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
4320
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
3249
4321
  if (payload) {
3250
4322
  for (const key in payload) {
3251
4323
  if (key.startsWith(fullPrefix)) {
@@ -3258,8 +4330,8 @@ class CLocalStorageCache extends ACacheProvider {
3258
4330
  }
3259
4331
  }
3260
4332
  }
3261
- async getRemainingTime(key, nuxtApp) {
3262
- if (undefined) {
4333
+ async getRemainingTime(key, context) {
4334
+ if (typeof window !== "undefined") {
3263
4335
  const prefixedKey = "cache:" + key;
3264
4336
  const entryStr = localStorage.getItem(prefixedKey);
3265
4337
  if (!entryStr) return null;
@@ -3274,7 +4346,7 @@ class CLocalStorageCache extends ACacheProvider {
3274
4346
  return null;
3275
4347
  }
3276
4348
  async cleanupExpired() {
3277
- if (undefined) {
4349
+ if (typeof window !== "undefined") {
3278
4350
  try {
3279
4351
  const prefix = "cache:";
3280
4352
  const now = Date.now();
@@ -3312,21 +4384,31 @@ const CLocalStorageCache$1 = {
3312
4384
 
3313
4385
  class CIndexedDBCache extends ACacheProvider {
3314
4386
  static instance = null;
3315
- static getInstance() {
3316
- if (!this.instance) {
3317
- this.instance = new CIndexedDBCache();
4387
+ static instances = /* @__PURE__ */ new Map();
4388
+ storeName;
4389
+ static getInstance(storeName = "cache") {
4390
+ if (storeName === "cache" && this.instance) {
4391
+ return this.instance;
3318
4392
  }
3319
- return this.instance;
4393
+ if (!this.instances.has(storeName)) {
4394
+ const inst = new CIndexedDBCache(storeName);
4395
+ this.instances.set(storeName, inst);
4396
+ if (storeName === "cache") {
4397
+ this.instance = inst;
4398
+ }
4399
+ }
4400
+ return this.instances.get(storeName);
3320
4401
  }
3321
- constructor() {
4402
+ constructor(storeName = "cache") {
3322
4403
  super();
3323
- if (undefined) {
4404
+ this.storeName = storeName;
4405
+ if (typeof window !== "undefined") {
3324
4406
  this._hydrateFromPayload();
3325
4407
  }
3326
4408
  }
3327
4409
  async _hydrateFromPayload() {
3328
4410
  try {
3329
- const payloadData = index.getSSRPayload();
4411
+ const payloadData = getSSRPayload();
3330
4412
  if (!payloadData) return;
3331
4413
  const prefix = "cache:";
3332
4414
  let count = 0;
@@ -3336,8 +4418,8 @@ class CIndexedDBCache extends ACacheProvider {
3336
4418
  if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
3337
4419
  KatluxIndexedDB.open().then(async (db) => {
3338
4420
  try {
3339
- const tx = db.transaction("cache", "readwrite");
3340
- const store = tx.objectStore("cache");
4421
+ const tx = db.transaction(this.storeName, "readwrite");
4422
+ const store = tx.objectStore(this.storeName);
3341
4423
  store.put(value, key);
3342
4424
  tx.commit?.();
3343
4425
  } catch (e) {
@@ -3354,10 +4436,10 @@ class CIndexedDBCache extends ACacheProvider {
3354
4436
  }
3355
4437
  }
3356
4438
  async getStore(mode) {
3357
- return KatluxIndexedDB.getStore("cache", mode);
4439
+ return KatluxIndexedDB.getStore(this.storeName, mode);
3358
4440
  }
3359
- async getKeyList(nuxtApp) {
3360
- if (!undefined) return [];
4441
+ async getKeyList(context) {
4442
+ if (!(typeof window !== "undefined")) return [];
3361
4443
  try {
3362
4444
  const store = await this.getStore("readonly");
3363
4445
  const keys = await new Promise((resolve, reject) => {
@@ -3372,9 +4454,9 @@ class CIndexedDBCache extends ACacheProvider {
3372
4454
  return [];
3373
4455
  }
3374
4456
  }
3375
- async get(key, nuxtApp) {
4457
+ async get(key, context) {
3376
4458
  const prefixedKey = "cache:" + key;
3377
- if (undefined) {
4459
+ if (typeof window !== "undefined") {
3378
4460
  try {
3379
4461
  const store = await this.getStore("readonly");
3380
4462
  const data = await new Promise((resolve, reject) => {
@@ -3395,12 +4477,12 @@ class CIndexedDBCache extends ACacheProvider {
3395
4477
  }
3396
4478
  }
3397
4479
  try {
3398
- const payloadData = index.getSSRPayload(nuxtApp);
4480
+ const payloadData = getSSRPayload(context);
3399
4481
  if (payloadData && payloadData[prefixedKey]) {
3400
4482
  const entry = payloadData[prefixedKey];
3401
4483
  if (Date.now() - entry.timestamp <= entry.lifetime) {
3402
- if (undefined) {
3403
- this.set(key, entry.data, entry.lifetime, nuxtApp);
4484
+ if (typeof window !== "undefined") {
4485
+ this.set(key, entry.data, entry.lifetime, context);
3404
4486
  }
3405
4487
  return entry.data;
3406
4488
  }
@@ -3410,24 +4492,14 @@ class CIndexedDBCache extends ACacheProvider {
3410
4492
  }
3411
4493
  return null;
3412
4494
  }
3413
- async set(key, data, lifetime, nuxtApp) {
4495
+ async set(key, data, lifetime, context) {
3414
4496
  const prefixedKey = "cache:" + key;
3415
4497
  const entry = {
3416
4498
  data,
3417
4499
  timestamp: Date.now(),
3418
4500
  lifetime
3419
4501
  };
3420
- if (undefined && nuxtApp) {
3421
- try {
3422
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3423
- if (payload) {
3424
- payload[prefixedKey] = entry;
3425
- }
3426
- } catch (e) {
3427
- console.warn("[Katlux Cache] IndexedDB error writing SSR payload for key: " + key, e);
3428
- }
3429
- }
3430
- if (undefined) {
4502
+ if (typeof window !== "undefined") {
3431
4503
  try {
3432
4504
  const store = await this.getStore("readwrite");
3433
4505
  await new Promise((resolve, reject) => {
@@ -3440,9 +4512,9 @@ class CIndexedDBCache extends ACacheProvider {
3440
4512
  }
3441
4513
  }
3442
4514
  }
3443
- async remove(key, nuxtApp) {
4515
+ async remove(key, context) {
3444
4516
  const prefixedKey = "cache:" + key;
3445
- if (undefined) {
4517
+ if (typeof window !== "undefined") {
3446
4518
  try {
3447
4519
  const store = await this.getStore("readwrite");
3448
4520
  await new Promise((resolve, reject) => {
@@ -3454,9 +4526,9 @@ class CIndexedDBCache extends ACacheProvider {
3454
4526
  console.warn("[Katlux Cache] IndexedDB error deleting key: " + key, e);
3455
4527
  }
3456
4528
  }
3457
- if (undefined && nuxtApp) {
4529
+ if (typeof window === "undefined" && context) {
3458
4530
  try {
3459
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
4531
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
3460
4532
  if (payload && payload[prefixedKey]) {
3461
4533
  delete payload[prefixedKey];
3462
4534
  }
@@ -3465,9 +4537,9 @@ class CIndexedDBCache extends ACacheProvider {
3465
4537
  }
3466
4538
  }
3467
4539
  }
3468
- async removeByPrefix(prefix, nuxtApp) {
4540
+ async removeByPrefix(prefix, context) {
3469
4541
  const fullPrefix = "cache:" + prefix;
3470
- if (undefined) {
4542
+ if (typeof window !== "undefined") {
3471
4543
  try {
3472
4544
  const store = await this.getStore("readwrite");
3473
4545
  const allKeys = await new Promise((resolve, reject) => {
@@ -3487,9 +4559,9 @@ class CIndexedDBCache extends ACacheProvider {
3487
4559
  console.warn("[Katlux Cache] IndexedDB error removing by prefix: " + prefix, e);
3488
4560
  }
3489
4561
  }
3490
- if (undefined && nuxtApp) {
4562
+ if (typeof window === "undefined" && context) {
3491
4563
  try {
3492
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
4564
+ const payload = context.payload?.data || context.ssrContext?.payload?.data;
3493
4565
  if (payload) {
3494
4566
  for (const key in payload) {
3495
4567
  if (key.startsWith(fullPrefix)) {
@@ -3502,8 +4574,8 @@ class CIndexedDBCache extends ACacheProvider {
3502
4574
  }
3503
4575
  }
3504
4576
  }
3505
- async getRemainingTime(key, nuxtApp) {
3506
- if (undefined) {
4577
+ async getRemainingTime(key, context) {
4578
+ if (typeof window !== "undefined") {
3507
4579
  try {
3508
4580
  const prefixedKey = "cache:" + key;
3509
4581
  const store = await this.getStore("readonly");
@@ -3522,7 +4594,7 @@ class CIndexedDBCache extends ACacheProvider {
3522
4594
  return null;
3523
4595
  }
3524
4596
  async cleanupExpired() {
3525
- if (!undefined) return;
4597
+ if (!(typeof window !== "undefined")) return;
3526
4598
  try {
3527
4599
  const prefix = "cache:";
3528
4600
  const now = Date.now();
@@ -3563,275 +4635,6 @@ const CIndexedDBCache$1 = {
3563
4635
  CIndexedDBCache: CIndexedDBCache
3564
4636
  };
3565
4637
 
3566
- class CMemoryCache extends ACacheProvider {
3567
- static instance = null;
3568
- static _storage = null;
3569
- static get storage() {
3570
- if (!this._storage) this._storage = /* @__PURE__ */ new Map();
3571
- return this._storage;
3572
- }
3573
- static getInstance() {
3574
- if (!this.instance) {
3575
- this.instance = new CMemoryCache();
3576
- }
3577
- return this.instance;
3578
- }
3579
- constructor() {
3580
- super();
3581
- if (undefined && CMemoryCache.storage.size === 0) {
3582
- this._hydrateFromPayload();
3583
- }
3584
- }
3585
- async _hydrateFromPayload() {
3586
- try {
3587
- const payloadData = index.getSSRPayload();
3588
- if (!payloadData) return;
3589
- for (const key in payloadData) {
3590
- const value = payloadData[key];
3591
- if (value && typeof value === "object" && "data" in value && "timestamp" in value && "lifetime" in value) {
3592
- if (typeof value.lifetime === "number") {
3593
- CMemoryCache.storage.set(key, value);
3594
- }
3595
- }
3596
- }
3597
- } catch (e) {
3598
- console.warn("[Katlux Cache] CMemoryCache payload hydration failed", e);
3599
- }
3600
- }
3601
- async getKeyList(nuxtApp) {
3602
- const prefix = "cache:";
3603
- return Array.from(CMemoryCache.storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
3604
- }
3605
- async get(key, nuxtApp) {
3606
- const prefixedKey = "cache:" + key;
3607
- const entry = CMemoryCache.storage.get(prefixedKey);
3608
- if (entry) {
3609
- if (Date.now() - entry.timestamp <= entry.lifetime) {
3610
- return entry.data;
3611
- } else {
3612
- CMemoryCache.storage.delete(prefixedKey);
3613
- }
3614
- }
3615
- try {
3616
- const payloadData = index.getSSRPayload(nuxtApp);
3617
- if (payloadData && payloadData[prefixedKey]) {
3618
- const entry2 = payloadData[prefixedKey];
3619
- if (Date.now() - entry2.timestamp <= entry2.lifetime) {
3620
- CMemoryCache.storage.set(prefixedKey, entry2);
3621
- return entry2.data;
3622
- }
3623
- }
3624
- } catch (e) {
3625
- console.warn("[Katlux Cache] CMemoryCache error reading SSR payload for key: " + key, e);
3626
- }
3627
- return null;
3628
- }
3629
- async set(key, data, lifetime, nuxtApp) {
3630
- const prefixedKey = "cache:" + key;
3631
- const entry = {
3632
- data,
3633
- timestamp: Date.now(),
3634
- lifetime
3635
- };
3636
- if (undefined && nuxtApp) {
3637
- try {
3638
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3639
- if (payload) {
3640
- payload[prefixedKey] = entry;
3641
- }
3642
- } catch (e) {
3643
- console.warn("[Katlux Cache] CMemoryCache error writing SSR payload for key: " + key, e);
3644
- }
3645
- }
3646
- CMemoryCache.storage.set(prefixedKey, entry);
3647
- }
3648
- async remove(key, nuxtApp) {
3649
- const prefixedKey = "cache:" + key;
3650
- CMemoryCache.storage.delete(prefixedKey);
3651
- if (undefined && nuxtApp) {
3652
- try {
3653
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3654
- if (payload && payload[prefixedKey]) {
3655
- delete payload[prefixedKey];
3656
- }
3657
- } catch (e) {
3658
- console.warn("[Katlux Cache] CMemoryCache error deleting key from SSR payload: " + key, e);
3659
- }
3660
- }
3661
- }
3662
- async removeByPrefix(prefix, nuxtApp) {
3663
- const fullPrefix = "cache:" + prefix;
3664
- const keysToDelete = [];
3665
- for (const key of CMemoryCache.storage.keys()) {
3666
- if (key.startsWith(fullPrefix)) {
3667
- keysToDelete.push(key);
3668
- }
3669
- }
3670
- for (const key of keysToDelete) {
3671
- CMemoryCache.storage.delete(key);
3672
- }
3673
- if (undefined && nuxtApp) {
3674
- try {
3675
- const payload = nuxtApp.payload?.data || nuxtApp.ssrContext?.payload?.data;
3676
- if (payload) {
3677
- for (const key in payload) {
3678
- if (key.startsWith(fullPrefix)) {
3679
- delete payload[key];
3680
- }
3681
- }
3682
- }
3683
- } catch (e) {
3684
- console.warn("[Katlux Cache] CMemoryCache error removing prefix from SSR payload: " + prefix, e);
3685
- }
3686
- }
3687
- }
3688
- async getRemainingTime(key, nuxtApp) {
3689
- const prefixedKey = "cache:" + key;
3690
- const entry = CMemoryCache.storage.get(prefixedKey);
3691
- if (!entry) return null;
3692
- return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
3693
- }
3694
- async cleanupExpired() {
3695
- const prefix = "cache:";
3696
- const now = Date.now();
3697
- const keysToDelete = [];
3698
- for (const [key, entry] of CMemoryCache.storage.entries()) {
3699
- if (key.startsWith(prefix)) {
3700
- if (now - entry.timestamp > entry.lifetime) {
3701
- keysToDelete.push(key);
3702
- }
3703
- }
3704
- }
3705
- for (const key of keysToDelete) {
3706
- CMemoryCache.storage.delete(key);
3707
- }
3708
- }
3709
- }
3710
-
3711
- const CMemoryCache$1 = {
3712
- __proto__: null,
3713
- CMemoryCache: CMemoryCache
3714
- };
3715
-
3716
- class CApplicationCache extends ACacheProvider {
3717
- static instance = null;
3718
- static _storage = null;
3719
- static get storage() {
3720
- if (!this._storage) {
3721
- this._storage = /* @__PURE__ */ new Map();
3722
- }
3723
- return this._storage;
3724
- }
3725
- static getInstance() {
3726
- if (!this.instance) {
3727
- this.instance = new CApplicationCache();
3728
- }
3729
- return this.instance;
3730
- }
3731
- static getSnapshot() {
3732
- return this.storage;
3733
- }
3734
- constructor() {
3735
- super();
3736
- }
3737
- async getKeyList(nuxtApp) {
3738
- const prefix = "cache:";
3739
- const storage = CApplicationCache.storage;
3740
- return Array.from(storage.keys()).filter((key) => key.startsWith(prefix)).map((key) => key.substring(prefix.length));
3741
- }
3742
- async get(key, nuxtApp) {
3743
- if (undefined) {
3744
- const prefixedKey = "cache:" + key;
3745
- const storage = CApplicationCache.storage;
3746
- const entry = storage.get(prefixedKey);
3747
- if (!entry) return null;
3748
- if (Date.now() - entry.timestamp > entry.lifetime) {
3749
- storage.delete(prefixedKey);
3750
- return null;
3751
- }
3752
- return entry.data;
3753
- }
3754
- return null;
3755
- }
3756
- async set(key, data, lifetime, nuxtApp) {
3757
- if (undefined) {
3758
- const prefixedKey = "cache:" + key;
3759
- const storage = CApplicationCache.storage;
3760
- storage.set(prefixedKey, {
3761
- data,
3762
- timestamp: Date.now(),
3763
- lifetime
3764
- });
3765
- }
3766
- }
3767
- async remove(key, nuxtApp) {
3768
- if (undefined) {
3769
- const prefixedKey = "cache:" + key;
3770
- CApplicationCache.storage.delete(prefixedKey);
3771
- }
3772
- }
3773
- async removeByPrefix(prefix, nuxtApp) {
3774
- if (undefined) {
3775
- const fullPrefix = "cache:" + prefix;
3776
- const storage = CApplicationCache.storage;
3777
- const keysToDelete = [];
3778
- for (const key of storage.keys()) {
3779
- if (key.startsWith(fullPrefix)) {
3780
- keysToDelete.push(key);
3781
- }
3782
- }
3783
- for (const key of keysToDelete) {
3784
- storage.delete(key);
3785
- }
3786
- }
3787
- }
3788
- async getRemainingTime(key, nuxtApp) {
3789
- if (undefined) {
3790
- const prefixedKey = "cache:" + key;
3791
- const storage = CApplicationCache.storage;
3792
- const entry = storage.get(prefixedKey);
3793
- if (!entry) return null;
3794
- return Math.max(0, entry.timestamp + entry.lifetime - Date.now());
3795
- }
3796
- return null;
3797
- }
3798
- async cleanupExpired() {
3799
- if (undefined) {
3800
- const prefix = "cache:";
3801
- const now = Date.now();
3802
- const storage = CApplicationCache.storage;
3803
- const keysToDelete = [];
3804
- for (const [key, entry] of storage.entries()) {
3805
- if (key.startsWith(prefix)) {
3806
- if (now - entry.timestamp > entry.lifetime) {
3807
- keysToDelete.push(key);
3808
- }
3809
- }
3810
- }
3811
- for (const key of keysToDelete) {
3812
- storage.delete(key);
3813
- }
3814
- }
3815
- }
3816
- }
3817
-
3818
- const CApplicationCache$1 = {
3819
- __proto__: null,
3820
- CApplicationCache: CApplicationCache
3821
- };
3822
-
3823
- exports.DefaultHydrationAdapter = index.DefaultHydrationAdapter;
3824
- exports.NuxtHydrationAdapter = index.NuxtHydrationAdapter;
3825
- exports.clearSSRData = index.clearSSRData;
3826
- exports.fetchWithSSR = index.fetchWithSSR;
3827
- exports.getAppRoute = index.getAppRoute;
3828
- exports.getAppRouter = index.getAppRouter;
3829
- exports.getHydrationAdapter = index.getHydrationAdapter;
3830
- exports.getPlatformApp = index.getPlatformApp;
3831
- exports.getSSRData = index.getSSRData;
3832
- exports.getSSRPayload = index.getSSRPayload;
3833
- exports.onPlatformReady = index.onPlatformReady;
3834
- exports.setHydrationAdapter = index.setHydrationAdapter;
3835
4638
  exports.AAPIDataProvider = AAPIDataProvider;
3836
4639
  exports.ADataProvider = ADataProvider;
3837
4640
  exports.CAPIFlatClientDataProvider = CAPIFlatClientDataProvider;
@@ -3839,16 +4642,18 @@ exports.CAPIFlatServerDataProvider = CAPIFlatServerDataProvider;
3839
4642
  exports.CAPITreeClientDataProvider = CAPITreeClientDataProvider;
3840
4643
  exports.CAPITreeServerDataProvider = CAPITreeServerDataProvider;
3841
4644
  exports.CApplicationCache = CApplicationCache;
4645
+ exports.CBrowserSessionCache = CBrowserSessionCache;
3842
4646
  exports.CCookieCache = CCookieCache;
3843
4647
  exports.CFlatClientDataProvider = CFlatClientDataProvider;
3844
4648
  exports.CFlatServerDataProvider = CFlatServerDataProvider;
3845
4649
  exports.CIndexedDBCache = CIndexedDBCache;
3846
4650
  exports.CLocalStorageCache = CLocalStorageCache;
3847
4651
  exports.CMemoryCache = CMemoryCache;
3848
- exports.CSessionCache = CSessionCache;
4652
+ exports.CServerSessionCache = CServerSessionCache;
3849
4653
  exports.CTreeClientDataProvider = CTreeClientDataProvider;
3850
4654
  exports.CTreeServerDataProvider = CTreeServerDataProvider;
3851
4655
  exports.CacheProviderFactory = CacheProviderFactory;
4656
+ exports.DefaultHydrationAdapter = DefaultHydrationAdapter;
3852
4657
  exports.ECacheStrategy = ECacheStrategy;
3853
4658
  exports.EDataFilterOperator = EDataFilterOperator;
3854
4659
  exports.EQueueStorage = EQueueStorage;
@@ -3857,7 +4662,9 @@ exports.QueueStorageFactory = QueueStorageFactory;
3857
4662
  exports.RequestProvider = RequestProvider;
3858
4663
  exports.RequestProviderRegistry = RequestProviderRegistry;
3859
4664
  exports.RequestQueue = RequestQueue;
4665
+ exports.SENSITIVE_HEADER_KEYS = SENSITIVE_HEADER_KEYS;
3860
4666
  exports.applyOperator = applyOperator;
4667
+ exports.clearSSRData = clearSSRData;
3861
4668
  exports.compareAnd = compareAnd;
3862
4669
  exports.compareEqual = compareEqual;
3863
4670
  exports.compareIn = compareIn;
@@ -3865,8 +4672,17 @@ exports.compareOr = compareOr;
3865
4672
  exports.compareValues = compareValues;
3866
4673
  exports.debounce = debounce;
3867
4674
  exports.evaluateFilter = evaluateFilter;
4675
+ exports.fetchWithSSR = fetchWithSSR;
3868
4676
  exports.filterData = filterData;
3869
4677
  exports.filterTreeData = filterTreeData;
4678
+ exports.getAppRoute = getAppRoute;
4679
+ exports.getAppRouter = getAppRouter;
4680
+ exports.getHydrationAdapter = getHydrationAdapter;
4681
+ exports.getPlatformApp = getPlatformApp;
4682
+ exports.getSSRData = getSSRData;
4683
+ exports.getSSRPayload = getSSRPayload;
4684
+ exports.onPlatformReady = onPlatformReady;
4685
+ exports.setHydrationAdapter = setHydrationAdapter;
3870
4686
  exports.sortData = sortData;
3871
4687
  exports.useDebounce = useDebounce;
3872
4688
  exports.useFilterLogic = useFilterLogic;