@lionrapid/core 0.6.1 → 0.6.3
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/browser/auto-init.d.ts +8 -3
- package/dist/browser/auto-init.d.ts.map +1 -1
- package/dist/browser/auto-init.js +34 -26
- package/dist/browser/auto-init.js.map +1 -1
- package/dist/browser/lionrapid.auto.dev.js +267 -24
- package/dist/browser/lionrapid.auto.dev.js.map +2 -2
- package/dist/browser/lionrapid.auto.js +267 -24
- package/dist/browser/lionrapid.auto.js.map +2 -2
- package/dist/browser/lionrapid.auto.min.js +4 -4
- package/dist/browser/lionrapid.auto.min.js.map +3 -3
- package/dist/browser/lionrapid.esm.js +241 -2
- package/dist/browser/lionrapid.esm.js.map +2 -2
- package/dist/browser/lionrapid.esm.min.js +3 -3
- package/dist/browser/lionrapid.esm.min.js.map +3 -3
- package/dist/browser/lionrapid.iife.dev.js +241 -2
- package/dist/browser/lionrapid.iife.dev.js.map +2 -2
- package/dist/browser/lionrapid.iife.js +241 -2
- package/dist/browser/lionrapid.iife.js.map +2 -2
- package/dist/browser/lionrapid.iife.min.js +3 -3
- package/dist/browser/lionrapid.iife.min.js.map +3 -3
- package/dist/browser/lionrapid.umd.js +241 -2
- package/dist/browser/lionrapid.umd.js.map +2 -2
- package/dist/browser/lionrapid.umd.min.js +3 -3
- package/dist/browser/lionrapid.umd.min.js.map +3 -3
- package/dist/browser/storage/cache-storage-repository.d.ts +65 -0
- package/dist/browser/storage/cache-storage-repository.d.ts.map +1 -1
- package/dist/browser/storage/cache-storage-repository.js +77 -7
- package/dist/browser/storage/cache-storage-repository.js.map +1 -1
- package/dist/browser/storage/localstorage-repository.d.ts +62 -0
- package/dist/browser/storage/localstorage-repository.d.ts.map +1 -1
- package/dist/browser/storage/localstorage-repository.js +71 -4
- package/dist/browser/storage/localstorage-repository.js.map +1 -1
- package/dist/config/repository.config.d.ts +17 -0
- package/dist/config/repository.config.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/repositories/network-repository.d.ts +42 -1
- package/dist/repositories/network-repository.d.ts.map +1 -1
- package/dist/repositories/network-repository.js +161 -1
- package/dist/repositories/network-repository.js.map +1 -1
- package/package.json +1 -1
|
@@ -3962,6 +3962,8 @@ var LionRapid = (() => {
|
|
|
3962
3962
|
};
|
|
3963
3963
|
|
|
3964
3964
|
// src/repositories/network-repository.ts
|
|
3965
|
+
var SURFACE_HEADER = "X-LR-Surface";
|
|
3966
|
+
var SURFACE_TAG = "snippet";
|
|
3965
3967
|
var _NetworkRepository = class _NetworkRepository {
|
|
3966
3968
|
constructor(config = {}) {
|
|
3967
3969
|
__publicField(this, "name", "NetworkRepository");
|
|
@@ -3977,6 +3979,31 @@ var LionRapid = (() => {
|
|
|
3977
3979
|
* and payload can never desync because they live and die together.
|
|
3978
3980
|
*/
|
|
3979
3981
|
__publicField(this, "namespaceSnapshots", /* @__PURE__ */ new Map());
|
|
3982
|
+
/**
|
|
3983
|
+
* Miss-path flood protection (READINESS before-scale #1: one cold locale
|
|
3984
|
+
* switch measured ~380 requests in 10 s — every t() miss refired a key GET
|
|
3985
|
+
* and a namespace GET on every re-render, forever on animated pages).
|
|
3986
|
+
*/
|
|
3987
|
+
/** GETs currently on the wire, keyed by `url|if-none-match` — identical
|
|
3988
|
+
* concurrent requests share one fetch; each awaiter gets a clone. The
|
|
3989
|
+
* If-None-Match value is part of the key so the 304-without-snapshot
|
|
3990
|
+
* unconditional refetch never coalesces onto a conditional flight. */
|
|
3991
|
+
__publicField(this, "inflightGets", /* @__PURE__ */ new Map());
|
|
3992
|
+
/** URL → 404/423 seen recently: repeats are answered locally (same typed
|
|
3993
|
+
* error, no network) until `until`. 423 honors the server's Retry-After.
|
|
3994
|
+
* Cleared entirely by any successful write — discovery sync keeps its
|
|
3995
|
+
* miss → batch → served-back round-trip. */
|
|
3996
|
+
__publicField(this, "negativeCache", /* @__PURE__ */ new Map());
|
|
3997
|
+
/** One-way latch: a 401 anywhere (or a 403 on a READ) means the key is
|
|
3998
|
+
* wrong or unauthorized for this project, and retrying cannot heal it —
|
|
3999
|
+
* after the first one nothing touches the network again for this
|
|
4000
|
+
* instance (a page reload starts fresh). Holds the status that tripped
|
|
4001
|
+
* it so short-circuits answer honestly. */
|
|
4002
|
+
__publicField(this, "authFailedStatus", null);
|
|
4003
|
+
/** Write-only latch (auth-byok Phase 18): a 403 (scope) or 429 (quota) on
|
|
4004
|
+
* a WRITE degrades this instance to read-only — writes stop, silently
|
|
4005
|
+
* and without retries, while reads keep serving the page. */
|
|
4006
|
+
__publicField(this, "writesFailedStatus", null);
|
|
3980
4007
|
/**
|
|
3981
4008
|
* Default endpoint templates with placeholder support
|
|
3982
4009
|
* Placeholders: :key, :locale, :namespace
|
|
@@ -3984,6 +4011,7 @@ var LionRapid = (() => {
|
|
|
3984
4011
|
__publicField(this, "DEFAULT_ENDPOINTS", {
|
|
3985
4012
|
getTranslation: "/api/integrations/translations/:key",
|
|
3986
4013
|
getNamespace: "/api/integrations/translations/:locale/:namespace",
|
|
4014
|
+
getProjectConfig: "/api/integrations/project-config",
|
|
3987
4015
|
setTranslation: "/api/integrations/sync/:key",
|
|
3988
4016
|
setNamespace: "/api/integrations/sync/:locale/:namespace",
|
|
3989
4017
|
setBatch: "/api/integrations/sync/batch",
|
|
@@ -4095,6 +4123,40 @@ var LionRapid = (() => {
|
|
|
4095
4123
|
this.handleCaughtError(error);
|
|
4096
4124
|
}
|
|
4097
4125
|
}
|
|
4126
|
+
/**
|
|
4127
|
+
* Project-level config for this key — the dashboard's language list,
|
|
4128
|
+
* served under the same trust model as translation reads (docs/20,
|
|
4129
|
+
* companion track). Returns null when the server doesn't expose the
|
|
4130
|
+
* endpoint (404 — older server, feature not deployed) or the payload is
|
|
4131
|
+
* unusable: absence means "keep your local fallback", never an error.
|
|
4132
|
+
*/
|
|
4133
|
+
async getProjectConfig() {
|
|
4134
|
+
if (!this.config?.options?.baseUrl) {
|
|
4135
|
+
throw new NetworkError("API base URL is not set");
|
|
4136
|
+
}
|
|
4137
|
+
const url = this.buildUrl("getProjectConfig", {});
|
|
4138
|
+
logger.debug(`API GET ProjectConfig: ${url}`);
|
|
4139
|
+
try {
|
|
4140
|
+
const response = await this.makeRequest(url, "GET");
|
|
4141
|
+
if (response.status === 404) {
|
|
4142
|
+
return null;
|
|
4143
|
+
}
|
|
4144
|
+
if (!response.ok) {
|
|
4145
|
+
this.handleHttpError(response, "project-config");
|
|
4146
|
+
}
|
|
4147
|
+
const data = await response.json();
|
|
4148
|
+
if (!data || typeof data.defaultLocale !== "string" || !Array.isArray(data.languages)) {
|
|
4149
|
+
logger.warn("project-config payload unusable \u2014 keeping local fallback");
|
|
4150
|
+
return null;
|
|
4151
|
+
}
|
|
4152
|
+
return {
|
|
4153
|
+
defaultLocale: data.defaultLocale,
|
|
4154
|
+
languages: data.languages.map(String)
|
|
4155
|
+
};
|
|
4156
|
+
} catch (error) {
|
|
4157
|
+
this.handleCaughtError(error);
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4098
4160
|
/**
|
|
4099
4161
|
* Shared namespace fetch with the canonical 304 contract:
|
|
4100
4162
|
* - If-None-Match is sent ONLY when a snapshot (version + payload) is in hand.
|
|
@@ -4419,7 +4481,87 @@ var LionRapid = (() => {
|
|
|
4419
4481
|
/**
|
|
4420
4482
|
* Make HTTP request with timeout and headers
|
|
4421
4483
|
*/
|
|
4422
|
-
|
|
4484
|
+
makeRequest(url, method, body, extraHeaders) {
|
|
4485
|
+
if (this.authFailedStatus !== null) {
|
|
4486
|
+
return Promise.resolve(
|
|
4487
|
+
new Response(null, {
|
|
4488
|
+
status: this.authFailedStatus,
|
|
4489
|
+
statusText: `auth latched off after ${this.authFailedStatus}`
|
|
4490
|
+
})
|
|
4491
|
+
);
|
|
4492
|
+
}
|
|
4493
|
+
if (method !== "GET") {
|
|
4494
|
+
if (this.writesFailedStatus !== null) {
|
|
4495
|
+
return Promise.resolve(
|
|
4496
|
+
new Response(null, {
|
|
4497
|
+
status: this.writesFailedStatus,
|
|
4498
|
+
statusText: `writes latched off after ${this.writesFailedStatus}`
|
|
4499
|
+
})
|
|
4500
|
+
);
|
|
4501
|
+
}
|
|
4502
|
+
return this.doFetch(url, method, body, extraHeaders).then(
|
|
4503
|
+
(resp) => this.recordOutcome(url, method, resp)
|
|
4504
|
+
);
|
|
4505
|
+
}
|
|
4506
|
+
const negative = this.negativeCache.get(url);
|
|
4507
|
+
if (negative) {
|
|
4508
|
+
if (Date.now() < negative.until) {
|
|
4509
|
+
logger.debug(`Negative-cache hit (${negative.status}): ${url}`);
|
|
4510
|
+
const headers = negative.status === 423 ? { "Retry-After": String(Math.ceil((negative.until - Date.now()) / 1e3)) } : void 0;
|
|
4511
|
+
return Promise.resolve(
|
|
4512
|
+
new Response(null, { status: negative.status, statusText: "negative cache", headers })
|
|
4513
|
+
);
|
|
4514
|
+
}
|
|
4515
|
+
this.negativeCache.delete(url);
|
|
4516
|
+
}
|
|
4517
|
+
const flightKey = `${url}|${extraHeaders?.["If-None-Match"] ?? ""}`;
|
|
4518
|
+
const existing = this.inflightGets.get(flightKey);
|
|
4519
|
+
if (existing) {
|
|
4520
|
+
return existing.then((resp) => this.cloneResponse(resp));
|
|
4521
|
+
}
|
|
4522
|
+
const flight = this.doFetch(url, method, body, extraHeaders).then((resp) => this.recordOutcome(url, method, resp)).finally(() => this.inflightGets.delete(flightKey));
|
|
4523
|
+
this.inflightGets.set(flightKey, flight);
|
|
4524
|
+
return flight.then((resp) => this.cloneResponse(resp));
|
|
4525
|
+
}
|
|
4526
|
+
/** Bookkeeping on every real (non-synthesized) response — runs once per
|
|
4527
|
+
* physical fetch, never once per coalesced awaiter. */
|
|
4528
|
+
recordOutcome(url, method, response) {
|
|
4529
|
+
const status = response.status;
|
|
4530
|
+
if (status === 401 || status === 403 && method === "GET") {
|
|
4531
|
+
if (this.authFailedStatus === null) {
|
|
4532
|
+
this.authFailedStatus = status;
|
|
4533
|
+
console.warn(
|
|
4534
|
+
`[LionRapid] API key rejected (${status}) \u2014 network translations are disabled for this session. Fix the key and reload; retrying cannot heal an auth failure.`
|
|
4535
|
+
);
|
|
4536
|
+
}
|
|
4537
|
+
return response;
|
|
4538
|
+
}
|
|
4539
|
+
if ((status === 403 || status === 429) && method !== "GET") {
|
|
4540
|
+
if (this.writesFailedStatus === null) {
|
|
4541
|
+
this.writesFailedStatus = status;
|
|
4542
|
+
logger.warn(
|
|
4543
|
+
`Write path disabled after ${status} (scope/quota) \u2014 running read-only`
|
|
4544
|
+
);
|
|
4545
|
+
}
|
|
4546
|
+
return response;
|
|
4547
|
+
}
|
|
4548
|
+
if (method === "GET" && (status === 404 || status === 423)) {
|
|
4549
|
+
const retryAfterSec = status === 423 ? Number(response.headers?.get?.("Retry-After")) : NaN;
|
|
4550
|
+
const ttl = Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? retryAfterSec * 1e3 : this.config.options?.negativeCacheTtlMs ?? _NetworkRepository.DEFAULT_NEGATIVE_TTL_MS;
|
|
4551
|
+
this.negativeCache.set(url, { status, until: Date.now() + ttl });
|
|
4552
|
+
} else if (method !== "GET" && response.ok) {
|
|
4553
|
+
this.negativeCache.clear();
|
|
4554
|
+
} else if (method === "GET" && response.ok) {
|
|
4555
|
+
this.negativeCache.delete(url);
|
|
4556
|
+
}
|
|
4557
|
+
return response;
|
|
4558
|
+
}
|
|
4559
|
+
/** Test doubles (and exotic runtimes) hand us plain objects — only real
|
|
4560
|
+
* Responses need cloning so each coalesced awaiter can read the body. */
|
|
4561
|
+
cloneResponse(response) {
|
|
4562
|
+
return typeof response.clone === "function" ? response.clone() : response;
|
|
4563
|
+
}
|
|
4564
|
+
async doFetch(url, method, body, extraHeaders) {
|
|
4423
4565
|
const controller = new AbortController();
|
|
4424
4566
|
const timeout = this.config.options?.timeout ?? 1e4;
|
|
4425
4567
|
const timeoutId = setTimeout(
|
|
@@ -4429,6 +4571,7 @@ var LionRapid = (() => {
|
|
|
4429
4571
|
try {
|
|
4430
4572
|
const headers = {
|
|
4431
4573
|
"Content-Type": "application/json",
|
|
4574
|
+
[SURFACE_HEADER]: SURFACE_TAG,
|
|
4432
4575
|
...this.config.options?.headers,
|
|
4433
4576
|
...extraHeaders
|
|
4434
4577
|
};
|
|
@@ -4452,6 +4595,7 @@ var LionRapid = (() => {
|
|
|
4452
4595
|
/** Legacy bare-version prefix — a version WITHOUT its payload is exactly the
|
|
4453
4596
|
* desync the snapshot store exists to prevent; entries are deleted on sight. */
|
|
4454
4597
|
__publicField(_NetworkRepository, "LEGACY_VERSION_PREFIX", "lionrapid:v:");
|
|
4598
|
+
__publicField(_NetworkRepository, "DEFAULT_NEGATIVE_TTL_MS", 6e4);
|
|
4455
4599
|
var NetworkRepository = _NetworkRepository;
|
|
4456
4600
|
|
|
4457
4601
|
// src/content/validator/ContentValidator.ts
|
|
@@ -5050,9 +5194,11 @@ var LionRapid = (() => {
|
|
|
5050
5194
|
this.config = {
|
|
5051
5195
|
enabled: config.enabled ?? true,
|
|
5052
5196
|
priority: config.priority ?? 0,
|
|
5197
|
+
// Use build sequence by default
|
|
5053
5198
|
options: {
|
|
5054
5199
|
prefix: config.options?.prefix ?? STORAGE_PREFIX,
|
|
5055
5200
|
ttl: config.options?.ttl ?? 24 * 60 * 60 * 1e3,
|
|
5201
|
+
// 24 hours default
|
|
5056
5202
|
maxSize: config.options?.maxSize ?? 500,
|
|
5057
5203
|
...config.options
|
|
5058
5204
|
}
|
|
@@ -5065,6 +5211,10 @@ var LionRapid = (() => {
|
|
|
5065
5211
|
this.migrateIfNeeded();
|
|
5066
5212
|
}
|
|
5067
5213
|
}
|
|
5214
|
+
/**
|
|
5215
|
+
* Check if localStorage is available
|
|
5216
|
+
* Returns false in SSR, private browsing, or when quota is 0
|
|
5217
|
+
*/
|
|
5068
5218
|
checkAvailability() {
|
|
5069
5219
|
if (typeof window === "undefined") {
|
|
5070
5220
|
return false;
|
|
@@ -5078,6 +5228,9 @@ var LionRapid = (() => {
|
|
|
5078
5228
|
return false;
|
|
5079
5229
|
}
|
|
5080
5230
|
}
|
|
5231
|
+
/**
|
|
5232
|
+
* Handle version migrations - clear cache when version changes
|
|
5233
|
+
*/
|
|
5081
5234
|
migrateIfNeeded() {
|
|
5082
5235
|
try {
|
|
5083
5236
|
const storedVersion = window.localStorage.getItem(VERSION_KEY);
|
|
@@ -5088,6 +5241,10 @@ var LionRapid = (() => {
|
|
|
5088
5241
|
} catch {
|
|
5089
5242
|
}
|
|
5090
5243
|
}
|
|
5244
|
+
/**
|
|
5245
|
+
* Get a translation value by key
|
|
5246
|
+
* Returns null if not found or expired
|
|
5247
|
+
*/
|
|
5091
5248
|
get(key) {
|
|
5092
5249
|
if (!this.available) return null;
|
|
5093
5250
|
try {
|
|
@@ -5104,6 +5261,10 @@ var LionRapid = (() => {
|
|
|
5104
5261
|
return null;
|
|
5105
5262
|
}
|
|
5106
5263
|
}
|
|
5264
|
+
/**
|
|
5265
|
+
* Set a translation value
|
|
5266
|
+
* Automatically handles quota exceeded by evicting oldest entries
|
|
5267
|
+
*/
|
|
5107
5268
|
set(key, value) {
|
|
5108
5269
|
if (!this.available) return;
|
|
5109
5270
|
const fullKey = this.prefix + key;
|
|
@@ -5128,6 +5289,9 @@ var LionRapid = (() => {
|
|
|
5128
5289
|
}
|
|
5129
5290
|
}
|
|
5130
5291
|
}
|
|
5292
|
+
/**
|
|
5293
|
+
* Remove a translation by key
|
|
5294
|
+
*/
|
|
5131
5295
|
remove(key) {
|
|
5132
5296
|
if (!this.available) return;
|
|
5133
5297
|
try {
|
|
@@ -5135,6 +5299,10 @@ var LionRapid = (() => {
|
|
|
5135
5299
|
} catch {
|
|
5136
5300
|
}
|
|
5137
5301
|
}
|
|
5302
|
+
/**
|
|
5303
|
+
* Clear all LionRapid entries from localStorage
|
|
5304
|
+
* Preserves entries from other applications
|
|
5305
|
+
*/
|
|
5138
5306
|
clear() {
|
|
5139
5307
|
if (!this.available) return;
|
|
5140
5308
|
try {
|
|
@@ -5149,6 +5317,9 @@ var LionRapid = (() => {
|
|
|
5149
5317
|
} catch {
|
|
5150
5318
|
}
|
|
5151
5319
|
}
|
|
5320
|
+
/**
|
|
5321
|
+
* Clear all entries for a specific namespace
|
|
5322
|
+
*/
|
|
5152
5323
|
clearNamespace(locale, namespace) {
|
|
5153
5324
|
if (!this.available) return;
|
|
5154
5325
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
@@ -5167,6 +5338,9 @@ var LionRapid = (() => {
|
|
|
5167
5338
|
} catch {
|
|
5168
5339
|
}
|
|
5169
5340
|
}
|
|
5341
|
+
/**
|
|
5342
|
+
* Get namespace translations
|
|
5343
|
+
*/
|
|
5170
5344
|
getNamespace(locale, namespace) {
|
|
5171
5345
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5172
5346
|
const value = this.get(namespaceCacheKey);
|
|
@@ -5178,10 +5352,16 @@ var LionRapid = (() => {
|
|
|
5178
5352
|
return null;
|
|
5179
5353
|
}
|
|
5180
5354
|
}
|
|
5355
|
+
/**
|
|
5356
|
+
* Set namespace translations
|
|
5357
|
+
*/
|
|
5181
5358
|
setNamespace(locale, namespace, translations) {
|
|
5182
5359
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5183
5360
|
this.set(namespaceCacheKey, JSON.stringify(translations));
|
|
5184
5361
|
}
|
|
5362
|
+
/**
|
|
5363
|
+
* Get all cache entries for debugging
|
|
5364
|
+
*/
|
|
5185
5365
|
getEntries() {
|
|
5186
5366
|
const entries = {};
|
|
5187
5367
|
if (!this.available) return entries;
|
|
@@ -5201,12 +5381,21 @@ var LionRapid = (() => {
|
|
|
5201
5381
|
}
|
|
5202
5382
|
return entries;
|
|
5203
5383
|
}
|
|
5384
|
+
/**
|
|
5385
|
+
* Get repository configuration
|
|
5386
|
+
*/
|
|
5204
5387
|
getConfig() {
|
|
5205
5388
|
return this.config;
|
|
5206
5389
|
}
|
|
5390
|
+
/**
|
|
5391
|
+
* Check if localStorage is available
|
|
5392
|
+
*/
|
|
5207
5393
|
isAvailable() {
|
|
5208
5394
|
return this.available;
|
|
5209
5395
|
}
|
|
5396
|
+
/**
|
|
5397
|
+
* Get the number of entries in the cache
|
|
5398
|
+
*/
|
|
5210
5399
|
getEntryCount() {
|
|
5211
5400
|
if (!this.available) return 0;
|
|
5212
5401
|
let count = 0;
|
|
@@ -5221,12 +5410,18 @@ var LionRapid = (() => {
|
|
|
5221
5410
|
}
|
|
5222
5411
|
return count;
|
|
5223
5412
|
}
|
|
5413
|
+
/**
|
|
5414
|
+
* Check if error is a quota exceeded error
|
|
5415
|
+
*/
|
|
5224
5416
|
isQuotaError(error) {
|
|
5225
5417
|
if (error instanceof DOMException) {
|
|
5226
5418
|
return error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED";
|
|
5227
5419
|
}
|
|
5228
5420
|
return false;
|
|
5229
5421
|
}
|
|
5422
|
+
/**
|
|
5423
|
+
* Evict oldest 25% of entries when quota is exceeded
|
|
5424
|
+
*/
|
|
5230
5425
|
evictOldest() {
|
|
5231
5426
|
if (!this.available) return;
|
|
5232
5427
|
try {
|
|
@@ -5254,6 +5449,9 @@ var LionRapid = (() => {
|
|
|
5254
5449
|
} catch {
|
|
5255
5450
|
}
|
|
5256
5451
|
}
|
|
5452
|
+
/**
|
|
5453
|
+
* Get cache statistics
|
|
5454
|
+
*/
|
|
5257
5455
|
getCacheStats() {
|
|
5258
5456
|
const size = this.getEntryCount();
|
|
5259
5457
|
const usage = this.maxSize > 0 ? `${Math.round(size / this.maxSize * 100)}%` : "0%";
|
|
@@ -5267,7 +5465,7 @@ var LionRapid = (() => {
|
|
|
5267
5465
|
|
|
5268
5466
|
// src/browser/storage/cache-storage-repository.ts
|
|
5269
5467
|
var CACHE_NAME = "lionrapid-v1";
|
|
5270
|
-
var CACHE_PREFIX = "lionrapid
|
|
5468
|
+
var CACHE_PREFIX = "https://cache.lionrapid.internal/";
|
|
5271
5469
|
var CacheStorageRepository = class {
|
|
5272
5470
|
constructor(config = {}) {
|
|
5273
5471
|
__publicField(this, "name", "CacheStorageRepository");
|
|
@@ -5282,6 +5480,7 @@ var LionRapid = (() => {
|
|
|
5282
5480
|
options: {
|
|
5283
5481
|
cacheName: config.options?.cacheName ?? CACHE_NAME,
|
|
5284
5482
|
ttl: config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3,
|
|
5483
|
+
// 7 days default
|
|
5285
5484
|
...config.options
|
|
5286
5485
|
}
|
|
5287
5486
|
};
|
|
@@ -5289,9 +5488,17 @@ var LionRapid = (() => {
|
|
|
5289
5488
|
this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
|
|
5290
5489
|
this.available = this.checkAvailability();
|
|
5291
5490
|
}
|
|
5491
|
+
/**
|
|
5492
|
+
* Check if Cache API is available
|
|
5493
|
+
* Returns false in SSR, old browsers, or insecure contexts
|
|
5494
|
+
*/
|
|
5292
5495
|
checkAvailability() {
|
|
5293
5496
|
return typeof caches !== "undefined";
|
|
5294
5497
|
}
|
|
5498
|
+
/**
|
|
5499
|
+
* Get a translation value by key
|
|
5500
|
+
* @throws {TranslationNotFoundError} When translation doesn't exist or is expired
|
|
5501
|
+
*/
|
|
5295
5502
|
async get(key) {
|
|
5296
5503
|
if (!this.available) {
|
|
5297
5504
|
throw new TranslationNotFoundError(key);
|
|
@@ -5315,6 +5522,9 @@ var LionRapid = (() => {
|
|
|
5315
5522
|
throw new TranslationNotFoundError(key);
|
|
5316
5523
|
}
|
|
5317
5524
|
}
|
|
5525
|
+
/**
|
|
5526
|
+
* Set a translation value
|
|
5527
|
+
*/
|
|
5318
5528
|
async set(key, value) {
|
|
5319
5529
|
if (!this.available) return;
|
|
5320
5530
|
try {
|
|
@@ -5333,6 +5543,9 @@ var LionRapid = (() => {
|
|
|
5333
5543
|
} catch {
|
|
5334
5544
|
}
|
|
5335
5545
|
}
|
|
5546
|
+
/**
|
|
5547
|
+
* Remove a translation by key
|
|
5548
|
+
*/
|
|
5336
5549
|
async remove(key) {
|
|
5337
5550
|
if (!this.available) return;
|
|
5338
5551
|
try {
|
|
@@ -5341,6 +5554,9 @@ var LionRapid = (() => {
|
|
|
5341
5554
|
} catch {
|
|
5342
5555
|
}
|
|
5343
5556
|
}
|
|
5557
|
+
/**
|
|
5558
|
+
* Clear all LionRapid entries from the cache
|
|
5559
|
+
*/
|
|
5344
5560
|
async clear() {
|
|
5345
5561
|
if (!this.available) return;
|
|
5346
5562
|
try {
|
|
@@ -5352,6 +5568,9 @@ var LionRapid = (() => {
|
|
|
5352
5568
|
} catch {
|
|
5353
5569
|
}
|
|
5354
5570
|
}
|
|
5571
|
+
/**
|
|
5572
|
+
* Clear all entries for a specific namespace
|
|
5573
|
+
*/
|
|
5355
5574
|
async clearNamespace(locale, namespace) {
|
|
5356
5575
|
if (!this.available) return;
|
|
5357
5576
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
@@ -5369,6 +5588,10 @@ var LionRapid = (() => {
|
|
|
5369
5588
|
} catch {
|
|
5370
5589
|
}
|
|
5371
5590
|
}
|
|
5591
|
+
/**
|
|
5592
|
+
* Get namespace translations
|
|
5593
|
+
* @throws {TranslationNotFoundError} When namespace doesn't exist
|
|
5594
|
+
*/
|
|
5372
5595
|
async getNamespace(locale, namespace) {
|
|
5373
5596
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5374
5597
|
const value = await this.get(namespaceCacheKey);
|
|
@@ -5379,16 +5602,29 @@ var LionRapid = (() => {
|
|
|
5379
5602
|
throw new TranslationNotFoundError(namespaceCacheKey);
|
|
5380
5603
|
}
|
|
5381
5604
|
}
|
|
5605
|
+
/**
|
|
5606
|
+
* Set namespace translations
|
|
5607
|
+
*/
|
|
5382
5608
|
async setNamespace(locale, namespace, translations) {
|
|
5383
5609
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5384
5610
|
await this.set(namespaceCacheKey, JSON.stringify(translations));
|
|
5385
5611
|
}
|
|
5612
|
+
/**
|
|
5613
|
+
* Get repository configuration
|
|
5614
|
+
*/
|
|
5386
5615
|
getConfig() {
|
|
5387
5616
|
return this.config;
|
|
5388
5617
|
}
|
|
5618
|
+
/**
|
|
5619
|
+
* Check if Cache API is available
|
|
5620
|
+
*/
|
|
5389
5621
|
isAvailable() {
|
|
5390
5622
|
return this.available;
|
|
5391
5623
|
}
|
|
5624
|
+
/**
|
|
5625
|
+
* Get all cached entries (for debugging)
|
|
5626
|
+
* Returns an object mapping keys to values
|
|
5627
|
+
*/
|
|
5392
5628
|
async getEntries() {
|
|
5393
5629
|
const entries = {};
|
|
5394
5630
|
if (!this.available) return entries;
|
|
@@ -5411,6 +5647,9 @@ var LionRapid = (() => {
|
|
|
5411
5647
|
}
|
|
5412
5648
|
return entries;
|
|
5413
5649
|
}
|
|
5650
|
+
/**
|
|
5651
|
+
* Get cache statistics
|
|
5652
|
+
*/
|
|
5414
5653
|
async getCacheStats() {
|
|
5415
5654
|
if (!this.available) {
|
|
5416
5655
|
return { size: 0, cacheName: this.cacheName };
|