@lionrapid/core 0.6.1 → 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.
- 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 +264 -24
- package/dist/browser/lionrapid.auto.dev.js.map +2 -2
- package/dist/browser/lionrapid.auto.js +264 -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 +238 -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 +238 -2
- package/dist/browser/lionrapid.iife.dev.js.map +2 -2
- package/dist/browser/lionrapid.iife.js +238 -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 +238 -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 +149 -1
- package/dist/repositories/network-repository.js.map +1 -1
- package/package.json +1 -1
|
@@ -3977,6 +3977,31 @@ var LionRapid = (() => {
|
|
|
3977
3977
|
* and payload can never desync because they live and die together.
|
|
3978
3978
|
*/
|
|
3979
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);
|
|
3980
4005
|
/**
|
|
3981
4006
|
* Default endpoint templates with placeholder support
|
|
3982
4007
|
* Placeholders: :key, :locale, :namespace
|
|
@@ -3984,6 +4009,7 @@ var LionRapid = (() => {
|
|
|
3984
4009
|
__publicField(this, "DEFAULT_ENDPOINTS", {
|
|
3985
4010
|
getTranslation: "/api/integrations/translations/:key",
|
|
3986
4011
|
getNamespace: "/api/integrations/translations/:locale/:namespace",
|
|
4012
|
+
getProjectConfig: "/api/integrations/project-config",
|
|
3987
4013
|
setTranslation: "/api/integrations/sync/:key",
|
|
3988
4014
|
setNamespace: "/api/integrations/sync/:locale/:namespace",
|
|
3989
4015
|
setBatch: "/api/integrations/sync/batch",
|
|
@@ -4095,6 +4121,40 @@ var LionRapid = (() => {
|
|
|
4095
4121
|
this.handleCaughtError(error);
|
|
4096
4122
|
}
|
|
4097
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
|
+
}
|
|
4098
4158
|
/**
|
|
4099
4159
|
* Shared namespace fetch with the canonical 304 contract:
|
|
4100
4160
|
* - If-None-Match is sent ONLY when a snapshot (version + payload) is in hand.
|
|
@@ -4419,7 +4479,87 @@ var LionRapid = (() => {
|
|
|
4419
4479
|
/**
|
|
4420
4480
|
* Make HTTP request with timeout and headers
|
|
4421
4481
|
*/
|
|
4422
|
-
|
|
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) {
|
|
4423
4563
|
const controller = new AbortController();
|
|
4424
4564
|
const timeout = this.config.options?.timeout ?? 1e4;
|
|
4425
4565
|
const timeoutId = setTimeout(
|
|
@@ -4452,6 +4592,7 @@ var LionRapid = (() => {
|
|
|
4452
4592
|
/** Legacy bare-version prefix — a version WITHOUT its payload is exactly the
|
|
4453
4593
|
* desync the snapshot store exists to prevent; entries are deleted on sight. */
|
|
4454
4594
|
__publicField(_NetworkRepository, "LEGACY_VERSION_PREFIX", "lionrapid:v:");
|
|
4595
|
+
__publicField(_NetworkRepository, "DEFAULT_NEGATIVE_TTL_MS", 6e4);
|
|
4455
4596
|
var NetworkRepository = _NetworkRepository;
|
|
4456
4597
|
|
|
4457
4598
|
// src/content/validator/ContentValidator.ts
|
|
@@ -5050,9 +5191,11 @@ var LionRapid = (() => {
|
|
|
5050
5191
|
this.config = {
|
|
5051
5192
|
enabled: config.enabled ?? true,
|
|
5052
5193
|
priority: config.priority ?? 0,
|
|
5194
|
+
// Use build sequence by default
|
|
5053
5195
|
options: {
|
|
5054
5196
|
prefix: config.options?.prefix ?? STORAGE_PREFIX,
|
|
5055
5197
|
ttl: config.options?.ttl ?? 24 * 60 * 60 * 1e3,
|
|
5198
|
+
// 24 hours default
|
|
5056
5199
|
maxSize: config.options?.maxSize ?? 500,
|
|
5057
5200
|
...config.options
|
|
5058
5201
|
}
|
|
@@ -5065,6 +5208,10 @@ var LionRapid = (() => {
|
|
|
5065
5208
|
this.migrateIfNeeded();
|
|
5066
5209
|
}
|
|
5067
5210
|
}
|
|
5211
|
+
/**
|
|
5212
|
+
* Check if localStorage is available
|
|
5213
|
+
* Returns false in SSR, private browsing, or when quota is 0
|
|
5214
|
+
*/
|
|
5068
5215
|
checkAvailability() {
|
|
5069
5216
|
if (typeof window === "undefined") {
|
|
5070
5217
|
return false;
|
|
@@ -5078,6 +5225,9 @@ var LionRapid = (() => {
|
|
|
5078
5225
|
return false;
|
|
5079
5226
|
}
|
|
5080
5227
|
}
|
|
5228
|
+
/**
|
|
5229
|
+
* Handle version migrations - clear cache when version changes
|
|
5230
|
+
*/
|
|
5081
5231
|
migrateIfNeeded() {
|
|
5082
5232
|
try {
|
|
5083
5233
|
const storedVersion = window.localStorage.getItem(VERSION_KEY);
|
|
@@ -5088,6 +5238,10 @@ var LionRapid = (() => {
|
|
|
5088
5238
|
} catch {
|
|
5089
5239
|
}
|
|
5090
5240
|
}
|
|
5241
|
+
/**
|
|
5242
|
+
* Get a translation value by key
|
|
5243
|
+
* Returns null if not found or expired
|
|
5244
|
+
*/
|
|
5091
5245
|
get(key) {
|
|
5092
5246
|
if (!this.available) return null;
|
|
5093
5247
|
try {
|
|
@@ -5104,6 +5258,10 @@ var LionRapid = (() => {
|
|
|
5104
5258
|
return null;
|
|
5105
5259
|
}
|
|
5106
5260
|
}
|
|
5261
|
+
/**
|
|
5262
|
+
* Set a translation value
|
|
5263
|
+
* Automatically handles quota exceeded by evicting oldest entries
|
|
5264
|
+
*/
|
|
5107
5265
|
set(key, value) {
|
|
5108
5266
|
if (!this.available) return;
|
|
5109
5267
|
const fullKey = this.prefix + key;
|
|
@@ -5128,6 +5286,9 @@ var LionRapid = (() => {
|
|
|
5128
5286
|
}
|
|
5129
5287
|
}
|
|
5130
5288
|
}
|
|
5289
|
+
/**
|
|
5290
|
+
* Remove a translation by key
|
|
5291
|
+
*/
|
|
5131
5292
|
remove(key) {
|
|
5132
5293
|
if (!this.available) return;
|
|
5133
5294
|
try {
|
|
@@ -5135,6 +5296,10 @@ var LionRapid = (() => {
|
|
|
5135
5296
|
} catch {
|
|
5136
5297
|
}
|
|
5137
5298
|
}
|
|
5299
|
+
/**
|
|
5300
|
+
* Clear all LionRapid entries from localStorage
|
|
5301
|
+
* Preserves entries from other applications
|
|
5302
|
+
*/
|
|
5138
5303
|
clear() {
|
|
5139
5304
|
if (!this.available) return;
|
|
5140
5305
|
try {
|
|
@@ -5149,6 +5314,9 @@ var LionRapid = (() => {
|
|
|
5149
5314
|
} catch {
|
|
5150
5315
|
}
|
|
5151
5316
|
}
|
|
5317
|
+
/**
|
|
5318
|
+
* Clear all entries for a specific namespace
|
|
5319
|
+
*/
|
|
5152
5320
|
clearNamespace(locale, namespace) {
|
|
5153
5321
|
if (!this.available) return;
|
|
5154
5322
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
@@ -5167,6 +5335,9 @@ var LionRapid = (() => {
|
|
|
5167
5335
|
} catch {
|
|
5168
5336
|
}
|
|
5169
5337
|
}
|
|
5338
|
+
/**
|
|
5339
|
+
* Get namespace translations
|
|
5340
|
+
*/
|
|
5170
5341
|
getNamespace(locale, namespace) {
|
|
5171
5342
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5172
5343
|
const value = this.get(namespaceCacheKey);
|
|
@@ -5178,10 +5349,16 @@ var LionRapid = (() => {
|
|
|
5178
5349
|
return null;
|
|
5179
5350
|
}
|
|
5180
5351
|
}
|
|
5352
|
+
/**
|
|
5353
|
+
* Set namespace translations
|
|
5354
|
+
*/
|
|
5181
5355
|
setNamespace(locale, namespace, translations) {
|
|
5182
5356
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5183
5357
|
this.set(namespaceCacheKey, JSON.stringify(translations));
|
|
5184
5358
|
}
|
|
5359
|
+
/**
|
|
5360
|
+
* Get all cache entries for debugging
|
|
5361
|
+
*/
|
|
5185
5362
|
getEntries() {
|
|
5186
5363
|
const entries = {};
|
|
5187
5364
|
if (!this.available) return entries;
|
|
@@ -5201,12 +5378,21 @@ var LionRapid = (() => {
|
|
|
5201
5378
|
}
|
|
5202
5379
|
return entries;
|
|
5203
5380
|
}
|
|
5381
|
+
/**
|
|
5382
|
+
* Get repository configuration
|
|
5383
|
+
*/
|
|
5204
5384
|
getConfig() {
|
|
5205
5385
|
return this.config;
|
|
5206
5386
|
}
|
|
5387
|
+
/**
|
|
5388
|
+
* Check if localStorage is available
|
|
5389
|
+
*/
|
|
5207
5390
|
isAvailable() {
|
|
5208
5391
|
return this.available;
|
|
5209
5392
|
}
|
|
5393
|
+
/**
|
|
5394
|
+
* Get the number of entries in the cache
|
|
5395
|
+
*/
|
|
5210
5396
|
getEntryCount() {
|
|
5211
5397
|
if (!this.available) return 0;
|
|
5212
5398
|
let count = 0;
|
|
@@ -5221,12 +5407,18 @@ var LionRapid = (() => {
|
|
|
5221
5407
|
}
|
|
5222
5408
|
return count;
|
|
5223
5409
|
}
|
|
5410
|
+
/**
|
|
5411
|
+
* Check if error is a quota exceeded error
|
|
5412
|
+
*/
|
|
5224
5413
|
isQuotaError(error) {
|
|
5225
5414
|
if (error instanceof DOMException) {
|
|
5226
5415
|
return error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED";
|
|
5227
5416
|
}
|
|
5228
5417
|
return false;
|
|
5229
5418
|
}
|
|
5419
|
+
/**
|
|
5420
|
+
* Evict oldest 25% of entries when quota is exceeded
|
|
5421
|
+
*/
|
|
5230
5422
|
evictOldest() {
|
|
5231
5423
|
if (!this.available) return;
|
|
5232
5424
|
try {
|
|
@@ -5254,6 +5446,9 @@ var LionRapid = (() => {
|
|
|
5254
5446
|
} catch {
|
|
5255
5447
|
}
|
|
5256
5448
|
}
|
|
5449
|
+
/**
|
|
5450
|
+
* Get cache statistics
|
|
5451
|
+
*/
|
|
5257
5452
|
getCacheStats() {
|
|
5258
5453
|
const size = this.getEntryCount();
|
|
5259
5454
|
const usage = this.maxSize > 0 ? `${Math.round(size / this.maxSize * 100)}%` : "0%";
|
|
@@ -5267,7 +5462,7 @@ var LionRapid = (() => {
|
|
|
5267
5462
|
|
|
5268
5463
|
// src/browser/storage/cache-storage-repository.ts
|
|
5269
5464
|
var CACHE_NAME = "lionrapid-v1";
|
|
5270
|
-
var CACHE_PREFIX = "lionrapid
|
|
5465
|
+
var CACHE_PREFIX = "https://cache.lionrapid.internal/";
|
|
5271
5466
|
var CacheStorageRepository = class {
|
|
5272
5467
|
constructor(config = {}) {
|
|
5273
5468
|
__publicField(this, "name", "CacheStorageRepository");
|
|
@@ -5282,6 +5477,7 @@ var LionRapid = (() => {
|
|
|
5282
5477
|
options: {
|
|
5283
5478
|
cacheName: config.options?.cacheName ?? CACHE_NAME,
|
|
5284
5479
|
ttl: config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3,
|
|
5480
|
+
// 7 days default
|
|
5285
5481
|
...config.options
|
|
5286
5482
|
}
|
|
5287
5483
|
};
|
|
@@ -5289,9 +5485,17 @@ var LionRapid = (() => {
|
|
|
5289
5485
|
this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
|
|
5290
5486
|
this.available = this.checkAvailability();
|
|
5291
5487
|
}
|
|
5488
|
+
/**
|
|
5489
|
+
* Check if Cache API is available
|
|
5490
|
+
* Returns false in SSR, old browsers, or insecure contexts
|
|
5491
|
+
*/
|
|
5292
5492
|
checkAvailability() {
|
|
5293
5493
|
return typeof caches !== "undefined";
|
|
5294
5494
|
}
|
|
5495
|
+
/**
|
|
5496
|
+
* Get a translation value by key
|
|
5497
|
+
* @throws {TranslationNotFoundError} When translation doesn't exist or is expired
|
|
5498
|
+
*/
|
|
5295
5499
|
async get(key) {
|
|
5296
5500
|
if (!this.available) {
|
|
5297
5501
|
throw new TranslationNotFoundError(key);
|
|
@@ -5315,6 +5519,9 @@ var LionRapid = (() => {
|
|
|
5315
5519
|
throw new TranslationNotFoundError(key);
|
|
5316
5520
|
}
|
|
5317
5521
|
}
|
|
5522
|
+
/**
|
|
5523
|
+
* Set a translation value
|
|
5524
|
+
*/
|
|
5318
5525
|
async set(key, value) {
|
|
5319
5526
|
if (!this.available) return;
|
|
5320
5527
|
try {
|
|
@@ -5333,6 +5540,9 @@ var LionRapid = (() => {
|
|
|
5333
5540
|
} catch {
|
|
5334
5541
|
}
|
|
5335
5542
|
}
|
|
5543
|
+
/**
|
|
5544
|
+
* Remove a translation by key
|
|
5545
|
+
*/
|
|
5336
5546
|
async remove(key) {
|
|
5337
5547
|
if (!this.available) return;
|
|
5338
5548
|
try {
|
|
@@ -5341,6 +5551,9 @@ var LionRapid = (() => {
|
|
|
5341
5551
|
} catch {
|
|
5342
5552
|
}
|
|
5343
5553
|
}
|
|
5554
|
+
/**
|
|
5555
|
+
* Clear all LionRapid entries from the cache
|
|
5556
|
+
*/
|
|
5344
5557
|
async clear() {
|
|
5345
5558
|
if (!this.available) return;
|
|
5346
5559
|
try {
|
|
@@ -5352,6 +5565,9 @@ var LionRapid = (() => {
|
|
|
5352
5565
|
} catch {
|
|
5353
5566
|
}
|
|
5354
5567
|
}
|
|
5568
|
+
/**
|
|
5569
|
+
* Clear all entries for a specific namespace
|
|
5570
|
+
*/
|
|
5355
5571
|
async clearNamespace(locale, namespace) {
|
|
5356
5572
|
if (!this.available) return;
|
|
5357
5573
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
@@ -5369,6 +5585,10 @@ var LionRapid = (() => {
|
|
|
5369
5585
|
} catch {
|
|
5370
5586
|
}
|
|
5371
5587
|
}
|
|
5588
|
+
/**
|
|
5589
|
+
* Get namespace translations
|
|
5590
|
+
* @throws {TranslationNotFoundError} When namespace doesn't exist
|
|
5591
|
+
*/
|
|
5372
5592
|
async getNamespace(locale, namespace) {
|
|
5373
5593
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5374
5594
|
const value = await this.get(namespaceCacheKey);
|
|
@@ -5379,16 +5599,29 @@ var LionRapid = (() => {
|
|
|
5379
5599
|
throw new TranslationNotFoundError(namespaceCacheKey);
|
|
5380
5600
|
}
|
|
5381
5601
|
}
|
|
5602
|
+
/**
|
|
5603
|
+
* Set namespace translations
|
|
5604
|
+
*/
|
|
5382
5605
|
async setNamespace(locale, namespace, translations) {
|
|
5383
5606
|
const namespaceCacheKey = `@${locale}:${namespace}`;
|
|
5384
5607
|
await this.set(namespaceCacheKey, JSON.stringify(translations));
|
|
5385
5608
|
}
|
|
5609
|
+
/**
|
|
5610
|
+
* Get repository configuration
|
|
5611
|
+
*/
|
|
5386
5612
|
getConfig() {
|
|
5387
5613
|
return this.config;
|
|
5388
5614
|
}
|
|
5615
|
+
/**
|
|
5616
|
+
* Check if Cache API is available
|
|
5617
|
+
*/
|
|
5389
5618
|
isAvailable() {
|
|
5390
5619
|
return this.available;
|
|
5391
5620
|
}
|
|
5621
|
+
/**
|
|
5622
|
+
* Get all cached entries (for debugging)
|
|
5623
|
+
* Returns an object mapping keys to values
|
|
5624
|
+
*/
|
|
5392
5625
|
async getEntries() {
|
|
5393
5626
|
const entries = {};
|
|
5394
5627
|
if (!this.available) return entries;
|
|
@@ -5411,6 +5644,9 @@ var LionRapid = (() => {
|
|
|
5411
5644
|
}
|
|
5412
5645
|
return entries;
|
|
5413
5646
|
}
|
|
5647
|
+
/**
|
|
5648
|
+
* Get cache statistics
|
|
5649
|
+
*/
|
|
5414
5650
|
async getCacheStats() {
|
|
5415
5651
|
if (!this.available) {
|
|
5416
5652
|
return { size: 0, cacheName: this.cacheName };
|