@lionrapid/core 0.6.6 → 0.7.0
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/LICENSE +21 -0
- package/dist/browser/auto-init.d.ts +6 -0
- package/dist/browser/auto-init.d.ts.map +1 -1
- package/dist/browser/auto-init.js +36 -6
- package/dist/browser/auto-init.js.map +1 -1
- package/dist/browser/language-switcher.d.ts +12 -0
- package/dist/browser/language-switcher.d.ts.map +1 -1
- package/dist/browser/language-switcher.js +58 -0
- package/dist/browser/language-switcher.js.map +1 -1
- package/dist/browser/lionrapid.auto.dev.js +163 -14
- package/dist/browser/lionrapid.auto.dev.js.map +3 -3
- package/dist/browser/lionrapid.auto.js +163 -14
- package/dist/browser/lionrapid.auto.js.map +3 -3
- package/dist/browser/lionrapid.auto.min.js +5 -5
- package/dist/browser/lionrapid.auto.min.js.map +4 -4
- package/dist/browser/lionrapid.esm.js +103 -10
- package/dist/browser/lionrapid.esm.js.map +2 -2
- package/dist/browser/lionrapid.esm.min.js +4 -4
- package/dist/browser/lionrapid.esm.min.js.map +3 -3
- package/dist/browser/lionrapid.iife.dev.js +103 -10
- package/dist/browser/lionrapid.iife.dev.js.map +2 -2
- package/dist/browser/lionrapid.iife.js +103 -10
- package/dist/browser/lionrapid.iife.js.map +2 -2
- package/dist/browser/lionrapid.iife.min.js +4 -4
- package/dist/browser/lionrapid.iife.min.js.map +3 -3
- package/dist/browser/lionrapid.umd.js +103 -10
- package/dist/browser/lionrapid.umd.js.map +2 -2
- package/dist/browser/lionrapid.umd.min.js +4 -4
- package/dist/browser/lionrapid.umd.min.js.map +3 -3
- package/dist/browser/storage/cache-storage-repository.d.ts +9 -0
- package/dist/browser/storage/cache-storage-repository.d.ts.map +1 -1
- package/dist/browser/storage/cache-storage-repository.js +14 -10
- package/dist/browser/storage/cache-storage-repository.js.map +1 -1
- package/dist/browser/storage/scope.d.ts +12 -0
- package/dist/browser/storage/scope.d.ts.map +1 -0
- package/dist/browser/storage/scope.js +15 -0
- package/dist/browser/storage/scope.js.map +1 -0
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +9 -0
- package/dist/builder.js.map +1 -1
- package/dist/handlers/async-storage-handler.d.ts +9 -0
- package/dist/handlers/async-storage-handler.d.ts.map +1 -1
- package/dist/handlers/async-storage-handler.js +42 -0
- package/dist/handlers/async-storage-handler.js.map +1 -1
- package/dist/handlers/handler-chain.d.ts +2 -0
- package/dist/handlers/handler-chain.d.ts.map +1 -1
- package/dist/handlers/handler-chain.js +29 -0
- package/dist/handlers/handler-chain.js.map +1 -1
- package/dist/handlers/sync-storage-handler.d.ts +4 -0
- package/dist/handlers/sync-storage-handler.d.ts.map +1 -1
- package/dist/handlers/sync-storage-handler.js +35 -0
- package/dist/handlers/sync-storage-handler.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interfaces/handler.interface.d.ts +4 -0
- package/dist/interfaces/handler.interface.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1234,6 +1234,24 @@ var LionRapid = (() => {
|
|
|
1234
1234
|
});
|
|
1235
1235
|
await Promise.allSettled(savePromises);
|
|
1236
1236
|
}
|
|
1237
|
+
/** Forget `locale:namespace` in every memory and storage handler (a 404). */
|
|
1238
|
+
async forgetNamespaceInHandlers(context) {
|
|
1239
|
+
for (const handler of this.syncHandlers) {
|
|
1240
|
+
try {
|
|
1241
|
+
handler.forgetNamespace?.(context);
|
|
1242
|
+
} catch (error) {
|
|
1243
|
+
logger.warn(`Failed to clear namespace in ${handler.name}`, error);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
for (const handler of this.asyncHandlers) {
|
|
1247
|
+
if (handler.type !== "storage" && handler.type !== "memory") continue;
|
|
1248
|
+
try {
|
|
1249
|
+
await handler.forgetNamespace?.(context);
|
|
1250
|
+
} catch (error) {
|
|
1251
|
+
logger.warn(`Failed to clear namespace in ${handler.name}`, error);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1237
1255
|
async saveNamespaceToHandlers(translations, context) {
|
|
1238
1256
|
this.saveNamespaceToMemoryHandlers(translations, context);
|
|
1239
1257
|
await this.saveNamespaceToStorageHandlers(translations, context);
|
|
@@ -1335,6 +1353,10 @@ var LionRapid = (() => {
|
|
|
1335
1353
|
});
|
|
1336
1354
|
return result.data;
|
|
1337
1355
|
}
|
|
1356
|
+
if (result && result.status === 404) {
|
|
1357
|
+
await this.forgetNamespaceInHandlers({ namespace, locale });
|
|
1358
|
+
return null;
|
|
1359
|
+
}
|
|
1338
1360
|
} catch (error) {
|
|
1339
1361
|
logger.warn(
|
|
1340
1362
|
`Failed to load namespace: ${locale}:${namespace} from ${handler.name}`,
|
|
@@ -1718,6 +1740,7 @@ var LionRapid = (() => {
|
|
|
1718
1740
|
context.locale + ":" + context.namespace,
|
|
1719
1741
|
this.name
|
|
1720
1742
|
);
|
|
1743
|
+
const previousKeys = this.storedNamespaceKeys(context.locale, context.namespace);
|
|
1721
1744
|
const namespaceCacheKey = createNamespaceCacheKey(
|
|
1722
1745
|
context.locale,
|
|
1723
1746
|
context.namespace
|
|
@@ -1729,11 +1752,38 @@ var LionRapid = (() => {
|
|
|
1729
1752
|
context.locale,
|
|
1730
1753
|
context.namespace
|
|
1731
1754
|
);
|
|
1755
|
+
for (const key of previousKeys) {
|
|
1756
|
+
if (!(key in flattened)) this.removeQuietly(key);
|
|
1757
|
+
}
|
|
1732
1758
|
for (const [flatKey, flatValue] of Object.entries(flattened)) {
|
|
1733
1759
|
this.setWithTTL(flatKey, flatValue);
|
|
1734
1760
|
}
|
|
1735
1761
|
repoBus.setSuccess(JSON.stringify(translations));
|
|
1736
1762
|
}
|
|
1763
|
+
/** Forget a namespace the server says does not exist (404). See AsyncStorageHandler. */
|
|
1764
|
+
forgetNamespace(context) {
|
|
1765
|
+
if (!context.namespace) return;
|
|
1766
|
+
for (const key of this.storedNamespaceKeys(context.locale, context.namespace)) {
|
|
1767
|
+
this.removeQuietly(key);
|
|
1768
|
+
}
|
|
1769
|
+
this.clearNamespace(context.locale, context.namespace);
|
|
1770
|
+
}
|
|
1771
|
+
storedNamespaceKeys(locale, namespace) {
|
|
1772
|
+
try {
|
|
1773
|
+
const blob = this.repository.get(createNamespaceCacheKey(locale, namespace));
|
|
1774
|
+
if (!blob) return [];
|
|
1775
|
+
return Object.keys(flattenTranslations(JSON.parse(blob), "", locale, namespace));
|
|
1776
|
+
} catch {
|
|
1777
|
+
return [];
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
removeQuietly(cacheKey) {
|
|
1781
|
+
this.ttlMap.delete(cacheKey);
|
|
1782
|
+
try {
|
|
1783
|
+
this.repository.remove(cacheKey);
|
|
1784
|
+
} catch {
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1737
1787
|
/**
|
|
1738
1788
|
* ✅ Strategy 1: Direct cache lookup using unified pattern
|
|
1739
1789
|
* Returns parsed ContentUnit (text + styles) or null
|
|
@@ -1987,6 +2037,7 @@ var LionRapid = (() => {
|
|
|
1987
2037
|
logger.debug(
|
|
1988
2038
|
`Saving namespace: ${context.locale}:${context.namespace} (${keyCount} keys)`
|
|
1989
2039
|
);
|
|
2040
|
+
const previousKeys = await this.storedNamespaceKeys(context.locale, context.namespace);
|
|
1990
2041
|
const namespaceCacheKey = createNamespaceCacheKey(
|
|
1991
2042
|
context.locale,
|
|
1992
2043
|
context.namespace
|
|
@@ -1998,6 +2049,9 @@ var LionRapid = (() => {
|
|
|
1998
2049
|
context.locale,
|
|
1999
2050
|
context.namespace
|
|
2000
2051
|
);
|
|
2052
|
+
for (const key of previousKeys) {
|
|
2053
|
+
if (!(key in flattened)) await this.removeQuietly(key);
|
|
2054
|
+
}
|
|
2001
2055
|
let savedCount = 0;
|
|
2002
2056
|
for (const [flatKey, flatValue] of Object.entries(flattened)) {
|
|
2003
2057
|
await this.setWithTTL(flatKey, flatValue);
|
|
@@ -2006,6 +2060,35 @@ var LionRapid = (() => {
|
|
|
2006
2060
|
logger.debug(`Saved: ${savedCount} keys + namespace blob`);
|
|
2007
2061
|
repoBus.setSuccess(JSON.stringify(translations));
|
|
2008
2062
|
}
|
|
2063
|
+
/**
|
|
2064
|
+
* Forget a namespace the server says does not exist (404): its blob and
|
|
2065
|
+
* every per-key entry the blob listed. A network failure never gets here,
|
|
2066
|
+
* so the offline floor still serves when the server is unreachable.
|
|
2067
|
+
*/
|
|
2068
|
+
async forgetNamespace(context) {
|
|
2069
|
+
if (!context.namespace) return;
|
|
2070
|
+
for (const key of await this.storedNamespaceKeys(context.locale, context.namespace)) {
|
|
2071
|
+
await this.removeQuietly(key);
|
|
2072
|
+
}
|
|
2073
|
+
await this.removeQuietly(createNamespaceCacheKey(context.locale, context.namespace));
|
|
2074
|
+
}
|
|
2075
|
+
/** The per-key cache keys (`locale:namespace:key`) the stored blob lists. */
|
|
2076
|
+
async storedNamespaceKeys(locale, namespace) {
|
|
2077
|
+
try {
|
|
2078
|
+
const blob = await this.repository.get(createNamespaceCacheKey(locale, namespace));
|
|
2079
|
+
if (!blob) return [];
|
|
2080
|
+
return Object.keys(flattenTranslations(JSON.parse(blob), "", locale, namespace));
|
|
2081
|
+
} catch {
|
|
2082
|
+
return [];
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
async removeQuietly(cacheKey) {
|
|
2086
|
+
this.ttlMap.delete(cacheKey);
|
|
2087
|
+
try {
|
|
2088
|
+
await this.repository.remove(cacheKey);
|
|
2089
|
+
} catch {
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2009
2092
|
/**
|
|
2010
2093
|
* ✅ Strategy 1: Direct cache lookup using unified pattern
|
|
2011
2094
|
* Returns parsed ContentUnit (text + styles) or null
|
|
@@ -4233,6 +4316,12 @@ var LionRapid = (() => {
|
|
|
4233
4316
|
logger.debug(`Preloaded: ${namespaceKey}`);
|
|
4234
4317
|
return;
|
|
4235
4318
|
}
|
|
4319
|
+
if (result?.status === 404) {
|
|
4320
|
+
await handlerChain.forgetNamespaceInHandlers({
|
|
4321
|
+
locale: preloadConfig.locale,
|
|
4322
|
+
namespace: preloadConfig.namespace
|
|
4323
|
+
});
|
|
4324
|
+
}
|
|
4236
4325
|
if (result?.error) {
|
|
4237
4326
|
warnLoudlyOnce(namespaceKey, result.error);
|
|
4238
4327
|
logger.warn(`Preload failed: ${namespaceKey}`, result.error);
|
|
@@ -5609,6 +5698,8 @@ var LionRapid = (() => {
|
|
|
5609
5698
|
__publicField(this, "type", "storage");
|
|
5610
5699
|
__publicField(this, "config");
|
|
5611
5700
|
__publicField(this, "cacheName");
|
|
5701
|
+
/** CACHE_PREFIX, plus `<scope>/` when scoped. */
|
|
5702
|
+
__publicField(this, "entryPrefix");
|
|
5612
5703
|
__publicField(this, "defaultTTL");
|
|
5613
5704
|
__publicField(this, "available");
|
|
5614
5705
|
this.config = {
|
|
@@ -5622,6 +5713,8 @@ var LionRapid = (() => {
|
|
|
5622
5713
|
}
|
|
5623
5714
|
};
|
|
5624
5715
|
this.cacheName = this.config.options?.cacheName ?? CACHE_NAME;
|
|
5716
|
+
const scope = this.config.options?.scope;
|
|
5717
|
+
this.entryPrefix = scope ? `${CACHE_PREFIX}${encodeURIComponent(scope)}/` : CACHE_PREFIX;
|
|
5625
5718
|
this.defaultTTL = this.config.options?.ttl ?? 7 * 24 * 60 * 60 * 1e3;
|
|
5626
5719
|
this.available = this.checkAvailability();
|
|
5627
5720
|
}
|
|
@@ -5642,13 +5735,13 @@ var LionRapid = (() => {
|
|
|
5642
5735
|
}
|
|
5643
5736
|
try {
|
|
5644
5737
|
const cache = await caches.open(this.cacheName);
|
|
5645
|
-
const response = await cache.match(
|
|
5738
|
+
const response = await cache.match(this.entryPrefix + key);
|
|
5646
5739
|
if (!response) {
|
|
5647
5740
|
throw new TranslationNotFoundError(key);
|
|
5648
5741
|
}
|
|
5649
5742
|
const data = await response.json();
|
|
5650
5743
|
if (data.expiry !== null && Date.now() > data.expiry) {
|
|
5651
|
-
await cache.delete(
|
|
5744
|
+
await cache.delete(this.entryPrefix + key);
|
|
5652
5745
|
throw new TranslationNotFoundError(key);
|
|
5653
5746
|
}
|
|
5654
5747
|
return data.value;
|
|
@@ -5672,7 +5765,7 @@ var LionRapid = (() => {
|
|
|
5672
5765
|
timestamp: Date.now()
|
|
5673
5766
|
};
|
|
5674
5767
|
await cache.put(
|
|
5675
|
-
|
|
5768
|
+
this.entryPrefix + key,
|
|
5676
5769
|
new Response(JSON.stringify(data), {
|
|
5677
5770
|
headers: { "Content-Type": "application/json" }
|
|
5678
5771
|
})
|
|
@@ -5687,7 +5780,7 @@ var LionRapid = (() => {
|
|
|
5687
5780
|
if (!this.available) return;
|
|
5688
5781
|
try {
|
|
5689
5782
|
const cache = await caches.open(this.cacheName);
|
|
5690
|
-
await cache.delete(
|
|
5783
|
+
await cache.delete(this.entryPrefix + key);
|
|
5691
5784
|
} catch {
|
|
5692
5785
|
}
|
|
5693
5786
|
}
|
|
@@ -5700,7 +5793,7 @@ var LionRapid = (() => {
|
|
|
5700
5793
|
const cache = await caches.open(this.cacheName);
|
|
5701
5794
|
const keys = await cache.keys();
|
|
5702
5795
|
await Promise.all(
|
|
5703
|
-
keys.filter((request) => request.url.includes(
|
|
5796
|
+
keys.filter((request) => request.url.includes(this.entryPrefix)).map((request) => cache.delete(request))
|
|
5704
5797
|
);
|
|
5705
5798
|
} catch {
|
|
5706
5799
|
}
|
|
@@ -5718,7 +5811,7 @@ var LionRapid = (() => {
|
|
|
5718
5811
|
await Promise.all(
|
|
5719
5812
|
keys.filter((request) => {
|
|
5720
5813
|
const url = request.url;
|
|
5721
|
-
const key = url.includes(
|
|
5814
|
+
const key = url.includes(this.entryPrefix) ? url.substring(url.indexOf(this.entryPrefix) + this.entryPrefix.length) : "";
|
|
5722
5815
|
return key === namespaceCacheKey || key.startsWith(keyPrefix);
|
|
5723
5816
|
}).map((request) => cache.delete(request))
|
|
5724
5817
|
);
|
|
@@ -5770,9 +5863,9 @@ var LionRapid = (() => {
|
|
|
5770
5863
|
const keys = await cache.keys();
|
|
5771
5864
|
for (const request of keys) {
|
|
5772
5865
|
const url = request.url;
|
|
5773
|
-
if (!url.includes(
|
|
5866
|
+
if (!url.includes(this.entryPrefix)) continue;
|
|
5774
5867
|
const key = url.substring(
|
|
5775
|
-
url.indexOf(
|
|
5868
|
+
url.indexOf(this.entryPrefix) + this.entryPrefix.length
|
|
5776
5869
|
);
|
|
5777
5870
|
try {
|
|
5778
5871
|
const value = await this.get(key);
|
|
@@ -5794,7 +5887,7 @@ var LionRapid = (() => {
|
|
|
5794
5887
|
try {
|
|
5795
5888
|
const cache = await caches.open(this.cacheName);
|
|
5796
5889
|
const keys = await cache.keys();
|
|
5797
|
-
const size = keys.filter((r) => r.url.includes(
|
|
5890
|
+
const size = keys.filter((r) => r.url.includes(this.entryPrefix)).length;
|
|
5798
5891
|
return { size, cacheName: this.cacheName };
|
|
5799
5892
|
} catch {
|
|
5800
5893
|
return { size: 0, cacheName: this.cacheName };
|
|
@@ -5806,7 +5899,7 @@ var LionRapid = (() => {
|
|
|
5806
5899
|
var DEFAULT_API_BASE_URL = "https://app.lionrapid.com";
|
|
5807
5900
|
|
|
5808
5901
|
// src/index.ts
|
|
5809
|
-
var VERSION = "0.
|
|
5902
|
+
var VERSION = "0.7.0";
|
|
5810
5903
|
return __toCommonJS(index_exports);
|
|
5811
5904
|
})();
|
|
5812
5905
|
//# sourceMappingURL=lionrapid.iife.dev.js.map
|