@lionrapid/core 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/browser/auto-init.d.ts +17 -3
  2. package/dist/browser/auto-init.d.ts.map +1 -1
  3. package/dist/browser/auto-init.js +57 -30
  4. package/dist/browser/auto-init.js.map +1 -1
  5. package/dist/browser/lionrapid.auto.dev.js +285 -27
  6. package/dist/browser/lionrapid.auto.dev.js.map +2 -2
  7. package/dist/browser/lionrapid.auto.js +285 -27
  8. package/dist/browser/lionrapid.auto.js.map +2 -2
  9. package/dist/browser/lionrapid.auto.min.js +4 -4
  10. package/dist/browser/lionrapid.auto.min.js.map +3 -3
  11. package/dist/browser/lionrapid.esm.js +244 -2
  12. package/dist/browser/lionrapid.esm.js.map +2 -2
  13. package/dist/browser/lionrapid.esm.min.js +3 -3
  14. package/dist/browser/lionrapid.esm.min.js.map +3 -3
  15. package/dist/browser/lionrapid.iife.dev.js +244 -2
  16. package/dist/browser/lionrapid.iife.dev.js.map +2 -2
  17. package/dist/browser/lionrapid.iife.js +244 -2
  18. package/dist/browser/lionrapid.iife.js.map +2 -2
  19. package/dist/browser/lionrapid.iife.min.js +3 -3
  20. package/dist/browser/lionrapid.iife.min.js.map +3 -3
  21. package/dist/browser/lionrapid.umd.js +244 -2
  22. package/dist/browser/lionrapid.umd.js.map +2 -2
  23. package/dist/browser/lionrapid.umd.min.js +3 -3
  24. package/dist/browser/lionrapid.umd.min.js.map +3 -3
  25. package/dist/browser/storage/cache-storage-repository.d.ts +65 -0
  26. package/dist/browser/storage/cache-storage-repository.d.ts.map +1 -1
  27. package/dist/browser/storage/cache-storage-repository.js +77 -7
  28. package/dist/browser/storage/cache-storage-repository.js.map +1 -1
  29. package/dist/browser/storage/localstorage-repository.d.ts +62 -0
  30. package/dist/browser/storage/localstorage-repository.d.ts.map +1 -1
  31. package/dist/browser/storage/localstorage-repository.js +71 -4
  32. package/dist/browser/storage/localstorage-repository.js.map +1 -1
  33. package/dist/config/repository.config.d.ts +17 -0
  34. package/dist/config/repository.config.d.ts.map +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/lionRapid.d.ts +1 -0
  39. package/dist/lionRapid.d.ts.map +1 -1
  40. package/dist/lionRapid.js +14 -0
  41. package/dist/lionRapid.js.map +1 -1
  42. package/dist/repositories/network-repository.d.ts +42 -1
  43. package/dist/repositories/network-repository.d.ts.map +1 -1
  44. package/dist/repositories/network-repository.js +149 -1
  45. package/dist/repositories/network-repository.js.map +1 -1
  46. package/package.json +1 -1
