@form-engine-ts/translator-cache 2.9.0 → 2.9.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/README.md CHANGED
@@ -26,6 +26,8 @@ Keys isolate adapter name, source locale, target locale, and a deterministic UTF
26
26
  are deduplicated, translated once in source order, cached, and restored to their original positions. The built-in memory
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
+ Adapters that expose a locale-aware cache variant (such as `@form-engine-ts/translator-google-v3` with a glossary)
30
+ are isolated automatically; an explicit `variant` is combined with that adapter variant.
29
31
  `onStatsReport` receives cumulative real cache hits, misses, evictions, and current size after successful translations.
30
32
  Cache backend failures default to `cacheErrorPolicy: "bypass"`: `onCacheError` is notified and translation continues
31
33
  through the wrapped adapter. Use `cacheErrorPolicy: "throw"` when cache availability is mandatory.
package/dist/index.cjs CHANGED
@@ -48,6 +48,11 @@ function nonNegativeDuration(value, fallback, name) {
48
48
  }
49
49
  return resolved;
50
50
  }
51
+ function getVariantProvider(adapter) {
52
+ if (typeof adapter !== "object" || adapter === null) return void 0;
53
+ const candidate = adapter;
54
+ return typeof candidate.getCacheVariant === "function" ? { getCacheVariant: candidate.getCacheVariant.bind(adapter) } : void 0;
55
+ }
51
56
  function createMemoryTranslationCache(options = {}) {
52
57
  const maxEntries = options.maxEntries ?? 500;
53
58
  if (!Number.isSafeInteger(maxEntries) || maxEntries < 1) {
@@ -120,6 +125,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
120
125
  const initialEvictionCount = cache.evictionCount ?? 0;
121
126
  let hits = 0;
122
127
  let misses = 0;
128
+ const variantProvider = getVariantProvider(baseAdapter);
123
129
  const handleCacheError = (cause, operation) => {
124
130
  const error = cause instanceof Error ? cause : new Error(String(cause));
125
131
  try {
@@ -160,14 +166,19 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
160
166
  }
161
167
  const target = requireLocale(targetLocale, "targetLocale");
162
168
  const source = sourceLocale === void 0 ? "auto" : requireLocale(sourceLocale, "sourceLocale");
169
+ const automaticVariant = variantProvider?.getCacheVariant(target, sourceLocale);
170
+ if (automaticVariant !== void 0 && automaticVariant.trim().length === 0) {
171
+ throw new TypeError("baseAdapter cache variant must not be empty.");
172
+ }
173
+ const variant = options.variant === void 0 ? automaticVariant : automaticVariant === void 0 ? options.variant : `${options.variant}:${automaticVariant}`;
163
174
  const keys = texts.map((text) => {
164
175
  const context = {
165
176
  sourceText: text,
166
177
  sourceLocale: source,
167
178
  targetLocale: target,
168
- ...options.variant === void 0 ? {} : { variant: options.variant }
179
+ ...variant === void 0 ? {} : { variant }
169
180
  };
170
- const key = options.buildKey?.(context) ?? `${prefix}:${adapterName}:${options.variant === void 0 ? "" : `${options.variant}:`}${source}:${target}:${hashTranslationText(text)}`;
181
+ const key = options.buildKey?.(context) ?? `${prefix}:${adapterName}:${variant === void 0 ? "" : `${variant}:`}${source}:${target}:${hashTranslationText(text)}`;
171
182
  if (typeof key !== "string" || key.length === 0) throw new TypeError("Translation cache key must not be empty.");
172
183
  return key;
173
184
  });
package/dist/index.js CHANGED
@@ -22,6 +22,11 @@ function nonNegativeDuration(value, fallback, name) {
22
22
  }
23
23
  return resolved;
24
24
  }
25
+ function getVariantProvider(adapter) {
26
+ if (typeof adapter !== "object" || adapter === null) return void 0;
27
+ const candidate = adapter;
28
+ return typeof candidate.getCacheVariant === "function" ? { getCacheVariant: candidate.getCacheVariant.bind(adapter) } : void 0;
29
+ }
25
30
  function createMemoryTranslationCache(options = {}) {
26
31
  const maxEntries = options.maxEntries ?? 500;
27
32
  if (!Number.isSafeInteger(maxEntries) || maxEntries < 1) {
@@ -94,6 +99,7 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
94
99
  const initialEvictionCount = cache.evictionCount ?? 0;
95
100
  let hits = 0;
96
101
  let misses = 0;
102
+ const variantProvider = getVariantProvider(baseAdapter);
97
103
  const handleCacheError = (cause, operation) => {
98
104
  const error = cause instanceof Error ? cause : new Error(String(cause));
99
105
  try {
@@ -134,14 +140,19 @@ function withTranslationCache(baseAdapter, cache, options = {}) {
134
140
  }
135
141
  const target = requireLocale(targetLocale, "targetLocale");
136
142
  const source = sourceLocale === void 0 ? "auto" : requireLocale(sourceLocale, "sourceLocale");
143
+ const automaticVariant = variantProvider?.getCacheVariant(target, sourceLocale);
144
+ if (automaticVariant !== void 0 && automaticVariant.trim().length === 0) {
145
+ throw new TypeError("baseAdapter cache variant must not be empty.");
146
+ }
147
+ const variant = options.variant === void 0 ? automaticVariant : automaticVariant === void 0 ? options.variant : `${options.variant}:${automaticVariant}`;
137
148
  const keys = texts.map((text) => {
138
149
  const context = {
139
150
  sourceText: text,
140
151
  sourceLocale: source,
141
152
  targetLocale: target,
142
- ...options.variant === void 0 ? {} : { variant: options.variant }
153
+ ...variant === void 0 ? {} : { variant }
143
154
  };
144
- const key = options.buildKey?.(context) ?? `${prefix}:${adapterName}:${options.variant === void 0 ? "" : `${options.variant}:`}${source}:${target}:${hashTranslationText(text)}`;
155
+ const key = options.buildKey?.(context) ?? `${prefix}:${adapterName}:${variant === void 0 ? "" : `${variant}:`}${source}:${target}:${hashTranslationText(text)}`;
145
156
  if (typeof key !== "string" || key.length === 0) throw new TypeError("Translation cache key must not be empty.");
146
157
  return key;
147
158
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@form-engine-ts/translator-cache",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
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.9.0"
41
+ "@form-engine-ts/core": "2.9.2"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup src/index.ts --format esm,cjs --dts --clean --external @form-engine-ts/core",