@form-engine-ts/translator-cache 2.8.0 → 2.9.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/README.md +2 -0
- package/dist/index.cjs +31 -2
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,3 +27,5 @@ are deduplicated, translated once in source order, cached, and restored to their
|
|
|
27
27
|
cache applies both TTL expiration and bounded LRU eviction and exposes `size`, `evictionCount`, and `clear()` diagnostics.
|
|
28
28
|
Use `variant` to isolate glossary/model/configuration revisions, or `buildKey` for complete key control.
|
|
29
29
|
`onStatsReport` receives cumulative real cache hits, misses, evictions, and current size after successful translations.
|
|
30
|
+
Cache backend failures default to `cacheErrorPolicy: "bypass"`: `onCacheError` is notified and translation continues
|
|
31
|
+
through the wrapped adapter. Use `cacheErrorPolicy: "throw"` when cache availability is mandatory.
|
package/dist/index.cjs
CHANGED
|
@@ -113,9 +113,38 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
113
113
|
if (options.buildKey !== void 0 && typeof options.buildKey !== "function") {
|
|
114
114
|
throw new TypeError("buildKey must be a function.");
|
|
115
115
|
}
|
|
116
|
+
if (options.cacheErrorPolicy !== void 0 && options.cacheErrorPolicy !== "bypass" && options.cacheErrorPolicy !== "throw") {
|
|
117
|
+
throw new TypeError('cacheErrorPolicy must be "bypass" or "throw".');
|
|
118
|
+
}
|
|
119
|
+
const cacheErrorPolicy = options.cacheErrorPolicy ?? "bypass";
|
|
116
120
|
const initialEvictionCount = cache.evictionCount ?? 0;
|
|
117
121
|
let hits = 0;
|
|
118
122
|
let misses = 0;
|
|
123
|
+
const handleCacheError = (cause, operation) => {
|
|
124
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
125
|
+
try {
|
|
126
|
+
options.onCacheError?.(error, operation);
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
return error;
|
|
130
|
+
};
|
|
131
|
+
const getCached = async (key) => {
|
|
132
|
+
try {
|
|
133
|
+
return await cache.get(key);
|
|
134
|
+
} catch (cause) {
|
|
135
|
+
const error = handleCacheError(cause, "get");
|
|
136
|
+
if (cacheErrorPolicy === "throw") throw error;
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const setCached = async (key, value) => {
|
|
141
|
+
try {
|
|
142
|
+
await cache.set(key, value, options.ttlMs);
|
|
143
|
+
} catch (cause) {
|
|
144
|
+
const error = handleCacheError(cause, "set");
|
|
145
|
+
if (cacheErrorPolicy === "throw") throw error;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
119
148
|
const reportStats = () => {
|
|
120
149
|
const size = cache.size ?? 0;
|
|
121
150
|
options.onStatsReport?.({
|
|
@@ -142,7 +171,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
142
171
|
if (typeof key !== "string" || key.length === 0) throw new TypeError("Translation cache key must not be empty.");
|
|
143
172
|
return key;
|
|
144
173
|
});
|
|
145
|
-
const cached = await Promise.all(keys.map(
|
|
174
|
+
const cached = await Promise.all(keys.map(getCached));
|
|
146
175
|
hits += cached.filter((value) => value !== void 0).length;
|
|
147
176
|
misses += cached.filter((value) => value === void 0).length;
|
|
148
177
|
const missingByKey = /* @__PURE__ */ new Map();
|
|
@@ -169,7 +198,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
169
198
|
missing.map(async ([key, value], translatedIndex) => {
|
|
170
199
|
const translation = translated[translatedIndex];
|
|
171
200
|
if (translation === void 0) throw new Error("Translation adapter result is unavailable.");
|
|
172
|
-
await
|
|
201
|
+
await setCached(key, translation);
|
|
173
202
|
for (const index of value.indices) cached[index] = translation;
|
|
174
203
|
})
|
|
175
204
|
);
|
package/dist/index.d.cts
CHANGED
|
@@ -25,6 +25,8 @@ interface TranslationCacheOptions {
|
|
|
25
25
|
readonly variant?: string;
|
|
26
26
|
readonly buildKey?: (context: TranslationCacheKeyContext) => string;
|
|
27
27
|
readonly onStatsReport?: (stats: TranslationCacheStats) => void;
|
|
28
|
+
readonly cacheErrorPolicy?: "bypass" | "throw";
|
|
29
|
+
readonly onCacheError?: (error: Error, operation: "get" | "set") => void;
|
|
28
30
|
}
|
|
29
31
|
interface MemoryTranslationCacheOptions {
|
|
30
32
|
readonly maxEntries?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ interface TranslationCacheOptions {
|
|
|
25
25
|
readonly variant?: string;
|
|
26
26
|
readonly buildKey?: (context: TranslationCacheKeyContext) => string;
|
|
27
27
|
readonly onStatsReport?: (stats: TranslationCacheStats) => void;
|
|
28
|
+
readonly cacheErrorPolicy?: "bypass" | "throw";
|
|
29
|
+
readonly onCacheError?: (error: Error, operation: "get" | "set") => void;
|
|
28
30
|
}
|
|
29
31
|
interface MemoryTranslationCacheOptions {
|
|
30
32
|
readonly maxEntries?: number;
|
package/dist/index.js
CHANGED
|
@@ -87,9 +87,38 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
87
87
|
if (options.buildKey !== void 0 && typeof options.buildKey !== "function") {
|
|
88
88
|
throw new TypeError("buildKey must be a function.");
|
|
89
89
|
}
|
|
90
|
+
if (options.cacheErrorPolicy !== void 0 && options.cacheErrorPolicy !== "bypass" && options.cacheErrorPolicy !== "throw") {
|
|
91
|
+
throw new TypeError('cacheErrorPolicy must be "bypass" or "throw".');
|
|
92
|
+
}
|
|
93
|
+
const cacheErrorPolicy = options.cacheErrorPolicy ?? "bypass";
|
|
90
94
|
const initialEvictionCount = cache.evictionCount ?? 0;
|
|
91
95
|
let hits = 0;
|
|
92
96
|
let misses = 0;
|
|
97
|
+
const handleCacheError = (cause, operation) => {
|
|
98
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
99
|
+
try {
|
|
100
|
+
options.onCacheError?.(error, operation);
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
return error;
|
|
104
|
+
};
|
|
105
|
+
const getCached = async (key) => {
|
|
106
|
+
try {
|
|
107
|
+
return await cache.get(key);
|
|
108
|
+
} catch (cause) {
|
|
109
|
+
const error = handleCacheError(cause, "get");
|
|
110
|
+
if (cacheErrorPolicy === "throw") throw error;
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const setCached = async (key, value) => {
|
|
115
|
+
try {
|
|
116
|
+
await cache.set(key, value, options.ttlMs);
|
|
117
|
+
} catch (cause) {
|
|
118
|
+
const error = handleCacheError(cause, "set");
|
|
119
|
+
if (cacheErrorPolicy === "throw") throw error;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
93
122
|
const reportStats = () => {
|
|
94
123
|
const size = cache.size ?? 0;
|
|
95
124
|
options.onStatsReport?.({
|
|
@@ -116,7 +145,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
116
145
|
if (typeof key !== "string" || key.length === 0) throw new TypeError("Translation cache key must not be empty.");
|
|
117
146
|
return key;
|
|
118
147
|
});
|
|
119
|
-
const cached = await Promise.all(keys.map(
|
|
148
|
+
const cached = await Promise.all(keys.map(getCached));
|
|
120
149
|
hits += cached.filter((value) => value !== void 0).length;
|
|
121
150
|
misses += cached.filter((value) => value === void 0).length;
|
|
122
151
|
const missingByKey = /* @__PURE__ */ new Map();
|
|
@@ -143,7 +172,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
|
|
|
143
172
|
missing.map(async ([key, value], translatedIndex) => {
|
|
144
173
|
const translation = translated[translatedIndex];
|
|
145
174
|
if (translation === void 0) throw new Error("Translation adapter result is unavailable.");
|
|
146
|
-
await
|
|
175
|
+
await setCached(key, translation);
|
|
147
176
|
for (const index of value.indices) cached[index] = translation;
|
|
148
177
|
})
|
|
149
178
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/translator-cache",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typescript"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@form-engine-ts/core": "2.
|
|
41
|
+
"@form-engine-ts/core": "2.9.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external @form-engine-ts/core",
|