@@ -2899,6 +2899,7 @@ var LionRapid = (() => {
2899
2899
  // 🔥 EMBEDDED: Core integration maps
2900
2900
  __publicField(this, "formatters", /* @__PURE__ */ new Map());
2901
2901
  __publicField(this, "processors", /* @__PURE__ */ new Map());
2902
+ __publicField(this, "warnedNoInterpolate", false);
2902
2903
  // 📡 EVENT-DRIVEN: Just track for cleanup
2903
2904
  __publicField(this, "eventPlugins", /* @__PURE__ */ new Set());
2904
2905
  // 📦 CONTENT: Parser and serializer for ContentUnit processing
@@ -3191,6 +3192,11 @@ var LionRapid = (() => {
3191
3192
  resolvedLocale,
3192
3193
  resolvedKey
3193
3194
  );
3195
+ } else if (!this.warnedNoInterpolate && params && Object.keys(params).length > 0 && processedValue.includes("{")) {
3196
+ this.warnedNoInterpolate = true;
3197
+ console.warn(
3198
+ "[LionRapid] Translation params were passed but no interpolate formatter is registered \u2014 {placeholders} render literally. Install @lionrapid/formatters and add .use(coreFormattersPlugin) to the builder."
3199
+ );
3194
3200
  }
3195
3201
  if (this.processors.size > 0) {
3196
3202
  for (const [name, processor] of this.processors.entries()) {
@@ -3971,6 +3977,31 @@ var LionRapid = (() => {
3971
3977
  * and payload can never desync because they live and die together.
3972
3978
  */
3973
3979
  __publicField(this, "namespaceSnapshots", /* @__PURE__ */ new Map());
3980
+ /**
3981
+ * Miss-path flood protection (READINESS before-scale #1: one cold locale
3982
+ * switch measured ~380 requests in 10 s — every t() miss refired a key GET
3983
+ * and a namespace GET on every re-render, forever on animated pages).
3984
+ */
3985
+ /** GETs currently on the wire, keyed by `url|if-none-match` — identical
3986
+ * concurrent requests share one fetch; each awaiter gets a clone. The
3987
+ * If-None-Match value is part of the key so the 304-without-snapshot
3988
+ * unconditional refetch never coalesces onto a conditional flight. */
3989
+ __publicField(this, "inflightGets", /* @__PURE__ */ new Map());
3990
+ /** URL → 404/423 seen recently: repeats are answered locally (same typed
3991
+ * error, no network) until `until`. 423 honors the server's Retry-After.
3992
+ * Cleared entirely by any successful write — discovery sync keeps its
3993
+ * miss → batch → served-back round-trip. */
3994
+ __publicField(this, "negativeCache", /* @__PURE__ */ new Map());
3995
+ /** One-way latch: a 401 anywhere (or a 403 on a READ) means the key is
3996
+ * wrong or unauthorized for this project, and retrying cannot heal it —
3997
+ * after the first one nothing touches the network again for this
3998
+ * instance (a page reload starts fresh). Holds the status that tripped
3999
+ * it so short-circuits answer honestly. */
4000
+ __publicField(this, "authFailedStatus", null);
4001
+ /** Write-only latch (auth-byok Phase 18): a 403 (scope) or 429 (quota) on
4002
+ * a WRITE degrades this instance to read-only — writes stop, silently
4003
+ * and without retries, while reads keep serving the page. */
4004
+ __publicField(this, "writesFailedStatus", null);
3974
4005
  /**
3975
4006
  * Default endpoint templates with placeholder support
3976
4007
  * Placeholders: :key, :locale, :namespace
@@ -3978,6 +4009,7 @@ var LionRapid = (() => {
3978
4009
  __publicField(this, "DEFAULT_ENDPOINTS", {
3979
4010
  getTranslation: "/api/integrations/translations/:key",
3980
4011
  getNamespace: "/api/integrations/translations/:locale/:namespace",
4012
+ getProjectConfig: "/api/integrations/project-config",
3981
4013
  setTranslation: "/api/integrations/sync/:key",
3982
4014
  setNamespace: "/api/integrations/sync/:locale/:namespace",
3983
4015
  setBatch: "/api/integrations/sync/batch",
@@ -4089,6 +4121,40 @@ var LionRapid = (() => {
4089
4121
  this.handleCaughtError(error);
4090
4122
  }
4091
4123
  }
4124
+ /**
4125
+ * Project-level config for this key — the dashboard's language list,
4126
+ * served under the same trust model as translation reads (docs/20,
4127
+ * companion track). Returns null when the server doesn't expose the
4128
+ * endpoint (404 — older server, feature not deployed) or the payload is
4129
+ * unusable: absence means "keep your local fallback", never an error.
4130
+ */
4131
+ async getProjectConfig() {
4132
+ if (!this.config?.options?.baseUrl) {
4133
+ throw new NetworkError("API base URL is not set");
4134
+ }
4135
+ const url = this.buildUrl("getProjectConfig", {});
4136
+ logger.debug(`API GET ProjectConfig: ${url}`);
4137
+ try {
4138
+ const response = await this.makeRequest(url, "GET");
4139
+ if (response.status === 404) {
4140
+ return null;
4141
+ }
4142
+ if (!response.ok) {
4143
+ this.handleHttpError(response, "project-config");
4144
+ }
4145
+ const data = await response.json();
4146
+ if (!data || typeof data.defaultLocale !== "string" || !Array.isArray(data.languages)) {
4147
+ logger.warn("project-config payload unusable \u2014 keeping local fallback");
4148
+ return null;
4149
+ }
4150
+ return {
4151
+ defaultLocale: data.defaultLocale,
4152
+ languages: data.languages.map(String)
4153
+ };
4154
+ } catch (error) {
4155
+ this.handleCaughtError(error);
4156
+ }
4157
+ }
4092
4158
  /**
4093
4159
  * Shared namespace fetch with the canonical 304 contract:
4094
4160
  * - If-None-Match is sent ONLY when a snapshot (version + payload) is in hand.
@@ -4413,7 +4479,87 @@ var LionRapid = (() => {
4413
4479
  /**
4414
4480
  * Make HTTP request with timeout and headers
4415
4481
  */
4416
- async makeRequest(url, method, body, extraHeaders) {
4482
+ makeRequest(url, method, body, extraHeaders) {
4483
+ if (this.authFailedStatus !== null) {
4484
+ return Promise.resolve(
4485
+ new Response(null, {
4486
+ status: this.authFailedStatus,
4487
+ statusText: `auth latched off after ${this.authFailedStatus}`
4488
+ })
4489
+ );
4490
+ }
4491
+ if (method !== "GET") {
4492
+ if (this.writesFailedStatus !== null) {
4493
+ return Promise.resolve(
4494
+ new Response(null, {
4495
+ status: this.writesFailedStatus,
4496
+ statusText: `writes latched off after ${this.writesFailedStatus}`
4497
+ })
4498
+ );
4499
+ }
4500
+ return this.doFetch(url, method, body, extraHeaders).then(
4501
+ (resp) => this.recordOutcome(url, method, resp)
4502
+ );
4503
+ }
4504
+ const negative = this.negativeCache.get(url);
4505
+ if (negative) {
4506
+ if (Date.now() < negative.until) {
4507
+ logger.debug(`Negative-cache hit (${negative.status}): ${url}`);
4508
+ const headers = negative.status === 423 ? { "Retry-After": String(Math.ceil((negative.until - Date.now()) / 1e3)) } : void 0;
4509
+ return Promise.resolve(
4510
+ new Response(null, { status: negative.status, statusText: "negative cache", headers })
4511
+ );
4512
+ }
4513
+ this.negativeCache.delete(url);
4514
+ }
4515
+ const flightKey = `${url}|${extraHeaders?.["If-None-Match"] ?? ""}`;
4516
+ const existing = this.inflightGets.get(flightKey);
4517
+ if (existing) {
4518
+ return existing.then((resp) => this.cloneResponse(resp));
4519
+ }
4520
+ const flight = this.doFetch(url, method, body, extraHeaders).then((resp) => this.recordOutcome(url, method, resp)).finally(() => this.inflightGets.delete(flightKey));
4521
+ this.inflightGets.set(flightKey, flight);
4522
+ return flight.then((resp) => this.cloneResponse(resp));
4523
+ }
4524
+ /** Bookkeeping on every real (non-synthesized) response — runs once per
4525
+ * physical fetch, never once per coalesced awaiter. */
4526
+ recordOutcome(url, method, response) {
4527
+ const status = response.status;
4528
+ if (status === 401 || status === 403 && method === "GET") {
4529
+ if (this.authFailedStatus === null) {
4530
+ this.authFailedStatus = status;
4531
+ console.warn(
4532
+ `[LionRapid] API key rejected (${status}) \u2014 network translations are disabled for this session. Fix the key and reload; retrying cannot heal an auth failure.`
4533
+ );
4534
+ }
4535
+ return response;
4536
+ }
4537
+ if ((status === 403 || status === 429) && method !== "GET") {
4538
+ if (this.writesFailedStatus === null) {
4539
+ this.writesFailedStatus = status;
4540
+ logger.warn(
4541
+ `Write path disabled after ${status} (scope/quota) \u2014 running read-only`
4542
+ );
4543
+ }
4544
+ return response;
4545
+ }
4546
+ if (method === "GET" && (status === 404 || status === 423)) {
4547
+ const retryAfterSec = status === 423 ? Number(response.headers?.get?.("Retry-After")) : NaN;
4548
+ const ttl = Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? retryAfterSec * 1e3 : this.config.options?.negativeCacheTtlMs ?? _NetworkRepository.DEFAULT_NEGATIVE_TTL_MS;
4549
+ this.negativeCache.set(url, { status, until: Date.now() + ttl });
4550
+ } else if (method !== "GET" && response.ok) {
4551
+ this.negativeCache.clear();
4552
+ } else if (method === "GET" && response.ok) {
4553
+ this.negativeCache.delete(url);
4554
+ }
4555
+ return response;
4556
+ }
4557
+ /** Test doubles (and exotic runtimes) hand us plain objects — only real
4558
+ * Responses need cloning so each coalesced awaiter can read the body. */
4559
+ cloneResponse(response) {
4560
+ return typeof response.clone === "function" ? response.clone() : response;
4561
+ }
4562
+ async doFetch(url, method, body, extraHeaders) {
4417
4563
  const controller = new AbortController();
4418
4564
  const timeout = this.config.options?.timeout ?? 1e4;
4419
4565
  const timeoutId = setTimeout(
@@ -4446,6 +4592,7 @@ var LionRapid = (() => {
4446
4592
  /** Legacy bare-version prefix — a version WITHOUT its payload is exactly the
4447
4593
  * desync the snapshot store exists to prevent; entries are deleted on sight. */
4448
4594
  __publicField(_NetworkRepository, "LEGACY_VERSION_PREFIX", "lionrapid:v:");
4595
+ __publicField(_NetworkRepository, "DEFAULT_NEGATIVE_TTL_MS", 6e4);
4449
4596
  var NetworkRepository = _NetworkRepository;
4450
4597
 
4451
4598
  // src/content/validator/ContentValidator.ts
@@ -5044,9 +5191,11 @@ var LionRapid = (() => {
5044
5191
  this.config = {
5045
5192
  enabled: config.enabled ?? true,
5046
5193
  priority: config.priority ?? 0,
5194
+ // Use build sequence by default
5047
5195
  options: {
5048
5196
  prefix: config.options?.prefix ?? STORAGE_PREFIX,
5049
5197
  ttl: config.options?.ttl ?? 24 * 60 * 60 * 1e3,
5198
+ // 24 hours default
5050
5199
  maxSize: config.options?.maxSize ?? 500,
5051
5200
  ...config.options
5052
5201
  }
@@ -5059,6 +5208,10 @@ var LionRapid = (() => {
5059
5208
  this.migrateIfNeeded();
5060
5209
  }
5061
5210
  }
5211
+ /**
5212
+ * Check if localStorage is available
5213
+ * Returns false in SSR, private browsing, or when quota is 0
5214
+ */
5062
5215
  checkAvailability() {
5063
5216
  if (typeof window === "undefined") {
5064
5217
  return false;
@@ -5072,6 +5225,9 @@ var LionRapid = (() => {
5072
5225
  return false;
5073
5226
  }
5074
5227
  }
5228
+ /**
5229
+ * Handle version migrations - clear cache when version changes
5230
+ */
5075
5231
  migrateIfNeeded() {
5076
5232
  try {
5077
5233
  const storedVersion = window.localStorage.getItem(VERSION_KEY);
@@ -5082,6 +5238,10 @@ var LionRapid = (() => {
5082
5238
  } catch {
5083
5239
  }
5084
5240
  }
5241
+ /**
5242
+ * Get a translation value by key
5243
+ * Returns null if not found or expired
5244
+ */
5085
5245
  get(key) {
5086
5246
  if (!this.available) return null;
5087
5247
  try {
@@ -5098,6 +5258,10 @@ var LionRapid = (() => {
5098
5258
  return null;
5099
5259
  }
5100
5260
  }
5261
+ /**
5262
+ * Set a translation value
5263
+ * Automatically handles quota exceeded by evicting oldest entries
5264
+ */
5101
5265
  set(key, value) {
5102
5266
  if (!this.available) return;
5103
5267
  const fullKey = this.prefix + key;
@@ -5122,6 +5286,9 @@ var LionRapid = (() => {
5122
5286
  }
5123
5287
  }
5124
5288
  }
5289
+ /**
5290
+ * Remove a translation by key
5291
+ */
5125
5292
  remove(key) {
5126
5293
  if (!this.available) return;
5127
5294
  try {
@@ -5129,6 +5296,10 @@ var LionRapid = (() => {
5129
5296
  } catch {
5130
5297
  }
5131
5298
  }
5299
+ /**
5300
+ * Clear all LionRapid entries from localStorage
5301
+ * Preserves entries from other applications
5302
+ */
5132
5303
  clear() {
5133
5304
  if (!this.available) return;
5134
5305
  try {
@@ -5143,6 +5314,9 @@ var LionRapid = (() => {
5143
5314
  } catch {
5144
5315
  }
5145
5316
  }
5317
+ /**
5318
+ * Clear all entries for a specific namespace
5319
+ */
5146
5320
  clearNamespace(locale, namespace) {
5147
5321
  if (!this.available) return;
5148
5322
  const namespaceCacheKey = `@${locale}:${namespace}`;
@@ -5161,6 +5335,9 @@ var LionRapid = (() => {
5161
5335
  } catch {
5162
5336
  }
5163
5337
  }
5338
+ /**
5339
+ * Get namespace translations
5340
+ */
5164
5341
  getNamespace(locale, namespace) {
5165
5342
  const namespaceCacheKey = `@${locale}:${namespace}`;
5166
5343
  const value = this.get(namespaceCacheKey);
@@ -5172,10 +5349,16 @@ var LionRapid = (() => {
5172
5349
  return null;
5173
5350
  }
5174
5351
  }
5352
+ /**
5353
+ * Set namespace translations
5354
+ */
5175
5355
  setNamespace(locale, namespace, translations) {
5176
5356
  const namespaceCacheKey = `@${locale}:${namespace}`;
5177
5357
  this.set(namespaceCacheKey, JSON.stringify(translations));
5178
5358
  }
5359
+ /**
5360
+ * Get all cache entries for debugging
5361
+ */
5179
5362
  getEntries() {
5180
5363
  const entries = {};
5181
5364
  if (!this.available) return entries;
@@ -5195,12 +5378,21 @@ var LionRapid = (() => {
5195
5378
  }
5196
5379
  return entries;
5197
5380
  }
5381
+ /**
5382
+ * Get repository configuration
5383
+ */
5198
5384
  getConfig() {
5199
5385
  return this.config;
5200
5386
  }
5387
+ /**
5388
+ * Check if localStorage is available
5389
+ */
5201
5390
  isAvailable() {
5202
5391
  return this.available;
5203
5392
  }
5393
+ /**
5394
+ * Get the number of entries in the cache
5395
+ */
5204
5396
  getEntryCount() {
5205
5397
  if (!this.available) return 0;
5206
5398
  let count = 0;
@@ -5215,12 +5407,18 @@ var LionRapid = (() => {
5215
5407
  }
5216
5408
  return count;
5217
5409
  }
5410
+ /**
5411
+ * Check if error is a quota exceeded error
5412
+ */
5218
5413
  isQuotaError(error) {
5219
5414
  if (error instanceof DOMException) {
5220
5415
  return error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED";
5221
5416
  }
5222
5417
  return false;
5223
5418
  }
5419
+ /**
5420
+ * Evict oldest 25% of entries when quota is exceeded
5421
+ */
5224
5422
  evictOldest() {
5225
5423
  if (!this.available) return;
5226
5424
  try {
@@ -5248,6 +5446,9 @@ var LionRapid = (() => {
5248
5446
  } catch {
5249
5447
  }
5250
5448
  }
5449
+ /**
5450
+ * Get cache statistics
5451
+ */
5251
5452
  getCacheStats() {
5252
5453
  const size = this.getEntryCount();
5253
5454
  const usage = this.maxSize > 0 ? `${Math.round(size / this.maxSize * 100)}%` : "0%";
@@ -5261,7 +5462,7 @@ var LionRapid = (() => {
5261
5462
 
5262
5463
  // src/browser/storage/cache-storage-repository.ts
5263
5464
  var CACHE_NAME = "lionrapid-v1";
5264
- var CACHE_PREFIX = "lionrapid:";
5465
+ var CACHE_PREFIX = "https://cache.lionrapid.internal/";
5265
5466
  var CacheStorageRepository = class {
5266
5467
  constructor(config = {}) {
5267
5468
  __publicField(this, "name", "CacheStorageRepository");
@@ -5276,6 +5477,7 @@ var LionRapid = (() => {
5276
5477
  options: {
5277
5478
  cacheName: config.options?.cacheName ?? CACHE_NAME,
5278
5479
  ttl: config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3,
5480
+ // 7 days default
5279
5481
  ...config.options
5280
5482
  }
5281
5483
  };
@@ -5283,9 +5485,17 @@ var LionRapid = (() => {
5283
5485
  this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
5284
5486
  this.available = this.checkAvailability();
5285
5487
  }
5488
+ /**
5489
+ * Check if Cache API is available
5490
+ * Returns false in SSR, old browsers, or insecure contexts
5491
+ */
5286
5492
  checkAvailability() {
5287
5493
  return typeof caches !== "undefined";
5288
5494
  }
5495
+ /**
5496
+ * Get a translation value by key
5497
+ * @throws {TranslationNotFoundError} When translation doesn't exist or is expired
5498
+ */
5289
5499
  async get(key) {
5290
5500
  if (!this.available) {
5291
5501
  throw new TranslationNotFoundError(key);
@@ -5309,6 +5519,9 @@ var LionRapid = (() => {
5309
5519
  throw new TranslationNotFoundError(key);
5310
5520
  }
5311
5521
  }
5522
+ /**
5523
+ * Set a translation value
5524
+ */
5312
5525
  async set(key, value) {
5313
5526
  if (!this.available) return;
5314
5527
  try {
@@ -5327,6 +5540,9 @@ var LionRapid = (() => {
5327
5540
  } catch {
5328
5541
  }
5329
5542
  }
5543
+ /**
5544
+ * Remove a translation by key
5545
+ */
5330
5546
  async remove(key) {
5331
5547
  if (!this.available) return;
5332
5548
  try {
@@ -5335,6 +5551,9 @@ var LionRapid = (() => {
5335
5551
  } catch {
5336
5552
  }
5337
5553
  }
5554
+ /**
5555
+ * Clear all LionRapid entries from the cache
5556
+ */
5338
5557
  async clear() {
5339
5558
  if (!this.available) return;
5340
5559
  try {
@@ -5346,6 +5565,9 @@ var LionRapid = (() => {
5346
5565
  } catch {
5347
5566
  }
5348
5567
  }
5568
+ /**
5569
+ * Clear all entries for a specific namespace
5570
+ */
5349
5571
  async clearNamespace(locale, namespace) {
5350
5572
  if (!this.available) return;
5351
5573
  const namespaceCacheKey = `@${locale}:${namespace}`;
@@ -5363,6 +5585,10 @@ var LionRapid = (() => {
5363
5585
  } catch {
5364
5586
  }
5365
5587
  }
5588
+ /**
5589
+ * Get namespace translations
5590
+ * @throws {TranslationNotFoundError} When namespace doesn't exist
5591
+ */
5366
5592
  async getNamespace(locale, namespace) {
5367
5593
  const namespaceCacheKey = `@${locale}:${namespace}`;
5368
5594
  const value = await this.get(namespaceCacheKey);
@@ -5373,16 +5599,29 @@ var LionRapid = (() => {
5373
5599
  throw new TranslationNotFoundError(namespaceCacheKey);
5374
5600
  }
5375
5601
  }
5602
+ /**
5603
+ * Set namespace translations
5604
+ */
5376
5605
  async setNamespace(locale, namespace, translations) {
5377
5606
  const namespaceCacheKey = `@${locale}:${namespace}`;
5378
5607
  await this.set(namespaceCacheKey, JSON.stringify(translations));
5379
5608
  }
5609
+ /**
5610
+ * Get repository configuration
5611
+ */
5380
5612
  getConfig() {
5381
5613
  return this.config;
5382
5614
  }
5615
+ /**
5616
+ * Check if Cache API is available
5617
+ */
5383
5618
  isAvailable() {
5384
5619
  return this.available;
5385
5620
  }
5621
+ /**
5622
+ * Get all cached entries (for debugging)
5623
+ * Returns an object mapping keys to values
5624
+ */
5386
5625
  async getEntries() {
5387
5626
  const entries = {};
5388
5627
  if (!this.available) return entries;
@@ -5405,6 +5644,9 @@ var LionRapid = (() => {
5405
5644
  }
5406
5645
  return entries;
5407
5646
  }
5647
+ /**
5648
+ * Get cache statistics
5649
+ */
5408
5650
  async getCacheStats() {
5409
5651
  if (!this.available) {
5410
5652
  return { size: 0, cacheName: this.cacheName };