@belocal/js-sdk 1.0.1 → 1.0.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/README.md CHANGED
@@ -10,24 +10,80 @@ npm i @belocal/js-sdk
10
10
 
11
11
  ## Usage
12
12
 
13
+ ### Initialization
14
+
13
15
  ```javascript
14
16
  import { BelocalEngine } from '@belocal/js-sdk';
15
17
 
16
18
  const engine = new BelocalEngine({ apiKey: 'your-api-key' });
19
+ ```
17
20
 
18
- // Single translation
19
- const text = await engine.t('Hello world', 'es');
21
+ ### translate
20
22
 
21
- // With context
22
- const text2 = await engine.t('Hello world', 'es', 'en', 'homepage greeting');
23
+ ```javascript
24
+ const text = await engine.translate('Hello world', 'es');
25
+ ```
23
26
 
24
- // Managed translation (cache_type: 'managed')
25
- const text3 = await engine.t('Hello world', 'es', undefined, undefined, true);
27
+ ### translateMany
26
28
 
27
- // Batch translation
29
+ ```javascript
28
30
  const texts = await engine.translateMany(['Hello', 'World'], 'es');
29
31
  ```
30
32
 
33
+ ### All options
34
+
35
+ ```javascript
36
+ const text = await engine.translate('crane', 'ru', {
37
+ source_lang: 'en',
38
+ context: 'website dedicated to animals',
39
+ managed: true,
40
+ ctx: {
41
+ user_type: 'product',
42
+ entity_key: 'birds',
43
+ entity_id: 'crane-001'
44
+ }
45
+ });
46
+ ```
47
+
48
+ ## API Reference
49
+
50
+ ### translate(text, lang, options?)
51
+
52
+ Translates a single text string.
53
+
54
+ | Param | Type | Description |
55
+ |-------|------|-------------|
56
+ | text | string | Text to translate |
57
+ | lang | string | Target language code |
58
+ | options | [TranslateOptions](#translateoptions) | Optional translation options |
59
+
60
+ ### translateMany(texts, lang, options?)
61
+
62
+ Translates multiple texts in a single batch.
63
+
64
+ | Param | Type | Description |
65
+ |-------|------|-------------|
66
+ | texts | string[] | Texts to translate |
67
+ | lang | string | Target language code |
68
+ | options | [TranslateOptions](#translateoptions) | Optional translation options |
69
+
70
+ ### TranslateOptions
71
+
72
+ | Property | Type | Description |
73
+ |----------|------|-------------|
74
+ | source_lang | string | Source language of the text |
75
+ | context | string | Context for better understanding of what is being translated |
76
+ | managed | boolean | Use managed translations cache (available on the website in Managed Translations section) |
77
+ | ctx | object | User context, see [ctx properties](#ctx-properties) below |
78
+
79
+ #### ctx properties
80
+
81
+ | Property | Description |
82
+ |----------|-------------|
83
+ | user_type | `product` or `chat`. Correct type improves translation quality |
84
+ | entity_key | Used together with entity_id. When passed with the same values, a shared context is always used |
85
+ | entity_id | Used together with entity_key. When passed with the same values, a shared context is always used |
86
+
31
87
  ## Options
32
88
 
33
89
  ```javascript
@@ -41,7 +97,7 @@ const engine = new BelocalEngine({
41
97
 
42
98
  ### batchWindowMs
43
99
 
44
- The SDK batches multiple `translate()` / `t()` calls made within a time window into a single HTTP request. When you call `t()` or `translate()`, the request is not sent immediately — instead it is queued. After `batchWindowMs` milliseconds of inactivity, all queued texts are grouped by target language and sent as one batch request to `/v1/translate/multi`. This reduces the number of HTTP round-trips when translating many strings at once (e.g. rendering a page). Default is `50`ms.
100
+ The SDK batches multiple `translate()` calls made within a time window into a single HTTP request. When you call `translate()`, the request is not sent immediately — instead it is queued. After `batchWindowMs` milliseconds of inactivity, all queued texts are grouped by target language and sent as one batch request to `/v1/translate/multi`. This reduces the number of HTTP round-trips when translating many strings at once (e.g. rendering a page). Default is `50`ms.
45
101
 
46
102
  ## TypeScript
47
103
 
@@ -50,7 +106,8 @@ import {
50
106
  BelocalEngine,
51
107
  type BelocalEngineOptions,
52
108
  type Lang,
53
- type TranslationCtx,
109
+ type TranslateOptions,
110
+ type UserCtx,
54
111
  USER_TYPE_PRODUCT,
55
112
  USER_TYPE_CHAT
56
113
  } from '@belocal/js-sdk';
package/dist/browser.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var jsMd5=require('js-md5');var x="1.0.1";function _(i,t){let s=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(s);if(typeof e=="object"){let o={};for(let c of Object.keys(e).sort())o[c]=s(e[c]);return o}return e},r=JSON.stringify(s(t));return `${i}:${r}`}var m=class{constructor(t,s){this.wrappedTransport=t;this.debug=s;this.inFlightRequests=new Map;}async post(t,s){let r=_(s,t),e=this.inFlightRequests.get(r);if(e)return this.debug&&console.log(`[DedupeTransport] Deduplicating request to ${s}`),e;let o=this.wrappedTransport.post(t,s).finally(()=>{this.inFlightRequests.delete(r);});return this.inFlightRequests.set(r,o),this.debug&&console.log(`[DedupeTransport] New request to ${s} (${this.inFlightRequests.size} in-flight)`),o}};var q="https://dynamic.belocal.dev",f=class{constructor(t){this.config=t;}async post(t,s){let r=`${q}${s}`,e=new AbortController,o=this.config.timeoutMs??1e4,c=setTimeout(()=>e.abort(),o);this.config.debug&&console.log(`[Base Browser Transport] POST request to ${r}`,t);try{let u=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-sdk":"js","x-sdk-version":x,...this.config.headers},body:JSON.stringify(t),signal:e.signal});if(!u.ok){let a=`HTTP ${u.status}: ${u.statusText}`;throw this.config.debug&&console.error("[Base Browser Transport] Request failed:",a),new Error(a)}let n=await u.json();return this.config.debug&&console.log("[Base Browser Transport] Request successful:",n),n}finally{c&&clearTimeout(c);}}};function h(i){let t=new f(i);return new m(t,i.debug)}function S(i,t,s,r){let e=[...i].sort(),o=r&&Object.keys(r).length>0?Object.fromEntries(Object.entries(r).sort(([u],[n])=>u.localeCompare(n))):null;return jsMd5.md5(JSON.stringify([e,t,s||null,o]))}async function K(i,t,s){i.debug&&console.log(`[BeLocal Multi Transport] Sending multi request with ${t.length} texts`);try{let r=new Map;t.forEach(n=>{let a=JSON.stringify({lang:n.lang,sourceLang:n.sourceLang||null,context:n.context||null});r.has(a)||r.set(a,[]),r.get(a).push(n);});let e=new Map,o=Array.from(r.entries()).map(([n,a])=>{let l=a[0],p=a.map(d=>d.text),g=S(p,l.lang,l.sourceLang,l.context);return e.set(g,a),{request_id:g,texts:p,lang:l.lang,source_lang:l.sourceLang,ctx:l.context}}),c=await i.baseTransport.post({requests:o},"/v1/translate/multi");i.debug&&console.log(`[BeLocal Multi Transport] Multi response received with ${c.results.length} groups`);let u=new Map;c.results.forEach(n=>{u.set(n.request_id,{texts:n.data.texts,status:n.data.status});}),e.forEach((n,a)=>{let l=u.get(a);if(!l){i.debug&&console.error(`[BeLocal Multi Transport] No result found for request_id: ${a}`),n.forEach(p=>{p.reject(new Error(`No result found for request ${a}`));});return}if(l.texts.length!==n.length){let p=new Error(`Mismatch: expected ${n.length} texts, got ${l.texts.length} for request_id ${a}`);i.debug&&console.error("[BeLocal Multi Transport]",p.message),n.forEach(g=>g.reject(p));return}n.forEach((p,g)=>{let d=l.texts[g],R=l.status||"success";i.debug&&console.log(`[BeLocal Multi Transport] Success for request_id ${a}[${g}]: "${d}"`),p.resolve({text:d,status:R});});});}catch(r){i.debug&&console.error("[BeLocal Multi Transport] Multi request error:",r);let e=r instanceof Error?r:new Error(String(r));t.forEach(o=>o.reject(e));}}function B(i,t){if(t.currentMulti.length===0||t.isRequestInFlight)return;let s=[...t.currentMulti];t.currentMulti=[],t.multiTimer=null,t.isRequestInFlight=true,K(i,s).finally(()=>{if(t.isRequestInFlight=false,t.currentMulti.length>0){let r=i.batchWindowMs??50;t.multiTimer=setTimeout(()=>B(i,t),r);}});}function M(i){let t=i.batchWindowMs??50,s={currentMulti:[],multiTimer:null,isRequestInFlight:false};return ({text:r,lang:e,source_lang:o,ctx:c})=>new Promise((u,n)=>{if(i.debug){let l=jsMd5.md5(JSON.stringify([r,e,o||null,c||null]));console.log(`[BeLocal Multi Transport] Queuing request ${l}: "${r}" to ${e}`);}let a={text:r,lang:e,sourceLang:o,context:c,resolve:u,reject:n};s.currentMulti.push(a),s.multiTimer===null&&!s.isRequestInFlight&&(s.multiTimer=setTimeout(()=>B(i,s),t));})}var T=class{constructor(){this.storage=new Map;}get(t){return this.storage.get(t)||null}set(t,s){this.storage.set(t,s);}};var y=class{constructor(t,s){let{apiKey:r,batchWindowMs:e=50,timeoutMs:o=1e4,debug:c=false}=t;this.debug=c,this.cache=new T;let u={Authorization:`Bearer ${r}`},n=s({headers:u,timeoutMs:o,debug:this.debug});this.transport=M({baseTransport:n,debug:this.debug,batchWindowMs:e}),this.debug&&console.log("[BeLocal Engine] Multi transport created with config:",{baseUrl:"https://dynamic.belocal.dev",timeoutMs:o,batchWindowMs:e});}async translate(t,s,r,e){return (await this.translateMany([t],s,r,e))[0]}async translateMany(t,s,r,e){let o=new Array(t.length),c=[];for(let u=0;u<t.length;u++){let n=t[u],a=this.generateCacheKey(n,s,r,e),l=this.cache.get(a);if(l){o[u]=l,this.debug&&console.log("[BeLocal Engine] Translation from cache:",n);continue}o[u]=null,c.push({index:u,text:n});}return c.length>0&&(await Promise.all(c.map(async({index:n,text:a})=>{let l=await this.transport({text:a,lang:s,source_lang:r,ctx:e});if(l.status!=="error"){let p=this.generateCacheKey(a,s,r,e);this.cache.set(p,l.text),this.debug&&console.log("[BeLocal Engine] Translation from API, cached:",a);}else this.debug&&console.log("[BeLocal Engine] Translation from API (not cached due to error status):",a);return {index:n,translation:l.text}}))).forEach(({index:n,translation:a})=>{o[n]=a;}),o}async t(t,s,r,e,o=false){let c=e||o?{...e?{user_ctx:e}:{},...o?{cache_type:"managed"}:{}}:void 0;return this.translate(t,s,r,c)}generateCacheKey(t,s,r,e){let o=e?Object.fromEntries(Object.entries(e).sort(([u],[n])=>u.localeCompare(n))):null;return jsMd5.md5(JSON.stringify({text:t,lang:s,source_lang:r||null,ctx:o}))}};var O="product",L="chat";var w=class extends y{constructor(t){super(t,h);}};
2
- exports.BaseBrowserTransport=f;exports.BelocalEngine=w;exports.USER_TYPE_CHAT=L;exports.USER_TYPE_PRODUCT=O;exports.createBaseBrowserTransport=h;exports.createMultiTransport=M;//# sourceMappingURL=browser.cjs.map
1
+ 'use strict';var jsMd5=require('js-md5');var M="1.0.3";function E(a,t){let e=s=>{if(s==null)return s;if(Array.isArray(s))return s.map(e);if(typeof s=="object"){let i={};for(let u of Object.keys(s).sort())i[u]=e(s[u]);return i}return s},r=JSON.stringify(e(t));return `${a}:${r}`}var m=class{constructor(t,e){this.wrappedTransport=t;this.debug=e;this.inFlightRequests=new Map;}async post(t,e){let r=E(e,t),s=this.inFlightRequests.get(r);if(s)return this.debug&&console.log(`[DedupeTransport] Deduplicating request to ${e}`),s;let i=this.wrappedTransport.post(t,e).finally(()=>{this.inFlightRequests.delete(r);});return this.inFlightRequests.set(r,i),this.debug&&console.log(`[DedupeTransport] New request to ${e} (${this.inFlightRequests.size} in-flight)`),i}};var R="https://dynamic.belocal.dev",d=class{constructor(t){this.config=t;}async post(t,e){let r=`${R}${e}`,s=new AbortController,i=this.config.timeoutMs??1e4,u=setTimeout(()=>s.abort(),i);this.config.debug&&console.log(`[Base Browser Transport] POST request to ${r}`,t);try{let g=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-sdk":"js","x-sdk-version":M,...this.config.headers},body:JSON.stringify(t),signal:s.signal});if(!g.ok){let o=`HTTP ${g.status}: ${g.statusText}`;throw this.config.debug&&console.error("[Base Browser Transport] Request failed:",o),new Error(o)}let n=await g.json();return this.config.debug&&console.log("[Base Browser Transport] Request successful:",n),n}finally{u&&clearTimeout(u);}}};function h(a){let t=new d(a);return new m(t,a.debug)}function q(a,t,e,r){let s=[...a].sort(),i=r&&Object.keys(r).length>0?Object.fromEntries(Object.entries(r).sort(([g],[n])=>g.localeCompare(n))):null;return jsMd5.md5(JSON.stringify([s,t,e||null,i]))}async function S(a,t,e){a.debug&&console.log(`[BeLocal Multi Transport] Sending multi request with ${t.length} texts`);try{let r=new Map;t.forEach(n=>{let o=JSON.stringify({lang:n.lang,sourceLang:n.sourceLang||null,context:n.context||null});r.has(o)||r.set(o,[]),r.get(o).push(n);});let s=new Map,i=Array.from(r.entries()).map(([n,o])=>{let c=o[0],l=o.map(f=>f.text),p=q(l,c.lang,c.sourceLang,c.context);return s.set(p,o),{request_id:p,texts:l,lang:c.lang,source_lang:c.sourceLang,ctx:c.context}}),u=await a.baseTransport.post({requests:i},"/v1/translate/multi");a.debug&&console.log(`[BeLocal Multi Transport] Multi response received with ${u.results.length} groups`);let g=new Map;u.results.forEach(n=>{g.set(n.request_id,{texts:n.data.texts,status:n.data.status});}),s.forEach((n,o)=>{let c=g.get(o);if(!c){a.debug&&console.error(`[BeLocal Multi Transport] No result found for request_id: ${o}`),n.forEach(l=>{l.reject(new Error(`No result found for request ${o}`));});return}if(c.texts.length!==n.length){let l=new Error(`Mismatch: expected ${n.length} texts, got ${c.texts.length} for request_id ${o}`);a.debug&&console.error("[BeLocal Multi Transport]",l.message),n.forEach(p=>p.reject(l));return}n.forEach((l,p)=>{let f=c.texts[p],_=c.status||"success";a.debug&&console.log(`[BeLocal Multi Transport] Success for request_id ${o}[${p}]: "${f}"`),l.resolve({text:f,status:_});});});}catch(r){a.debug&&console.error("[BeLocal Multi Transport] Multi request error:",r);let s=r instanceof Error?r:new Error(String(r));t.forEach(i=>i.reject(s));}}function B(a,t){if(t.currentMulti.length===0||t.isRequestInFlight)return;let e=[...t.currentMulti];t.currentMulti=[],t.multiTimer=null,t.isRequestInFlight=true,S(a,e).finally(()=>{if(t.isRequestInFlight=false,t.currentMulti.length>0){let r=a.batchWindowMs??50;t.multiTimer=setTimeout(()=>B(a,t),r);}});}function x(a){let t=a.batchWindowMs??50,e={currentMulti:[],multiTimer:null,isRequestInFlight:false},r=(({text:s,lang:i,source_lang:u,ctx:g})=>new Promise((n,o)=>{if(a.debug){let l=jsMd5.md5(JSON.stringify([s,i,u||null,g||null]));console.log(`[BeLocal Multi Transport] Queuing request ${l}: "${s}" to ${i}`);}let c={text:s,lang:i,sourceLang:u,context:g,resolve:n,reject:o};e.currentMulti.push(c),e.multiTimer===null&&!e.isRequestInFlight&&(e.multiTimer=setTimeout(()=>B(a,e),t));}));return r.destroy=()=>{e.multiTimer&&(clearTimeout(e.multiTimer),e.multiTimer=null),e.currentMulti.forEach(s=>s.reject(new Error("Transport destroyed"))),e.currentMulti=[];},r}var T=class{constructor(t={}){this.storage=new Map;this.maxSize=t.maxSize??1e4,this.ttlMs=t.ttlMs??36e5;}get(t){let e=this.storage.get(t);return e===void 0?null:Date.now()>e.expiresAt?(this.storage.delete(t),null):(this.storage.delete(t),this.storage.set(t,e),e.value)}set(t,e){if(this.storage.delete(t),this.storage.size>=this.maxSize){let r=this.storage.keys().next().value;r!==void 0&&this.storage.delete(r);}this.storage.set(t,{value:e,expiresAt:Date.now()+this.ttlMs});}clear(){this.storage.clear();}};var y=class{constructor(t,e){let{apiKey:r,batchWindowMs:s=50,timeoutMs:i=1e4,debug:u=false,cacheTtlMs:g=36e5,cacheMaxSize:n=1e4}=t;if(!r||typeof r!="string")throw new Error("[BeLocal] apiKey is required and must be a non-empty string");if(typeof i!="number"||!Number.isFinite(i)||i<=0)throw new Error("[BeLocal] timeoutMs must be a positive finite number");let o=Math.max(0,s);this.debug=u,this.cache=new T({ttlMs:g,maxSize:n});let c={Authorization:`Bearer ${r}`},l=e({headers:c,timeoutMs:i,debug:this.debug});this.transport=x({baseTransport:l,debug:this.debug,batchWindowMs:o}),this.debug&&console.log("[BeLocal Engine] Multi transport created with config:",{baseUrl:"https://dynamic.belocal.dev",timeoutMs:i,batchWindowMs:o});}async translate(t,e,r){return (await this.translateMany([t],e,r))[0]}async translateMany(t,e,r){let{source_lang:s,ctx:i}=this.resolveOptions(r),u=new Array(t.length),g=[];for(let n=0;n<t.length;n++){let o=t[n],c=this.generateCacheKey(o,e,s,i),l=this.cache.get(c);if(l!==null){u[n]=l,this.debug&&console.log("[BeLocal Engine] Translation from cache:",o);continue}u[n]=null,g.push({index:n,text:o});}return g.length>0&&(await Promise.allSettled(g.map(async({index:o,text:c})=>{let l=await this.transport({text:c,lang:e,source_lang:s,ctx:i});if(l.status!=="error"){let p=this.generateCacheKey(c,e,s,i);this.cache.set(p,l.text),this.debug&&console.log("[BeLocal Engine] Translation from API, cached:",c);}else this.debug&&console.log("[BeLocal Engine] Translation from API (not cached due to error status):",c);return {index:o,translation:l.text}}))).forEach((o,c)=>{let{index:l,text:p}=g[c];if(o.status==="fulfilled")u[l]=o.value.translation;else if(u[l]=p,this.debug){let f=o.reason;console.error("[BeLocal Engine] Translation failed, using original text:",p,f instanceof Error?f.message:String(f));}}),u}resolveOptions(t){if(!t)return {};let e={...t.ctx,...t.context&&{user_ctx:t.context},...t.managed&&{cache_type:"managed"}},r=Object.values(e).some(Boolean)?e:void 0;return {source_lang:t.source_lang,ctx:r}}destroy(){this.transport.destroy?.(),this.cache.clear();}generateCacheKey(t,e,r,s){let i=s?Object.fromEntries(Object.entries(s).sort(([g],[n])=>g.localeCompare(n))):null;return jsMd5.md5(JSON.stringify({text:t,lang:e,source_lang:r||null,ctx:i}))}};var v="product",L="chat";var w=class extends y{constructor(t){super(t,h);}};
2
+ exports.BaseBrowserTransport=d;exports.BelocalEngine=w;exports.USER_TYPE_CHAT=L;exports.USER_TYPE_PRODUCT=v;exports.createBaseBrowserTransport=h;exports.createMultiTransport=x;//# sourceMappingURL=browser.cjs.map
3
3
  //# sourceMappingURL=browser.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/transports/base/dedupe.ts","../src/transports/base/browser.ts","../src/transports/multi.ts","../src/cache/local.ts","../src/core/engine/engine.ts","../src/core/types.ts","../src/core/engine/browser.ts"],"names":["SDK_VERSION","generateRequestKey","endpointPath","data","normalize","value","sorted","key","normalizedData","DedupeTransport","wrappedTransport","debug","requestKey","existingRequest","requestPromise","BASE_URL","BaseBrowserTransport","config","url","controller","timeoutMs","timeoutId","response","errorMsg","result","createBaseBrowserTransport","transport","generateRequestId","texts","lang","sourceLang","context","sortedTexts","sortedContext","a","b","md5","sendMulti","items","state","groups","item","groupKey","requestIdToGroupItems","requests","groupItems","firstItem","requestId","multiResponse","resultMap","error","index","translatedText","status","errorToReject","processMulti","itemsToSend","windowMs","createMultiTransport","text","source_lang","ctx","resolve","reject","tempRequestId","requestItem","LocalCache","BelocalEngine","options","baseTransportFactory","apiKey","batchWindowMs","authHeaders","baseTransport","results","cacheMisses","i","cacheKey","cachedResult","translation","managed","sortedCtx","USER_TYPE_PRODUCT","USER_TYPE_CHAT"],"mappings":"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","file":"browser.cjs","sourcesContent":["declare const __SDK_VERSION__: string;\nexport const SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : 'undefined';\nexport const SDK_NAME = 'js';\n","import type { BaseTransport } from '../../core/types';\n\nfunction generateRequestKey(endpointPath: string, data: any): string {\n const normalize = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(normalize);\n }\n if (typeof value === 'object') {\n const sorted: Record<string, any> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = normalize(value[key]);\n }\n return sorted;\n }\n return value;\n };\n\n const normalizedData = JSON.stringify(normalize(data));\n return `${endpointPath}:${normalizedData}`;\n}\n\n/** Deduplicates identical in-flight requests so they share a single HTTP call. */\nexport class DedupeTransport implements BaseTransport {\n private inFlightRequests = new Map<string, Promise<any>>();\n\n constructor(\n private wrappedTransport: BaseTransport,\n private debug?: boolean\n ) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const requestKey = generateRequestKey(endpointPath, data);\n\n const existingRequest = this.inFlightRequests.get(requestKey);\n if (existingRequest) {\n if (this.debug) {\n console.log(`[DedupeTransport] Deduplicating request to ${endpointPath}`);\n }\n return existingRequest;\n }\n\n const requestPromise = this.wrappedTransport.post(data, endpointPath)\n .finally(() => {\n this.inFlightRequests.delete(requestKey);\n });\n\n this.inFlightRequests.set(requestKey, requestPromise);\n\n if (this.debug) {\n console.log(`[DedupeTransport] New request to ${endpointPath} (${this.inFlightRequests.size} in-flight)`);\n }\n\n return requestPromise;\n }\n}\n","import type { BaseTransport } from '../../core/types';\nimport { SDK_NAME, SDK_VERSION } from '../../version';\nimport { DedupeTransport } from './dedupe';\n\nconst BASE_URL = 'https://dynamic.belocal.dev';\n\nexport interface BaseBrowserTransportConfig {\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport class BaseBrowserTransport implements BaseTransport {\n constructor(private config: BaseBrowserTransportConfig) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const url = `${BASE_URL}${endpointPath}`;\n const controller = new AbortController();\n const timeoutMs = this.config.timeoutMs ?? 10000;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (this.config.debug) {\n console.log(`[Base Browser Transport] POST request to ${url}`, data);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-sdk': SDK_NAME,\n 'x-sdk-version': SDK_VERSION,\n ...this.config.headers,\n },\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (this.config.debug) {\n console.error(`[Base Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (this.config.debug) {\n console.log(`[Base Browser Transport] Request successful:`, result);\n }\n \n return result;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n}\n\nexport function createBaseBrowserTransport(config: BaseBrowserTransportConfig): BaseTransport {\n const transport = new BaseBrowserTransport(config);\n return new DedupeTransport(transport, config.debug);\n}\n","import type { Transport, BaseTransport, KV } from '../core/types';\nimport { md5 } from 'js-md5';\n\nexport interface MultiTransportConfig {\n baseTransport: BaseTransport;\n debug?: boolean;\n batchWindowMs?: number;\n}\n\ninterface MultiRequest {\n request_id: string;\n texts: string[];\n lang: string;\n source_lang?: string;\n ctx?: KV;\n}\n\ninterface MultiRequestItem {\n text: string;\n lang: string;\n sourceLang?: string;\n context?: KV;\n resolve: (value: { text: string; status: string }) => void;\n reject: (error: Error) => void;\n}\n\ninterface MultiResponse {\n results: Array<{\n request_id: string;\n data: { texts: string[]; status: string };\n }>;\n}\n\ninterface MultiState {\n currentMulti: MultiRequestItem[];\n multiTimer: ReturnType<typeof setTimeout> | null;\n isRequestInFlight: boolean;\n}\n\nfunction generateRequestId(texts: string[], lang: string, sourceLang?: string, context?: KV): string {\n const sortedTexts = [...texts].sort();\n\n const sortedContext = context && Object.keys(context).length > 0\n ? Object.fromEntries(Object.entries(context).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = [sortedTexts, lang, sourceLang || null, sortedContext];\n return md5(JSON.stringify(data));\n}\n\nasync function sendMulti(\n config: MultiTransportConfig,\n items: MultiRequestItem[],\n state: MultiState\n): Promise<void> {\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Sending multi request with ${items.length} texts`);\n }\n\n try {\n const groups = new Map<string, MultiRequestItem[]>();\n\n items.forEach(item => {\n const groupKey = JSON.stringify({\n lang: item.lang,\n sourceLang: item.sourceLang || null,\n context: item.context || null\n });\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(item);\n });\n\n const requestIdToGroupItems = new Map<string, MultiRequestItem[]>();\n const requests: MultiRequest[] = Array.from(groups.entries()).map(([groupKey, groupItems]) => {\n const firstItem = groupItems[0];\n const texts = groupItems.map(item => item.text);\n\n const requestId = generateRequestId(\n texts,\n firstItem.lang,\n firstItem.sourceLang,\n firstItem.context\n );\n\n requestIdToGroupItems.set(requestId, groupItems);\n\n return {\n request_id: requestId,\n texts,\n lang: firstItem.lang,\n source_lang: firstItem.sourceLang,\n ctx: firstItem.context\n };\n });\n\n const multiResponse: MultiResponse = await config.baseTransport.post({ requests }, '/v1/translate/multi');\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Multi response received with ${multiResponse.results.length} groups`);\n }\n\n const resultMap = new Map<string, { texts: string[]; status: string }>();\n multiResponse.results.forEach(result => {\n resultMap.set(result.request_id, { texts: result.data.texts, status: result.data.status });\n });\n\n requestIdToGroupItems.forEach((groupItems, requestId) => {\n const result = resultMap.get(requestId);\n\n if (!result) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] No result found for request_id: ${requestId}`);\n }\n groupItems.forEach(item => {\n item.reject(new Error(`No result found for request ${requestId}`));\n });\n return;\n }\n\n if (result.texts.length !== groupItems.length) {\n const error = new Error(`Mismatch: expected ${groupItems.length} texts, got ${result.texts.length} for request_id ${requestId}`);\n if (config.debug) {\n console.error(`[BeLocal Multi Transport]`, error.message);\n }\n groupItems.forEach(item => item.reject(error));\n return;\n }\n\n groupItems.forEach((item, index) => {\n const translatedText = result.texts[index];\n const status = result.status || 'success';\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Success for request_id ${requestId}[${index}]: \"${translatedText}\"`);\n }\n\n item.resolve({ text: translatedText, status });\n });\n });\n } catch (error) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] Multi request error:`, error);\n }\n\n const errorToReject = error instanceof Error ? error : new Error(String(error));\n items.forEach(item => item.reject(errorToReject));\n }\n}\n\nfunction processMulti(config: MultiTransportConfig, state: MultiState): void {\n if (state.currentMulti.length === 0 || state.isRequestInFlight) {\n return;\n }\n\n const itemsToSend = [...state.currentMulti];\n state.currentMulti = [];\n state.multiTimer = null;\n state.isRequestInFlight = true;\n\n sendMulti(config, itemsToSend, state).finally(() => {\n state.isRequestInFlight = false;\n\n if (state.currentMulti.length > 0) {\n const windowMs = config.batchWindowMs ?? 50;\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n}\n\nexport function createMultiTransport(config: MultiTransportConfig): Transport {\n const windowMs = config.batchWindowMs ?? 50;\n\n const state: MultiState = {\n currentMulti: [],\n multiTimer: null,\n isRequestInFlight: false,\n };\n\n return ({ text, lang, source_lang, ctx }) => {\n return new Promise<{ text: string; status: string }>((resolve, reject) => {\n if (config.debug) {\n const tempRequestId = md5(JSON.stringify([text, lang, source_lang || null, ctx || null]));\n console.log(`[BeLocal Multi Transport] Queuing request ${tempRequestId}: \"${text}\" to ${lang}`);\n }\n\n const requestItem: MultiRequestItem = {\n text,\n lang,\n sourceLang: source_lang,\n context: ctx,\n resolve,\n reject,\n };\n\n state.currentMulti.push(requestItem);\n\n if (state.multiTimer === null && !state.isRequestInFlight) {\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n };\n}\n","import type { Cache } from './types';\n\nexport class LocalCache implements Cache {\n private storage = new Map<string, string>();\n\n get(key: string): string | null {\n return this.storage.get(key) || null;\n }\n\n set(key: string, value: string): void {\n this.storage.set(key, value);\n }\n}\n","import type { BelocalEngineOptions, KV, Lang, Transport, BaseTransport } from '../types';\nimport { createMultiTransport } from '../../transports/multi';\nimport { LocalCache } from '../../cache/local';\nimport type { Cache } from '../../cache/types';\nimport { md5 } from 'js-md5';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n private cache: Cache;\n\n constructor(options: BelocalEngineOptions, baseTransportFactory: (opts: any) => BaseTransport) {\n const {\n apiKey,\n batchWindowMs = 50,\n timeoutMs = 10000,\n debug = false\n } = options;\n\n this.debug = debug;\n this.cache = new LocalCache();\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`\n };\n\n const baseTransport = baseTransportFactory({\n headers: authHeaders,\n timeoutMs,\n debug: this.debug\n });\n\n this.transport = createMultiTransport({\n baseTransport,\n debug: this.debug,\n batchWindowMs\n });\n\n if (this.debug) {\n console.log('[BeLocal Engine] Multi transport created with config:', {\n baseUrl: 'https://dynamic.belocal.dev',\n timeoutMs,\n batchWindowMs\n });\n }\n }\n\n /** Translates a single text string to the target language. */\n async translate(text: string, lang: Lang, source_lang?: string, ctx?: KV): Promise<string> {\n const results = await this.translateMany([text], lang, source_lang, ctx);\n return results[0];\n }\n\n /** Translates multiple text strings to the target language in a single batch. */\n async translateMany(texts: string[], lang: Lang, source_lang?: string, ctx?: KV): Promise<string[]> {\n const results: (string | null)[] = new Array(texts.length);\n const cacheMisses: Array<{ index: number; text: string }> = [];\n\n for (let i = 0; i < texts.length; i++) {\n const text = texts[i];\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n\n const cachedResult = this.cache.get(cacheKey);\n if (cachedResult) {\n results[i] = cachedResult;\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from cache:', text);\n }\n continue;\n }\n\n results[i] = null;\n cacheMisses.push({ index: i, text });\n }\n\n if (cacheMisses.length > 0) {\n const translations = await Promise.all(\n cacheMisses.map(async ({ index, text }) => {\n const result = await this.transport({ text, lang, source_lang, ctx });\n\n if (result.status !== 'error') {\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n this.cache.set(cacheKey, result.text);\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API, cached:', text);\n }\n } else {\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API (not cached due to error status):', text);\n }\n }\n\n return { index, translation: result.text };\n })\n );\n\n translations.forEach(({ index, translation }) => {\n results[index] = translation;\n });\n }\n\n return results as string[];\n }\n\n /** Shortcut for translate() */\n async t(text: string, lang: Lang, source_lang?: string, context?: string, managed = false): Promise<string> {\n const ctx: KV | undefined = (context || managed)\n ? { ...(context ? { user_ctx: context } : {}), ...(managed ? { cache_type: 'managed' } : {}) }\n : undefined;\n return this.translate(text, lang, source_lang, ctx);\n }\n\n private generateCacheKey(text: string, lang: Lang, source_lang?: string, ctx?: KV): string {\n const sortedCtx = ctx\n ? Object.fromEntries(Object.entries(ctx).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = {\n text,\n lang,\n source_lang: source_lang || null,\n ctx: sortedCtx\n };\n return md5(JSON.stringify(data));\n }\n}\n","export type Lang = string;\n\nexport type TranslationCtx = {\n user_type?: string;\n user_ctx?: string;\n cache_type?: string;\n entity_key?: string;\n entity_id?: string;\n}\n\nexport const USER_TYPE_PRODUCT = 'product';\nexport const USER_TYPE_CHAT = 'chat';\n\nexport type KV = TranslationCtx;\n\nexport interface BaseTransport {\n post(data: any, endpointPath: string): Promise<any>;\n}\n\nexport type Transport = (params: { text: string; lang: Lang; source_lang?: string; ctx?: KV }) => Promise<{ text: string; status: string }>;\n\nexport interface BelocalEngineOptions {\n apiKey: string;\n batchWindowMs?: number;\n timeoutMs?: number;\n debug?: boolean;\n}\n","import type { BelocalEngineOptions } from '../types';\nimport { createBaseBrowserTransport } from '../../transports/base/browser';\nimport { BelocalEngine as BaseEngine } from './engine';\n\nexport class BelocalEngine extends BaseEngine {\n constructor(options: BelocalEngineOptions) {\n super(options, createBaseBrowserTransport);\n }\n}\n\nexport type { BelocalEngineOptions, Lang, KV, BaseTransport, TranslationCtx } from '../types';\nexport { USER_TYPE_PRODUCT, USER_TYPE_CHAT } from '../types';\nexport { createMultiTransport } from '../../transports/multi';\nexport { BaseBrowserTransport, createBaseBrowserTransport } from '../../transports/base';\n"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/transports/base/dedupe.ts","../src/transports/base/browser.ts","../src/transports/multi.ts","../src/cache/local.ts","../src/core/engine/engine.ts","../src/core/types.ts","../src/core/engine/browser.ts"],"names":["SDK_VERSION","generateRequestKey","endpointPath","data","normalize","value","sorted","key","normalizedData","DedupeTransport","wrappedTransport","debug","requestKey","existingRequest","requestPromise","BASE_URL","BaseBrowserTransport","config","url","controller","timeoutMs","timeoutId","response","errorMsg","result","createBaseBrowserTransport","transport","generateRequestId","texts","lang","sourceLang","context","sortedTexts","sortedContext","a","b","md5","sendMulti","items","state","groups","item","groupKey","requestIdToGroupItems","requests","groupItems","firstItem","requestId","multiResponse","resultMap","error","index","translatedText","status","errorToReject","processMulti","itemsToSend","windowMs","createMultiTransport","text","source_lang","ctx","resolve","reject","tempRequestId","requestItem","LocalCache","options","entry","oldestKey","BelocalEngine","baseTransportFactory","apiKey","batchWindowMs","cacheTtlMs","cacheMaxSize","safeBatchWindowMs","authHeaders","baseTransport","results","cacheMisses","i","cacheKey","cachedResult","settlement","reason","serverCtx","sortedCtx","USER_TYPE_PRODUCT","USER_TYPE_CHAT"],"mappings":"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","file":"browser.cjs","sourcesContent":["declare const __SDK_VERSION__: string;\nexport const SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : 'undefined';\nexport const SDK_NAME = 'js';\n","import type { BaseTransport } from '../../core/types';\n\nfunction generateRequestKey(endpointPath: string, data: any): string {\n const normalize = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(normalize);\n }\n if (typeof value === 'object') {\n const sorted: Record<string, any> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = normalize(value[key]);\n }\n return sorted;\n }\n return value;\n };\n\n const normalizedData = JSON.stringify(normalize(data));\n return `${endpointPath}:${normalizedData}`;\n}\n\n/** Deduplicates identical in-flight requests so they share a single HTTP call. */\nexport class DedupeTransport implements BaseTransport {\n private inFlightRequests = new Map<string, Promise<any>>();\n\n constructor(\n private wrappedTransport: BaseTransport,\n private debug?: boolean\n ) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const requestKey = generateRequestKey(endpointPath, data);\n\n const existingRequest = this.inFlightRequests.get(requestKey);\n if (existingRequest) {\n if (this.debug) {\n console.log(`[DedupeTransport] Deduplicating request to ${endpointPath}`);\n }\n return existingRequest;\n }\n\n const requestPromise = this.wrappedTransport.post(data, endpointPath)\n .finally(() => {\n this.inFlightRequests.delete(requestKey);\n });\n\n this.inFlightRequests.set(requestKey, requestPromise);\n\n if (this.debug) {\n console.log(`[DedupeTransport] New request to ${endpointPath} (${this.inFlightRequests.size} in-flight)`);\n }\n\n return requestPromise;\n }\n}\n","import type { BaseTransport } from '../../core/types';\nimport { SDK_NAME, SDK_VERSION } from '../../version';\nimport { DedupeTransport } from './dedupe';\n\nconst BASE_URL = 'https://dynamic.belocal.dev';\n\nexport interface BaseBrowserTransportConfig {\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport class BaseBrowserTransport implements BaseTransport {\n constructor(private config: BaseBrowserTransportConfig) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const url = `${BASE_URL}${endpointPath}`;\n const controller = new AbortController();\n const timeoutMs = this.config.timeoutMs ?? 10000;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (this.config.debug) {\n console.log(`[Base Browser Transport] POST request to ${url}`, data);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-sdk': SDK_NAME,\n 'x-sdk-version': SDK_VERSION,\n ...this.config.headers,\n },\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (this.config.debug) {\n console.error(`[Base Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (this.config.debug) {\n console.log(`[Base Browser Transport] Request successful:`, result);\n }\n \n return result;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n}\n\nexport function createBaseBrowserTransport(config: BaseBrowserTransportConfig): BaseTransport {\n const transport = new BaseBrowserTransport(config);\n return new DedupeTransport(transport, config.debug);\n}\n","import type { Transport, BaseTransport, TranslationCtx } from '../core/types';\nimport { md5 } from 'js-md5';\n\nexport interface MultiTransportConfig {\n baseTransport: BaseTransport;\n debug?: boolean;\n batchWindowMs?: number;\n}\n\ninterface MultiRequest {\n request_id: string;\n texts: string[];\n lang: string;\n source_lang?: string;\n ctx?: TranslationCtx;\n}\n\ninterface MultiRequestItem {\n text: string;\n lang: string;\n sourceLang?: string;\n context?: TranslationCtx;\n resolve: (value: { text: string; status: string }) => void;\n reject: (error: Error) => void;\n}\n\ninterface MultiResponse {\n results: Array<{\n request_id: string;\n data: { texts: string[]; status: string };\n }>;\n}\n\ninterface MultiState {\n currentMulti: MultiRequestItem[];\n multiTimer: ReturnType<typeof setTimeout> | null;\n isRequestInFlight: boolean;\n}\n\nfunction generateRequestId(texts: string[], lang: string, sourceLang?: string, context?: TranslationCtx): string {\n const sortedTexts = [...texts].sort();\n\n const sortedContext = context && Object.keys(context).length > 0\n ? Object.fromEntries(Object.entries(context).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = [sortedTexts, lang, sourceLang || null, sortedContext];\n return md5(JSON.stringify(data));\n}\n\nasync function sendMulti(\n config: MultiTransportConfig,\n items: MultiRequestItem[],\n state: MultiState\n): Promise<void> {\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Sending multi request with ${items.length} texts`);\n }\n\n try {\n const groups = new Map<string, MultiRequestItem[]>();\n\n items.forEach(item => {\n const groupKey = JSON.stringify({\n lang: item.lang,\n sourceLang: item.sourceLang || null,\n context: item.context || null\n });\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(item);\n });\n\n const requestIdToGroupItems = new Map<string, MultiRequestItem[]>();\n const requests: MultiRequest[] = Array.from(groups.entries()).map(([groupKey, groupItems]) => {\n const firstItem = groupItems[0];\n const texts = groupItems.map(item => item.text);\n\n const requestId = generateRequestId(\n texts,\n firstItem.lang,\n firstItem.sourceLang,\n firstItem.context\n );\n\n requestIdToGroupItems.set(requestId, groupItems);\n\n return {\n request_id: requestId,\n texts,\n lang: firstItem.lang,\n source_lang: firstItem.sourceLang,\n ctx: firstItem.context\n };\n });\n\n const multiResponse: MultiResponse = await config.baseTransport.post({ requests }, '/v1/translate/multi');\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Multi response received with ${multiResponse.results.length} groups`);\n }\n\n const resultMap = new Map<string, { texts: string[]; status: string }>();\n multiResponse.results.forEach(result => {\n resultMap.set(result.request_id, { texts: result.data.texts, status: result.data.status });\n });\n\n requestIdToGroupItems.forEach((groupItems, requestId) => {\n const result = resultMap.get(requestId);\n\n if (!result) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] No result found for request_id: ${requestId}`);\n }\n groupItems.forEach(item => {\n item.reject(new Error(`No result found for request ${requestId}`));\n });\n return;\n }\n\n if (result.texts.length !== groupItems.length) {\n const error = new Error(`Mismatch: expected ${groupItems.length} texts, got ${result.texts.length} for request_id ${requestId}`);\n if (config.debug) {\n console.error(`[BeLocal Multi Transport]`, error.message);\n }\n groupItems.forEach(item => item.reject(error));\n return;\n }\n\n groupItems.forEach((item, index) => {\n const translatedText = result.texts[index];\n const status = result.status || 'success';\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Success for request_id ${requestId}[${index}]: \"${translatedText}\"`);\n }\n\n item.resolve({ text: translatedText, status });\n });\n });\n } catch (error) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] Multi request error:`, error);\n }\n\n const errorToReject = error instanceof Error ? error : new Error(String(error));\n items.forEach(item => item.reject(errorToReject));\n }\n}\n\nfunction processMulti(config: MultiTransportConfig, state: MultiState): void {\n if (state.currentMulti.length === 0 || state.isRequestInFlight) {\n return;\n }\n\n const itemsToSend = [...state.currentMulti];\n state.currentMulti = [];\n state.multiTimer = null;\n state.isRequestInFlight = true;\n\n sendMulti(config, itemsToSend, state).finally(() => {\n state.isRequestInFlight = false;\n\n if (state.currentMulti.length > 0) {\n const windowMs = config.batchWindowMs ?? 50;\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n}\n\nexport function createMultiTransport(config: MultiTransportConfig): Transport {\n const windowMs = config.batchWindowMs ?? 50;\n\n const state: MultiState = {\n currentMulti: [],\n multiTimer: null,\n isRequestInFlight: false,\n };\n\n const transport = (({ text, lang, source_lang, ctx }) => {\n return new Promise<{ text: string; status: string }>((resolve, reject) => {\n if (config.debug) {\n const tempRequestId = md5(JSON.stringify([text, lang, source_lang || null, ctx || null]));\n console.log(`[BeLocal Multi Transport] Queuing request ${tempRequestId}: \"${text}\" to ${lang}`);\n }\n\n const requestItem: MultiRequestItem = {\n text,\n lang,\n sourceLang: source_lang,\n context: ctx,\n resolve,\n reject,\n };\n\n state.currentMulti.push(requestItem);\n\n if (state.multiTimer === null && !state.isRequestInFlight) {\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n }) as Transport & { destroy: () => void };\n\n transport.destroy = () => {\n if (state.multiTimer) {\n clearTimeout(state.multiTimer);\n state.multiTimer = null;\n }\n state.currentMulti.forEach(item =>\n item.reject(new Error('Transport destroyed'))\n );\n state.currentMulti = [];\n };\n\n return transport;\n}\n","import type { Cache, CacheOptions } from './types';\n\ninterface CacheEntry {\n value: string;\n expiresAt: number;\n}\n\nexport class LocalCache implements Cache {\n private storage = new Map<string, CacheEntry>();\n private maxSize: number;\n private ttlMs: number;\n\n constructor(options: CacheOptions = {}) {\n this.maxSize = options.maxSize ?? 10_000;\n this.ttlMs = options.ttlMs ?? 3_600_000;\n }\n\n get(key: string): string | null {\n const entry = this.storage.get(key);\n if (entry === undefined) return null;\n\n if (Date.now() > entry.expiresAt) {\n this.storage.delete(key);\n return null;\n }\n\n this.storage.delete(key);\n this.storage.set(key, entry);\n\n return entry.value;\n }\n\n set(key: string, value: string): void {\n this.storage.delete(key);\n\n if (this.storage.size >= this.maxSize) {\n const oldestKey = this.storage.keys().next().value;\n if (oldestKey !== undefined) {\n this.storage.delete(oldestKey);\n }\n }\n\n this.storage.set(key, {\n value,\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n clear(): void {\n this.storage.clear();\n }\n}\n","import type { BelocalEngineOptions, Lang, TranslateOptions, TranslationCtx, Transport, BaseTransport } from '../types';\nimport { createMultiTransport } from '../../transports/multi';\nimport { LocalCache } from '../../cache/local';\nimport type { Cache } from '../../cache/types';\nimport { md5 } from 'js-md5';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n private cache: Cache;\n\n constructor(options: BelocalEngineOptions, baseTransportFactory: (opts: any) => BaseTransport) {\n const {\n apiKey,\n batchWindowMs = 50,\n timeoutMs = 10000,\n debug = false,\n cacheTtlMs = 3_600_000,\n cacheMaxSize = 10_000\n } = options;\n\n if (!apiKey || typeof apiKey !== 'string') {\n throw new Error('[BeLocal] apiKey is required and must be a non-empty string');\n }\n\n if (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new Error('[BeLocal] timeoutMs must be a positive finite number');\n }\n\n const safeBatchWindowMs = Math.max(0, batchWindowMs);\n\n this.debug = debug;\n this.cache = new LocalCache({ ttlMs: cacheTtlMs, maxSize: cacheMaxSize });\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`\n };\n\n const baseTransport = baseTransportFactory({\n headers: authHeaders,\n timeoutMs,\n debug: this.debug\n });\n\n this.transport = createMultiTransport({\n baseTransport,\n debug: this.debug,\n batchWindowMs: safeBatchWindowMs\n });\n\n if (this.debug) {\n console.log('[BeLocal Engine] Multi transport created with config:', {\n baseUrl: 'https://dynamic.belocal.dev',\n timeoutMs,\n batchWindowMs: safeBatchWindowMs\n });\n }\n }\n\n /** Translates a single text string to the target language. */\n async translate(text: string, lang: Lang, options?: TranslateOptions): Promise<string> {\n const results = await this.translateMany([text], lang, options);\n return results[0];\n }\n\n /** Translates multiple text strings to the target language in a single batch. */\n async translateMany(texts: string[], lang: Lang, options?: TranslateOptions): Promise<string[]> {\n const { source_lang, ctx } = this.resolveOptions(options);\n const results: (string | null)[] = new Array(texts.length);\n const cacheMisses: Array<{ index: number; text: string }> = [];\n\n for (let i = 0; i < texts.length; i++) {\n const text = texts[i];\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n\n const cachedResult = this.cache.get(cacheKey);\n if (cachedResult !== null) {\n results[i] = cachedResult;\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from cache:', text);\n }\n continue;\n }\n\n results[i] = null;\n cacheMisses.push({ index: i, text });\n }\n\n if (cacheMisses.length > 0) {\n const settlements = await Promise.allSettled(\n cacheMisses.map(async ({ index, text }) => {\n const result = await this.transport({ text, lang, source_lang, ctx });\n\n if (result.status !== 'error') {\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n this.cache.set(cacheKey, result.text);\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API, cached:', text);\n }\n } else {\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API (not cached due to error status):', text);\n }\n }\n\n return { index, translation: result.text };\n })\n );\n\n settlements.forEach((settlement, i) => {\n const { index, text } = cacheMisses[i];\n if (settlement.status === 'fulfilled') {\n results[index] = settlement.value.translation;\n } else {\n results[index] = text;\n if (this.debug) {\n const reason = settlement.reason;\n console.error(\n '[BeLocal Engine] Translation failed, using original text:',\n text,\n reason instanceof Error ? reason.message : String(reason)\n );\n }\n }\n });\n }\n\n return results as string[];\n }\n\n private resolveOptions(options?: TranslateOptions): { source_lang?: string; ctx?: TranslationCtx } {\n if (!options) return {};\n const serverCtx: TranslationCtx = {\n ...options.ctx,\n ...(options.context && { user_ctx: options.context }),\n ...(options.managed && { cache_type: 'managed' }),\n };\n const ctx = Object.values(serverCtx).some(Boolean) ? serverCtx : undefined;\n return { source_lang: options.source_lang, ctx };\n }\n\n /** Cleans up internal resources (timers, cache). Call when the engine is no longer needed. */\n destroy(): void {\n (this.transport as any).destroy?.();\n this.cache.clear();\n }\n\n private generateCacheKey(text: string, lang: Lang, source_lang?: string, ctx?: TranslationCtx): string {\n const sortedCtx = ctx\n ? Object.fromEntries(Object.entries(ctx).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = {\n text,\n lang,\n source_lang: source_lang || null,\n ctx: sortedCtx\n };\n return md5(JSON.stringify(data));\n }\n}\n","export type Lang = string;\n\nexport type UserCtx = {\n user_type?: string;\n entity_key?: string;\n entity_id?: string;\n};\n\nexport type TranslationCtx = {\n user_type?: string;\n user_ctx?: string;\n cache_type?: string;\n entity_key?: string;\n entity_id?: string;\n};\n\nexport const USER_TYPE_PRODUCT = 'product';\nexport const USER_TYPE_CHAT = 'chat';\n\nexport type TranslateOptions = {\n source_lang?: string;\n context?: string;\n managed?: boolean;\n ctx?: UserCtx;\n};\n\nexport interface BaseTransport {\n post(data: any, endpointPath: string): Promise<any>;\n}\n\nexport type Transport = (params: { text: string; lang: Lang; source_lang?: string; ctx?: TranslationCtx }) => Promise<{ text: string; status: string }>;\n\nexport interface BelocalEngineOptions {\n apiKey: string;\n batchWindowMs?: number;\n timeoutMs?: number;\n debug?: boolean;\n cacheTtlMs?: number;\n cacheMaxSize?: number;\n}\n","import type { BelocalEngineOptions } from '../types';\nimport { createBaseBrowserTransport } from '../../transports/base/browser';\nimport { BelocalEngine as BaseEngine } from './engine';\n\nexport class BelocalEngine extends BaseEngine {\n constructor(options: BelocalEngineOptions) {\n super(options, createBaseBrowserTransport);\n }\n}\n\nexport type { BelocalEngineOptions, Lang, TranslateOptions, BaseTransport, TranslationCtx, UserCtx } from '../types';\nexport { USER_TYPE_PRODUCT, USER_TYPE_CHAT } from '../types';\nexport { createMultiTransport } from '../../transports/multi';\nexport { BaseBrowserTransport, createBaseBrowserTransport } from '../../transports/base';\n"]}
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  type Lang = string;
2
+ type UserCtx = {
3
+ user_type?: string;
4
+ entity_key?: string;
5
+ entity_id?: string;
6
+ };
2
7
  type TranslationCtx = {
3
8
  user_type?: string;
4
9
  user_ctx?: string;
@@ -8,7 +13,12 @@ type TranslationCtx = {
8
13
  };
9
14
  declare const USER_TYPE_PRODUCT = "product";
10
15
  declare const USER_TYPE_CHAT = "chat";
11
- type KV = TranslationCtx;
16
+ type TranslateOptions = {
17
+ source_lang?: string;
18
+ context?: string;
19
+ managed?: boolean;
20
+ ctx?: UserCtx;
21
+ };
12
22
  interface BaseTransport {
13
23
  post(data: any, endpointPath: string): Promise<any>;
14
24
  }
@@ -16,7 +26,7 @@ type Transport = (params: {
16
26
  text: string;
17
27
  lang: Lang;
18
28
  source_lang?: string;
19
- ctx?: KV;
29
+ ctx?: TranslationCtx;
20
30
  }) => Promise<{
21
31
  text: string;
22
32
  status: string;
@@ -26,6 +36,8 @@ interface BelocalEngineOptions {
26
36
  batchWindowMs?: number;
27
37
  timeoutMs?: number;
28
38
  debug?: boolean;
39
+ cacheTtlMs?: number;
40
+ cacheMaxSize?: number;
29
41
  }
30
42
 
31
43
  declare class BelocalEngine$1 {
@@ -34,11 +46,12 @@ declare class BelocalEngine$1 {
34
46
  private cache;
35
47
  constructor(options: BelocalEngineOptions, baseTransportFactory: (opts: any) => BaseTransport);
36
48
  /** Translates a single text string to the target language. */
37
- translate(text: string, lang: Lang, source_lang?: string, ctx?: KV): Promise<string>;
49
+ translate(text: string, lang: Lang, options?: TranslateOptions): Promise<string>;
38
50
  /** Translates multiple text strings to the target language in a single batch. */
39
- translateMany(texts: string[], lang: Lang, source_lang?: string, ctx?: KV): Promise<string[]>;
40
- /** Shortcut for translate() */
41
- t(text: string, lang: Lang, source_lang?: string, context?: string, managed?: boolean): Promise<string>;
51
+ translateMany(texts: string[], lang: Lang, options?: TranslateOptions): Promise<string[]>;
52
+ private resolveOptions;
53
+ /** Cleans up internal resources (timers, cache). Call when the engine is no longer needed. */
54
+ destroy(): void;
42
55
  private generateCacheKey;
43
56
  }
44
57
 
@@ -65,4 +78,4 @@ declare class BelocalEngine extends BelocalEngine$1 {
65
78
  constructor(options: BelocalEngineOptions);
66
79
  }
67
80
 
68
- export { BaseBrowserTransport, type BaseTransport, BelocalEngine, type BelocalEngineOptions, type KV, type Lang, type TranslationCtx, USER_TYPE_CHAT, USER_TYPE_PRODUCT, createBaseBrowserTransport, createMultiTransport };
81
+ export { BaseBrowserTransport, type BaseTransport, BelocalEngine, type BelocalEngineOptions, type Lang, type TranslateOptions, type TranslationCtx, USER_TYPE_CHAT, USER_TYPE_PRODUCT, type UserCtx, createBaseBrowserTransport, createMultiTransport };
package/dist/browser.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import {md5}from'js-md5';var x="1.0.1";function _(i,t){let s=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(s);if(typeof e=="object"){let o={};for(let c of Object.keys(e).sort())o[c]=s(e[c]);return o}return e},r=JSON.stringify(s(t));return `${i}:${r}`}var m=class{constructor(t,s){this.wrappedTransport=t;this.debug=s;this.inFlightRequests=new Map;}async post(t,s){let r=_(s,t),e=this.inFlightRequests.get(r);if(e)return this.debug&&console.log(`[DedupeTransport] Deduplicating request to ${s}`),e;let o=this.wrappedTransport.post(t,s).finally(()=>{this.inFlightRequests.delete(r);});return this.inFlightRequests.set(r,o),this.debug&&console.log(`[DedupeTransport] New request to ${s} (${this.inFlightRequests.size} in-flight)`),o}};var q="https://dynamic.belocal.dev",f=class{constructor(t){this.config=t;}async post(t,s){let r=`${q}${s}`,e=new AbortController,o=this.config.timeoutMs??1e4,c=setTimeout(()=>e.abort(),o);this.config.debug&&console.log(`[Base Browser Transport] POST request to ${r}`,t);try{let u=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-sdk":"js","x-sdk-version":x,...this.config.headers},body:JSON.stringify(t),signal:e.signal});if(!u.ok){let a=`HTTP ${u.status}: ${u.statusText}`;throw this.config.debug&&console.error("[Base Browser Transport] Request failed:",a),new Error(a)}let n=await u.json();return this.config.debug&&console.log("[Base Browser Transport] Request successful:",n),n}finally{c&&clearTimeout(c);}}};function h(i){let t=new f(i);return new m(t,i.debug)}function S(i,t,s,r){let e=[...i].sort(),o=r&&Object.keys(r).length>0?Object.fromEntries(Object.entries(r).sort(([u],[n])=>u.localeCompare(n))):null;return md5(JSON.stringify([e,t,s||null,o]))}async function K(i,t,s){i.debug&&console.log(`[BeLocal Multi Transport] Sending multi request with ${t.length} texts`);try{let r=new Map;t.forEach(n=>{let a=JSON.stringify({lang:n.lang,sourceLang:n.sourceLang||null,context:n.context||null});r.has(a)||r.set(a,[]),r.get(a).push(n);});let e=new Map,o=Array.from(r.entries()).map(([n,a])=>{let l=a[0],p=a.map(d=>d.text),g=S(p,l.lang,l.sourceLang,l.context);return e.set(g,a),{request_id:g,texts:p,lang:l.lang,source_lang:l.sourceLang,ctx:l.context}}),c=await i.baseTransport.post({requests:o},"/v1/translate/multi");i.debug&&console.log(`[BeLocal Multi Transport] Multi response received with ${c.results.length} groups`);let u=new Map;c.results.forEach(n=>{u.set(n.request_id,{texts:n.data.texts,status:n.data.status});}),e.forEach((n,a)=>{let l=u.get(a);if(!l){i.debug&&console.error(`[BeLocal Multi Transport] No result found for request_id: ${a}`),n.forEach(p=>{p.reject(new Error(`No result found for request ${a}`));});return}if(l.texts.length!==n.length){let p=new Error(`Mismatch: expected ${n.length} texts, got ${l.texts.length} for request_id ${a}`);i.debug&&console.error("[BeLocal Multi Transport]",p.message),n.forEach(g=>g.reject(p));return}n.forEach((p,g)=>{let d=l.texts[g],R=l.status||"success";i.debug&&console.log(`[BeLocal Multi Transport] Success for request_id ${a}[${g}]: "${d}"`),p.resolve({text:d,status:R});});});}catch(r){i.debug&&console.error("[BeLocal Multi Transport] Multi request error:",r);let e=r instanceof Error?r:new Error(String(r));t.forEach(o=>o.reject(e));}}function B(i,t){if(t.currentMulti.length===0||t.isRequestInFlight)return;let s=[...t.currentMulti];t.currentMulti=[],t.multiTimer=null,t.isRequestInFlight=true,K(i,s).finally(()=>{if(t.isRequestInFlight=false,t.currentMulti.length>0){let r=i.batchWindowMs??50;t.multiTimer=setTimeout(()=>B(i,t),r);}});}function M(i){let t=i.batchWindowMs??50,s={currentMulti:[],multiTimer:null,isRequestInFlight:false};return ({text:r,lang:e,source_lang:o,ctx:c})=>new Promise((u,n)=>{if(i.debug){let l=md5(JSON.stringify([r,e,o||null,c||null]));console.log(`[BeLocal Multi Transport] Queuing request ${l}: "${r}" to ${e}`);}let a={text:r,lang:e,sourceLang:o,context:c,resolve:u,reject:n};s.currentMulti.push(a),s.multiTimer===null&&!s.isRequestInFlight&&(s.multiTimer=setTimeout(()=>B(i,s),t));})}var T=class{constructor(){this.storage=new Map;}get(t){return this.storage.get(t)||null}set(t,s){this.storage.set(t,s);}};var y=class{constructor(t,s){let{apiKey:r,batchWindowMs:e=50,timeoutMs:o=1e4,debug:c=false}=t;this.debug=c,this.cache=new T;let u={Authorization:`Bearer ${r}`},n=s({headers:u,timeoutMs:o,debug:this.debug});this.transport=M({baseTransport:n,debug:this.debug,batchWindowMs:e}),this.debug&&console.log("[BeLocal Engine] Multi transport created with config:",{baseUrl:"https://dynamic.belocal.dev",timeoutMs:o,batchWindowMs:e});}async translate(t,s,r,e){return (await this.translateMany([t],s,r,e))[0]}async translateMany(t,s,r,e){let o=new Array(t.length),c=[];for(let u=0;u<t.length;u++){let n=t[u],a=this.generateCacheKey(n,s,r,e),l=this.cache.get(a);if(l){o[u]=l,this.debug&&console.log("[BeLocal Engine] Translation from cache:",n);continue}o[u]=null,c.push({index:u,text:n});}return c.length>0&&(await Promise.all(c.map(async({index:n,text:a})=>{let l=await this.transport({text:a,lang:s,source_lang:r,ctx:e});if(l.status!=="error"){let p=this.generateCacheKey(a,s,r,e);this.cache.set(p,l.text),this.debug&&console.log("[BeLocal Engine] Translation from API, cached:",a);}else this.debug&&console.log("[BeLocal Engine] Translation from API (not cached due to error status):",a);return {index:n,translation:l.text}}))).forEach(({index:n,translation:a})=>{o[n]=a;}),o}async t(t,s,r,e,o=false){let c=e||o?{...e?{user_ctx:e}:{},...o?{cache_type:"managed"}:{}}:void 0;return this.translate(t,s,r,c)}generateCacheKey(t,s,r,e){let o=e?Object.fromEntries(Object.entries(e).sort(([u],[n])=>u.localeCompare(n))):null;return md5(JSON.stringify({text:t,lang:s,source_lang:r||null,ctx:o}))}};var O="product",L="chat";var w=class extends y{constructor(t){super(t,h);}};
2
- export{f as BaseBrowserTransport,w as BelocalEngine,L as USER_TYPE_CHAT,O as USER_TYPE_PRODUCT,h as createBaseBrowserTransport,M as createMultiTransport};//# sourceMappingURL=browser.mjs.map
1
+ import {md5}from'js-md5';var M="1.0.3";function E(a,t){let e=s=>{if(s==null)return s;if(Array.isArray(s))return s.map(e);if(typeof s=="object"){let i={};for(let u of Object.keys(s).sort())i[u]=e(s[u]);return i}return s},r=JSON.stringify(e(t));return `${a}:${r}`}var m=class{constructor(t,e){this.wrappedTransport=t;this.debug=e;this.inFlightRequests=new Map;}async post(t,e){let r=E(e,t),s=this.inFlightRequests.get(r);if(s)return this.debug&&console.log(`[DedupeTransport] Deduplicating request to ${e}`),s;let i=this.wrappedTransport.post(t,e).finally(()=>{this.inFlightRequests.delete(r);});return this.inFlightRequests.set(r,i),this.debug&&console.log(`[DedupeTransport] New request to ${e} (${this.inFlightRequests.size} in-flight)`),i}};var R="https://dynamic.belocal.dev",d=class{constructor(t){this.config=t;}async post(t,e){let r=`${R}${e}`,s=new AbortController,i=this.config.timeoutMs??1e4,u=setTimeout(()=>s.abort(),i);this.config.debug&&console.log(`[Base Browser Transport] POST request to ${r}`,t);try{let g=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-sdk":"js","x-sdk-version":M,...this.config.headers},body:JSON.stringify(t),signal:s.signal});if(!g.ok){let o=`HTTP ${g.status}: ${g.statusText}`;throw this.config.debug&&console.error("[Base Browser Transport] Request failed:",o),new Error(o)}let n=await g.json();return this.config.debug&&console.log("[Base Browser Transport] Request successful:",n),n}finally{u&&clearTimeout(u);}}};function h(a){let t=new d(a);return new m(t,a.debug)}function q(a,t,e,r){let s=[...a].sort(),i=r&&Object.keys(r).length>0?Object.fromEntries(Object.entries(r).sort(([g],[n])=>g.localeCompare(n))):null;return md5(JSON.stringify([s,t,e||null,i]))}async function S(a,t,e){a.debug&&console.log(`[BeLocal Multi Transport] Sending multi request with ${t.length} texts`);try{let r=new Map;t.forEach(n=>{let o=JSON.stringify({lang:n.lang,sourceLang:n.sourceLang||null,context:n.context||null});r.has(o)||r.set(o,[]),r.get(o).push(n);});let s=new Map,i=Array.from(r.entries()).map(([n,o])=>{let c=o[0],l=o.map(f=>f.text),p=q(l,c.lang,c.sourceLang,c.context);return s.set(p,o),{request_id:p,texts:l,lang:c.lang,source_lang:c.sourceLang,ctx:c.context}}),u=await a.baseTransport.post({requests:i},"/v1/translate/multi");a.debug&&console.log(`[BeLocal Multi Transport] Multi response received with ${u.results.length} groups`);let g=new Map;u.results.forEach(n=>{g.set(n.request_id,{texts:n.data.texts,status:n.data.status});}),s.forEach((n,o)=>{let c=g.get(o);if(!c){a.debug&&console.error(`[BeLocal Multi Transport] No result found for request_id: ${o}`),n.forEach(l=>{l.reject(new Error(`No result found for request ${o}`));});return}if(c.texts.length!==n.length){let l=new Error(`Mismatch: expected ${n.length} texts, got ${c.texts.length} for request_id ${o}`);a.debug&&console.error("[BeLocal Multi Transport]",l.message),n.forEach(p=>p.reject(l));return}n.forEach((l,p)=>{let f=c.texts[p],_=c.status||"success";a.debug&&console.log(`[BeLocal Multi Transport] Success for request_id ${o}[${p}]: "${f}"`),l.resolve({text:f,status:_});});});}catch(r){a.debug&&console.error("[BeLocal Multi Transport] Multi request error:",r);let s=r instanceof Error?r:new Error(String(r));t.forEach(i=>i.reject(s));}}function B(a,t){if(t.currentMulti.length===0||t.isRequestInFlight)return;let e=[...t.currentMulti];t.currentMulti=[],t.multiTimer=null,t.isRequestInFlight=true,S(a,e).finally(()=>{if(t.isRequestInFlight=false,t.currentMulti.length>0){let r=a.batchWindowMs??50;t.multiTimer=setTimeout(()=>B(a,t),r);}});}function x(a){let t=a.batchWindowMs??50,e={currentMulti:[],multiTimer:null,isRequestInFlight:false},r=(({text:s,lang:i,source_lang:u,ctx:g})=>new Promise((n,o)=>{if(a.debug){let l=md5(JSON.stringify([s,i,u||null,g||null]));console.log(`[BeLocal Multi Transport] Queuing request ${l}: "${s}" to ${i}`);}let c={text:s,lang:i,sourceLang:u,context:g,resolve:n,reject:o};e.currentMulti.push(c),e.multiTimer===null&&!e.isRequestInFlight&&(e.multiTimer=setTimeout(()=>B(a,e),t));}));return r.destroy=()=>{e.multiTimer&&(clearTimeout(e.multiTimer),e.multiTimer=null),e.currentMulti.forEach(s=>s.reject(new Error("Transport destroyed"))),e.currentMulti=[];},r}var T=class{constructor(t={}){this.storage=new Map;this.maxSize=t.maxSize??1e4,this.ttlMs=t.ttlMs??36e5;}get(t){let e=this.storage.get(t);return e===void 0?null:Date.now()>e.expiresAt?(this.storage.delete(t),null):(this.storage.delete(t),this.storage.set(t,e),e.value)}set(t,e){if(this.storage.delete(t),this.storage.size>=this.maxSize){let r=this.storage.keys().next().value;r!==void 0&&this.storage.delete(r);}this.storage.set(t,{value:e,expiresAt:Date.now()+this.ttlMs});}clear(){this.storage.clear();}};var y=class{constructor(t,e){let{apiKey:r,batchWindowMs:s=50,timeoutMs:i=1e4,debug:u=false,cacheTtlMs:g=36e5,cacheMaxSize:n=1e4}=t;if(!r||typeof r!="string")throw new Error("[BeLocal] apiKey is required and must be a non-empty string");if(typeof i!="number"||!Number.isFinite(i)||i<=0)throw new Error("[BeLocal] timeoutMs must be a positive finite number");let o=Math.max(0,s);this.debug=u,this.cache=new T({ttlMs:g,maxSize:n});let c={Authorization:`Bearer ${r}`},l=e({headers:c,timeoutMs:i,debug:this.debug});this.transport=x({baseTransport:l,debug:this.debug,batchWindowMs:o}),this.debug&&console.log("[BeLocal Engine] Multi transport created with config:",{baseUrl:"https://dynamic.belocal.dev",timeoutMs:i,batchWindowMs:o});}async translate(t,e,r){return (await this.translateMany([t],e,r))[0]}async translateMany(t,e,r){let{source_lang:s,ctx:i}=this.resolveOptions(r),u=new Array(t.length),g=[];for(let n=0;n<t.length;n++){let o=t[n],c=this.generateCacheKey(o,e,s,i),l=this.cache.get(c);if(l!==null){u[n]=l,this.debug&&console.log("[BeLocal Engine] Translation from cache:",o);continue}u[n]=null,g.push({index:n,text:o});}return g.length>0&&(await Promise.allSettled(g.map(async({index:o,text:c})=>{let l=await this.transport({text:c,lang:e,source_lang:s,ctx:i});if(l.status!=="error"){let p=this.generateCacheKey(c,e,s,i);this.cache.set(p,l.text),this.debug&&console.log("[BeLocal Engine] Translation from API, cached:",c);}else this.debug&&console.log("[BeLocal Engine] Translation from API (not cached due to error status):",c);return {index:o,translation:l.text}}))).forEach((o,c)=>{let{index:l,text:p}=g[c];if(o.status==="fulfilled")u[l]=o.value.translation;else if(u[l]=p,this.debug){let f=o.reason;console.error("[BeLocal Engine] Translation failed, using original text:",p,f instanceof Error?f.message:String(f));}}),u}resolveOptions(t){if(!t)return {};let e={...t.ctx,...t.context&&{user_ctx:t.context},...t.managed&&{cache_type:"managed"}},r=Object.values(e).some(Boolean)?e:void 0;return {source_lang:t.source_lang,ctx:r}}destroy(){this.transport.destroy?.(),this.cache.clear();}generateCacheKey(t,e,r,s){let i=s?Object.fromEntries(Object.entries(s).sort(([g],[n])=>g.localeCompare(n))):null;return md5(JSON.stringify({text:t,lang:e,source_lang:r||null,ctx:i}))}};var v="product",L="chat";var w=class extends y{constructor(t){super(t,h);}};
2
+ export{d as BaseBrowserTransport,w as BelocalEngine,L as USER_TYPE_CHAT,v as USER_TYPE_PRODUCT,h as createBaseBrowserTransport,x as createMultiTransport};//# sourceMappingURL=browser.mjs.map
3
3
  //# sourceMappingURL=browser.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/transports/base/dedupe.ts","../src/transports/base/browser.ts","../src/transports/multi.ts","../src/cache/local.ts","../src/core/engine/engine.ts","../src/core/types.ts","../src/core/engine/browser.ts"],"names":["SDK_VERSION","generateRequestKey","endpointPath","data","normalize","value","sorted","key","normalizedData","DedupeTransport","wrappedTransport","debug","requestKey","existingRequest","requestPromise","BASE_URL","BaseBrowserTransport","config","url","controller","timeoutMs","timeoutId","response","errorMsg","result","createBaseBrowserTransport","transport","generateRequestId","texts","lang","sourceLang","context","sortedTexts","sortedContext","a","b","md5","sendMulti","items","state","groups","item","groupKey","requestIdToGroupItems","requests","groupItems","firstItem","requestId","multiResponse","resultMap","error","index","translatedText","status","errorToReject","processMulti","itemsToSend","windowMs","createMultiTransport","text","source_lang","ctx","resolve","reject","tempRequestId","requestItem","LocalCache","BelocalEngine","options","baseTransportFactory","apiKey","batchWindowMs","authHeaders","baseTransport","results","cacheMisses","i","cacheKey","cachedResult","translation","managed","sortedCtx","USER_TYPE_PRODUCT","USER_TYPE_CHAT"],"mappings":"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","file":"browser.mjs","sourcesContent":["declare const __SDK_VERSION__: string;\nexport const SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : 'undefined';\nexport const SDK_NAME = 'js';\n","import type { BaseTransport } from '../../core/types';\n\nfunction generateRequestKey(endpointPath: string, data: any): string {\n const normalize = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(normalize);\n }\n if (typeof value === 'object') {\n const sorted: Record<string, any> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = normalize(value[key]);\n }\n return sorted;\n }\n return value;\n };\n\n const normalizedData = JSON.stringify(normalize(data));\n return `${endpointPath}:${normalizedData}`;\n}\n\n/** Deduplicates identical in-flight requests so they share a single HTTP call. */\nexport class DedupeTransport implements BaseTransport {\n private inFlightRequests = new Map<string, Promise<any>>();\n\n constructor(\n private wrappedTransport: BaseTransport,\n private debug?: boolean\n ) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const requestKey = generateRequestKey(endpointPath, data);\n\n const existingRequest = this.inFlightRequests.get(requestKey);\n if (existingRequest) {\n if (this.debug) {\n console.log(`[DedupeTransport] Deduplicating request to ${endpointPath}`);\n }\n return existingRequest;\n }\n\n const requestPromise = this.wrappedTransport.post(data, endpointPath)\n .finally(() => {\n this.inFlightRequests.delete(requestKey);\n });\n\n this.inFlightRequests.set(requestKey, requestPromise);\n\n if (this.debug) {\n console.log(`[DedupeTransport] New request to ${endpointPath} (${this.inFlightRequests.size} in-flight)`);\n }\n\n return requestPromise;\n }\n}\n","import type { BaseTransport } from '../../core/types';\nimport { SDK_NAME, SDK_VERSION } from '../../version';\nimport { DedupeTransport } from './dedupe';\n\nconst BASE_URL = 'https://dynamic.belocal.dev';\n\nexport interface BaseBrowserTransportConfig {\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport class BaseBrowserTransport implements BaseTransport {\n constructor(private config: BaseBrowserTransportConfig) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const url = `${BASE_URL}${endpointPath}`;\n const controller = new AbortController();\n const timeoutMs = this.config.timeoutMs ?? 10000;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (this.config.debug) {\n console.log(`[Base Browser Transport] POST request to ${url}`, data);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-sdk': SDK_NAME,\n 'x-sdk-version': SDK_VERSION,\n ...this.config.headers,\n },\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (this.config.debug) {\n console.error(`[Base Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (this.config.debug) {\n console.log(`[Base Browser Transport] Request successful:`, result);\n }\n \n return result;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n}\n\nexport function createBaseBrowserTransport(config: BaseBrowserTransportConfig): BaseTransport {\n const transport = new BaseBrowserTransport(config);\n return new DedupeTransport(transport, config.debug);\n}\n","import type { Transport, BaseTransport, KV } from '../core/types';\nimport { md5 } from 'js-md5';\n\nexport interface MultiTransportConfig {\n baseTransport: BaseTransport;\n debug?: boolean;\n batchWindowMs?: number;\n}\n\ninterface MultiRequest {\n request_id: string;\n texts: string[];\n lang: string;\n source_lang?: string;\n ctx?: KV;\n}\n\ninterface MultiRequestItem {\n text: string;\n lang: string;\n sourceLang?: string;\n context?: KV;\n resolve: (value: { text: string; status: string }) => void;\n reject: (error: Error) => void;\n}\n\ninterface MultiResponse {\n results: Array<{\n request_id: string;\n data: { texts: string[]; status: string };\n }>;\n}\n\ninterface MultiState {\n currentMulti: MultiRequestItem[];\n multiTimer: ReturnType<typeof setTimeout> | null;\n isRequestInFlight: boolean;\n}\n\nfunction generateRequestId(texts: string[], lang: string, sourceLang?: string, context?: KV): string {\n const sortedTexts = [...texts].sort();\n\n const sortedContext = context && Object.keys(context).length > 0\n ? Object.fromEntries(Object.entries(context).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = [sortedTexts, lang, sourceLang || null, sortedContext];\n return md5(JSON.stringify(data));\n}\n\nasync function sendMulti(\n config: MultiTransportConfig,\n items: MultiRequestItem[],\n state: MultiState\n): Promise<void> {\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Sending multi request with ${items.length} texts`);\n }\n\n try {\n const groups = new Map<string, MultiRequestItem[]>();\n\n items.forEach(item => {\n const groupKey = JSON.stringify({\n lang: item.lang,\n sourceLang: item.sourceLang || null,\n context: item.context || null\n });\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(item);\n });\n\n const requestIdToGroupItems = new Map<string, MultiRequestItem[]>();\n const requests: MultiRequest[] = Array.from(groups.entries()).map(([groupKey, groupItems]) => {\n const firstItem = groupItems[0];\n const texts = groupItems.map(item => item.text);\n\n const requestId = generateRequestId(\n texts,\n firstItem.lang,\n firstItem.sourceLang,\n firstItem.context\n );\n\n requestIdToGroupItems.set(requestId, groupItems);\n\n return {\n request_id: requestId,\n texts,\n lang: firstItem.lang,\n source_lang: firstItem.sourceLang,\n ctx: firstItem.context\n };\n });\n\n const multiResponse: MultiResponse = await config.baseTransport.post({ requests }, '/v1/translate/multi');\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Multi response received with ${multiResponse.results.length} groups`);\n }\n\n const resultMap = new Map<string, { texts: string[]; status: string }>();\n multiResponse.results.forEach(result => {\n resultMap.set(result.request_id, { texts: result.data.texts, status: result.data.status });\n });\n\n requestIdToGroupItems.forEach((groupItems, requestId) => {\n const result = resultMap.get(requestId);\n\n if (!result) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] No result found for request_id: ${requestId}`);\n }\n groupItems.forEach(item => {\n item.reject(new Error(`No result found for request ${requestId}`));\n });\n return;\n }\n\n if (result.texts.length !== groupItems.length) {\n const error = new Error(`Mismatch: expected ${groupItems.length} texts, got ${result.texts.length} for request_id ${requestId}`);\n if (config.debug) {\n console.error(`[BeLocal Multi Transport]`, error.message);\n }\n groupItems.forEach(item => item.reject(error));\n return;\n }\n\n groupItems.forEach((item, index) => {\n const translatedText = result.texts[index];\n const status = result.status || 'success';\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Success for request_id ${requestId}[${index}]: \"${translatedText}\"`);\n }\n\n item.resolve({ text: translatedText, status });\n });\n });\n } catch (error) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] Multi request error:`, error);\n }\n\n const errorToReject = error instanceof Error ? error : new Error(String(error));\n items.forEach(item => item.reject(errorToReject));\n }\n}\n\nfunction processMulti(config: MultiTransportConfig, state: MultiState): void {\n if (state.currentMulti.length === 0 || state.isRequestInFlight) {\n return;\n }\n\n const itemsToSend = [...state.currentMulti];\n state.currentMulti = [];\n state.multiTimer = null;\n state.isRequestInFlight = true;\n\n sendMulti(config, itemsToSend, state).finally(() => {\n state.isRequestInFlight = false;\n\n if (state.currentMulti.length > 0) {\n const windowMs = config.batchWindowMs ?? 50;\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n}\n\nexport function createMultiTransport(config: MultiTransportConfig): Transport {\n const windowMs = config.batchWindowMs ?? 50;\n\n const state: MultiState = {\n currentMulti: [],\n multiTimer: null,\n isRequestInFlight: false,\n };\n\n return ({ text, lang, source_lang, ctx }) => {\n return new Promise<{ text: string; status: string }>((resolve, reject) => {\n if (config.debug) {\n const tempRequestId = md5(JSON.stringify([text, lang, source_lang || null, ctx || null]));\n console.log(`[BeLocal Multi Transport] Queuing request ${tempRequestId}: \"${text}\" to ${lang}`);\n }\n\n const requestItem: MultiRequestItem = {\n text,\n lang,\n sourceLang: source_lang,\n context: ctx,\n resolve,\n reject,\n };\n\n state.currentMulti.push(requestItem);\n\n if (state.multiTimer === null && !state.isRequestInFlight) {\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n };\n}\n","import type { Cache } from './types';\n\nexport class LocalCache implements Cache {\n private storage = new Map<string, string>();\n\n get(key: string): string | null {\n return this.storage.get(key) || null;\n }\n\n set(key: string, value: string): void {\n this.storage.set(key, value);\n }\n}\n","import type { BelocalEngineOptions, KV, Lang, Transport, BaseTransport } from '../types';\nimport { createMultiTransport } from '../../transports/multi';\nimport { LocalCache } from '../../cache/local';\nimport type { Cache } from '../../cache/types';\nimport { md5 } from 'js-md5';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n private cache: Cache;\n\n constructor(options: BelocalEngineOptions, baseTransportFactory: (opts: any) => BaseTransport) {\n const {\n apiKey,\n batchWindowMs = 50,\n timeoutMs = 10000,\n debug = false\n } = options;\n\n this.debug = debug;\n this.cache = new LocalCache();\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`\n };\n\n const baseTransport = baseTransportFactory({\n headers: authHeaders,\n timeoutMs,\n debug: this.debug\n });\n\n this.transport = createMultiTransport({\n baseTransport,\n debug: this.debug,\n batchWindowMs\n });\n\n if (this.debug) {\n console.log('[BeLocal Engine] Multi transport created with config:', {\n baseUrl: 'https://dynamic.belocal.dev',\n timeoutMs,\n batchWindowMs\n });\n }\n }\n\n /** Translates a single text string to the target language. */\n async translate(text: string, lang: Lang, source_lang?: string, ctx?: KV): Promise<string> {\n const results = await this.translateMany([text], lang, source_lang, ctx);\n return results[0];\n }\n\n /** Translates multiple text strings to the target language in a single batch. */\n async translateMany(texts: string[], lang: Lang, source_lang?: string, ctx?: KV): Promise<string[]> {\n const results: (string | null)[] = new Array(texts.length);\n const cacheMisses: Array<{ index: number; text: string }> = [];\n\n for (let i = 0; i < texts.length; i++) {\n const text = texts[i];\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n\n const cachedResult = this.cache.get(cacheKey);\n if (cachedResult) {\n results[i] = cachedResult;\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from cache:', text);\n }\n continue;\n }\n\n results[i] = null;\n cacheMisses.push({ index: i, text });\n }\n\n if (cacheMisses.length > 0) {\n const translations = await Promise.all(\n cacheMisses.map(async ({ index, text }) => {\n const result = await this.transport({ text, lang, source_lang, ctx });\n\n if (result.status !== 'error') {\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n this.cache.set(cacheKey, result.text);\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API, cached:', text);\n }\n } else {\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API (not cached due to error status):', text);\n }\n }\n\n return { index, translation: result.text };\n })\n );\n\n translations.forEach(({ index, translation }) => {\n results[index] = translation;\n });\n }\n\n return results as string[];\n }\n\n /** Shortcut for translate() */\n async t(text: string, lang: Lang, source_lang?: string, context?: string, managed = false): Promise<string> {\n const ctx: KV | undefined = (context || managed)\n ? { ...(context ? { user_ctx: context } : {}), ...(managed ? { cache_type: 'managed' } : {}) }\n : undefined;\n return this.translate(text, lang, source_lang, ctx);\n }\n\n private generateCacheKey(text: string, lang: Lang, source_lang?: string, ctx?: KV): string {\n const sortedCtx = ctx\n ? Object.fromEntries(Object.entries(ctx).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = {\n text,\n lang,\n source_lang: source_lang || null,\n ctx: sortedCtx\n };\n return md5(JSON.stringify(data));\n }\n}\n","export type Lang = string;\n\nexport type TranslationCtx = {\n user_type?: string;\n user_ctx?: string;\n cache_type?: string;\n entity_key?: string;\n entity_id?: string;\n}\n\nexport const USER_TYPE_PRODUCT = 'product';\nexport const USER_TYPE_CHAT = 'chat';\n\nexport type KV = TranslationCtx;\n\nexport interface BaseTransport {\n post(data: any, endpointPath: string): Promise<any>;\n}\n\nexport type Transport = (params: { text: string; lang: Lang; source_lang?: string; ctx?: KV }) => Promise<{ text: string; status: string }>;\n\nexport interface BelocalEngineOptions {\n apiKey: string;\n batchWindowMs?: number;\n timeoutMs?: number;\n debug?: boolean;\n}\n","import type { BelocalEngineOptions } from '../types';\nimport { createBaseBrowserTransport } from '../../transports/base/browser';\nimport { BelocalEngine as BaseEngine } from './engine';\n\nexport class BelocalEngine extends BaseEngine {\n constructor(options: BelocalEngineOptions) {\n super(options, createBaseBrowserTransport);\n }\n}\n\nexport type { BelocalEngineOptions, Lang, KV, BaseTransport, TranslationCtx } from '../types';\nexport { USER_TYPE_PRODUCT, USER_TYPE_CHAT } from '../types';\nexport { createMultiTransport } from '../../transports/multi';\nexport { BaseBrowserTransport, createBaseBrowserTransport } from '../../transports/base';\n"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/transports/base/dedupe.ts","../src/transports/base/browser.ts","../src/transports/multi.ts","../src/cache/local.ts","../src/core/engine/engine.ts","../src/core/types.ts","../src/core/engine/browser.ts"],"names":["SDK_VERSION","generateRequestKey","endpointPath","data","normalize","value","sorted","key","normalizedData","DedupeTransport","wrappedTransport","debug","requestKey","existingRequest","requestPromise","BASE_URL","BaseBrowserTransport","config","url","controller","timeoutMs","timeoutId","response","errorMsg","result","createBaseBrowserTransport","transport","generateRequestId","texts","lang","sourceLang","context","sortedTexts","sortedContext","a","b","md5","sendMulti","items","state","groups","item","groupKey","requestIdToGroupItems","requests","groupItems","firstItem","requestId","multiResponse","resultMap","error","index","translatedText","status","errorToReject","processMulti","itemsToSend","windowMs","createMultiTransport","text","source_lang","ctx","resolve","reject","tempRequestId","requestItem","LocalCache","options","entry","oldestKey","BelocalEngine","baseTransportFactory","apiKey","batchWindowMs","cacheTtlMs","cacheMaxSize","safeBatchWindowMs","authHeaders","baseTransport","results","cacheMisses","i","cacheKey","cachedResult","settlement","reason","serverCtx","sortedCtx","USER_TYPE_PRODUCT","USER_TYPE_CHAT"],"mappings":"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","file":"browser.mjs","sourcesContent":["declare const __SDK_VERSION__: string;\nexport const SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : 'undefined';\nexport const SDK_NAME = 'js';\n","import type { BaseTransport } from '../../core/types';\n\nfunction generateRequestKey(endpointPath: string, data: any): string {\n const normalize = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(normalize);\n }\n if (typeof value === 'object') {\n const sorted: Record<string, any> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = normalize(value[key]);\n }\n return sorted;\n }\n return value;\n };\n\n const normalizedData = JSON.stringify(normalize(data));\n return `${endpointPath}:${normalizedData}`;\n}\n\n/** Deduplicates identical in-flight requests so they share a single HTTP call. */\nexport class DedupeTransport implements BaseTransport {\n private inFlightRequests = new Map<string, Promise<any>>();\n\n constructor(\n private wrappedTransport: BaseTransport,\n private debug?: boolean\n ) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const requestKey = generateRequestKey(endpointPath, data);\n\n const existingRequest = this.inFlightRequests.get(requestKey);\n if (existingRequest) {\n if (this.debug) {\n console.log(`[DedupeTransport] Deduplicating request to ${endpointPath}`);\n }\n return existingRequest;\n }\n\n const requestPromise = this.wrappedTransport.post(data, endpointPath)\n .finally(() => {\n this.inFlightRequests.delete(requestKey);\n });\n\n this.inFlightRequests.set(requestKey, requestPromise);\n\n if (this.debug) {\n console.log(`[DedupeTransport] New request to ${endpointPath} (${this.inFlightRequests.size} in-flight)`);\n }\n\n return requestPromise;\n }\n}\n","import type { BaseTransport } from '../../core/types';\nimport { SDK_NAME, SDK_VERSION } from '../../version';\nimport { DedupeTransport } from './dedupe';\n\nconst BASE_URL = 'https://dynamic.belocal.dev';\n\nexport interface BaseBrowserTransportConfig {\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport class BaseBrowserTransport implements BaseTransport {\n constructor(private config: BaseBrowserTransportConfig) {}\n\n async post(data: any, endpointPath: string): Promise<any> {\n const url = `${BASE_URL}${endpointPath}`;\n const controller = new AbortController();\n const timeoutMs = this.config.timeoutMs ?? 10000;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n if (this.config.debug) {\n console.log(`[Base Browser Transport] POST request to ${url}`, data);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-sdk': SDK_NAME,\n 'x-sdk-version': SDK_VERSION,\n ...this.config.headers,\n },\n body: JSON.stringify(data),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (this.config.debug) {\n console.error(`[Base Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (this.config.debug) {\n console.log(`[Base Browser Transport] Request successful:`, result);\n }\n \n return result;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n}\n\nexport function createBaseBrowserTransport(config: BaseBrowserTransportConfig): BaseTransport {\n const transport = new BaseBrowserTransport(config);\n return new DedupeTransport(transport, config.debug);\n}\n","import type { Transport, BaseTransport, TranslationCtx } from '../core/types';\nimport { md5 } from 'js-md5';\n\nexport interface MultiTransportConfig {\n baseTransport: BaseTransport;\n debug?: boolean;\n batchWindowMs?: number;\n}\n\ninterface MultiRequest {\n request_id: string;\n texts: string[];\n lang: string;\n source_lang?: string;\n ctx?: TranslationCtx;\n}\n\ninterface MultiRequestItem {\n text: string;\n lang: string;\n sourceLang?: string;\n context?: TranslationCtx;\n resolve: (value: { text: string; status: string }) => void;\n reject: (error: Error) => void;\n}\n\ninterface MultiResponse {\n results: Array<{\n request_id: string;\n data: { texts: string[]; status: string };\n }>;\n}\n\ninterface MultiState {\n currentMulti: MultiRequestItem[];\n multiTimer: ReturnType<typeof setTimeout> | null;\n isRequestInFlight: boolean;\n}\n\nfunction generateRequestId(texts: string[], lang: string, sourceLang?: string, context?: TranslationCtx): string {\n const sortedTexts = [...texts].sort();\n\n const sortedContext = context && Object.keys(context).length > 0\n ? Object.fromEntries(Object.entries(context).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = [sortedTexts, lang, sourceLang || null, sortedContext];\n return md5(JSON.stringify(data));\n}\n\nasync function sendMulti(\n config: MultiTransportConfig,\n items: MultiRequestItem[],\n state: MultiState\n): Promise<void> {\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Sending multi request with ${items.length} texts`);\n }\n\n try {\n const groups = new Map<string, MultiRequestItem[]>();\n\n items.forEach(item => {\n const groupKey = JSON.stringify({\n lang: item.lang,\n sourceLang: item.sourceLang || null,\n context: item.context || null\n });\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(item);\n });\n\n const requestIdToGroupItems = new Map<string, MultiRequestItem[]>();\n const requests: MultiRequest[] = Array.from(groups.entries()).map(([groupKey, groupItems]) => {\n const firstItem = groupItems[0];\n const texts = groupItems.map(item => item.text);\n\n const requestId = generateRequestId(\n texts,\n firstItem.lang,\n firstItem.sourceLang,\n firstItem.context\n );\n\n requestIdToGroupItems.set(requestId, groupItems);\n\n return {\n request_id: requestId,\n texts,\n lang: firstItem.lang,\n source_lang: firstItem.sourceLang,\n ctx: firstItem.context\n };\n });\n\n const multiResponse: MultiResponse = await config.baseTransport.post({ requests }, '/v1/translate/multi');\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Multi response received with ${multiResponse.results.length} groups`);\n }\n\n const resultMap = new Map<string, { texts: string[]; status: string }>();\n multiResponse.results.forEach(result => {\n resultMap.set(result.request_id, { texts: result.data.texts, status: result.data.status });\n });\n\n requestIdToGroupItems.forEach((groupItems, requestId) => {\n const result = resultMap.get(requestId);\n\n if (!result) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] No result found for request_id: ${requestId}`);\n }\n groupItems.forEach(item => {\n item.reject(new Error(`No result found for request ${requestId}`));\n });\n return;\n }\n\n if (result.texts.length !== groupItems.length) {\n const error = new Error(`Mismatch: expected ${groupItems.length} texts, got ${result.texts.length} for request_id ${requestId}`);\n if (config.debug) {\n console.error(`[BeLocal Multi Transport]`, error.message);\n }\n groupItems.forEach(item => item.reject(error));\n return;\n }\n\n groupItems.forEach((item, index) => {\n const translatedText = result.texts[index];\n const status = result.status || 'success';\n\n if (config.debug) {\n console.log(`[BeLocal Multi Transport] Success for request_id ${requestId}[${index}]: \"${translatedText}\"`);\n }\n\n item.resolve({ text: translatedText, status });\n });\n });\n } catch (error) {\n if (config.debug) {\n console.error(`[BeLocal Multi Transport] Multi request error:`, error);\n }\n\n const errorToReject = error instanceof Error ? error : new Error(String(error));\n items.forEach(item => item.reject(errorToReject));\n }\n}\n\nfunction processMulti(config: MultiTransportConfig, state: MultiState): void {\n if (state.currentMulti.length === 0 || state.isRequestInFlight) {\n return;\n }\n\n const itemsToSend = [...state.currentMulti];\n state.currentMulti = [];\n state.multiTimer = null;\n state.isRequestInFlight = true;\n\n sendMulti(config, itemsToSend, state).finally(() => {\n state.isRequestInFlight = false;\n\n if (state.currentMulti.length > 0) {\n const windowMs = config.batchWindowMs ?? 50;\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n}\n\nexport function createMultiTransport(config: MultiTransportConfig): Transport {\n const windowMs = config.batchWindowMs ?? 50;\n\n const state: MultiState = {\n currentMulti: [],\n multiTimer: null,\n isRequestInFlight: false,\n };\n\n const transport = (({ text, lang, source_lang, ctx }) => {\n return new Promise<{ text: string; status: string }>((resolve, reject) => {\n if (config.debug) {\n const tempRequestId = md5(JSON.stringify([text, lang, source_lang || null, ctx || null]));\n console.log(`[BeLocal Multi Transport] Queuing request ${tempRequestId}: \"${text}\" to ${lang}`);\n }\n\n const requestItem: MultiRequestItem = {\n text,\n lang,\n sourceLang: source_lang,\n context: ctx,\n resolve,\n reject,\n };\n\n state.currentMulti.push(requestItem);\n\n if (state.multiTimer === null && !state.isRequestInFlight) {\n state.multiTimer = setTimeout(() => processMulti(config, state), windowMs);\n }\n });\n }) as Transport & { destroy: () => void };\n\n transport.destroy = () => {\n if (state.multiTimer) {\n clearTimeout(state.multiTimer);\n state.multiTimer = null;\n }\n state.currentMulti.forEach(item =>\n item.reject(new Error('Transport destroyed'))\n );\n state.currentMulti = [];\n };\n\n return transport;\n}\n","import type { Cache, CacheOptions } from './types';\n\ninterface CacheEntry {\n value: string;\n expiresAt: number;\n}\n\nexport class LocalCache implements Cache {\n private storage = new Map<string, CacheEntry>();\n private maxSize: number;\n private ttlMs: number;\n\n constructor(options: CacheOptions = {}) {\n this.maxSize = options.maxSize ?? 10_000;\n this.ttlMs = options.ttlMs ?? 3_600_000;\n }\n\n get(key: string): string | null {\n const entry = this.storage.get(key);\n if (entry === undefined) return null;\n\n if (Date.now() > entry.expiresAt) {\n this.storage.delete(key);\n return null;\n }\n\n this.storage.delete(key);\n this.storage.set(key, entry);\n\n return entry.value;\n }\n\n set(key: string, value: string): void {\n this.storage.delete(key);\n\n if (this.storage.size >= this.maxSize) {\n const oldestKey = this.storage.keys().next().value;\n if (oldestKey !== undefined) {\n this.storage.delete(oldestKey);\n }\n }\n\n this.storage.set(key, {\n value,\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n clear(): void {\n this.storage.clear();\n }\n}\n","import type { BelocalEngineOptions, Lang, TranslateOptions, TranslationCtx, Transport, BaseTransport } from '../types';\nimport { createMultiTransport } from '../../transports/multi';\nimport { LocalCache } from '../../cache/local';\nimport type { Cache } from '../../cache/types';\nimport { md5 } from 'js-md5';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n private cache: Cache;\n\n constructor(options: BelocalEngineOptions, baseTransportFactory: (opts: any) => BaseTransport) {\n const {\n apiKey,\n batchWindowMs = 50,\n timeoutMs = 10000,\n debug = false,\n cacheTtlMs = 3_600_000,\n cacheMaxSize = 10_000\n } = options;\n\n if (!apiKey || typeof apiKey !== 'string') {\n throw new Error('[BeLocal] apiKey is required and must be a non-empty string');\n }\n\n if (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new Error('[BeLocal] timeoutMs must be a positive finite number');\n }\n\n const safeBatchWindowMs = Math.max(0, batchWindowMs);\n\n this.debug = debug;\n this.cache = new LocalCache({ ttlMs: cacheTtlMs, maxSize: cacheMaxSize });\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`\n };\n\n const baseTransport = baseTransportFactory({\n headers: authHeaders,\n timeoutMs,\n debug: this.debug\n });\n\n this.transport = createMultiTransport({\n baseTransport,\n debug: this.debug,\n batchWindowMs: safeBatchWindowMs\n });\n\n if (this.debug) {\n console.log('[BeLocal Engine] Multi transport created with config:', {\n baseUrl: 'https://dynamic.belocal.dev',\n timeoutMs,\n batchWindowMs: safeBatchWindowMs\n });\n }\n }\n\n /** Translates a single text string to the target language. */\n async translate(text: string, lang: Lang, options?: TranslateOptions): Promise<string> {\n const results = await this.translateMany([text], lang, options);\n return results[0];\n }\n\n /** Translates multiple text strings to the target language in a single batch. */\n async translateMany(texts: string[], lang: Lang, options?: TranslateOptions): Promise<string[]> {\n const { source_lang, ctx } = this.resolveOptions(options);\n const results: (string | null)[] = new Array(texts.length);\n const cacheMisses: Array<{ index: number; text: string }> = [];\n\n for (let i = 0; i < texts.length; i++) {\n const text = texts[i];\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n\n const cachedResult = this.cache.get(cacheKey);\n if (cachedResult !== null) {\n results[i] = cachedResult;\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from cache:', text);\n }\n continue;\n }\n\n results[i] = null;\n cacheMisses.push({ index: i, text });\n }\n\n if (cacheMisses.length > 0) {\n const settlements = await Promise.allSettled(\n cacheMisses.map(async ({ index, text }) => {\n const result = await this.transport({ text, lang, source_lang, ctx });\n\n if (result.status !== 'error') {\n const cacheKey = this.generateCacheKey(text, lang, source_lang, ctx);\n this.cache.set(cacheKey, result.text);\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API, cached:', text);\n }\n } else {\n if (this.debug) {\n console.log('[BeLocal Engine] Translation from API (not cached due to error status):', text);\n }\n }\n\n return { index, translation: result.text };\n })\n );\n\n settlements.forEach((settlement, i) => {\n const { index, text } = cacheMisses[i];\n if (settlement.status === 'fulfilled') {\n results[index] = settlement.value.translation;\n } else {\n results[index] = text;\n if (this.debug) {\n const reason = settlement.reason;\n console.error(\n '[BeLocal Engine] Translation failed, using original text:',\n text,\n reason instanceof Error ? reason.message : String(reason)\n );\n }\n }\n });\n }\n\n return results as string[];\n }\n\n private resolveOptions(options?: TranslateOptions): { source_lang?: string; ctx?: TranslationCtx } {\n if (!options) return {};\n const serverCtx: TranslationCtx = {\n ...options.ctx,\n ...(options.context && { user_ctx: options.context }),\n ...(options.managed && { cache_type: 'managed' }),\n };\n const ctx = Object.values(serverCtx).some(Boolean) ? serverCtx : undefined;\n return { source_lang: options.source_lang, ctx };\n }\n\n /** Cleans up internal resources (timers, cache). Call when the engine is no longer needed. */\n destroy(): void {\n (this.transport as any).destroy?.();\n this.cache.clear();\n }\n\n private generateCacheKey(text: string, lang: Lang, source_lang?: string, ctx?: TranslationCtx): string {\n const sortedCtx = ctx\n ? Object.fromEntries(Object.entries(ctx).sort(([a], [b]) => a.localeCompare(b)))\n : null;\n\n const data = {\n text,\n lang,\n source_lang: source_lang || null,\n ctx: sortedCtx\n };\n return md5(JSON.stringify(data));\n }\n}\n","export type Lang = string;\n\nexport type UserCtx = {\n user_type?: string;\n entity_key?: string;\n entity_id?: string;\n};\n\nexport type TranslationCtx = {\n user_type?: string;\n user_ctx?: string;\n cache_type?: string;\n entity_key?: string;\n entity_id?: string;\n};\n\nexport const USER_TYPE_PRODUCT = 'product';\nexport const USER_TYPE_CHAT = 'chat';\n\nexport type TranslateOptions = {\n source_lang?: string;\n context?: string;\n managed?: boolean;\n ctx?: UserCtx;\n};\n\nexport interface BaseTransport {\n post(data: any, endpointPath: string): Promise<any>;\n}\n\nexport type Transport = (params: { text: string; lang: Lang; source_lang?: string; ctx?: TranslationCtx }) => Promise<{ text: string; status: string }>;\n\nexport interface BelocalEngineOptions {\n apiKey: string;\n batchWindowMs?: number;\n timeoutMs?: number;\n debug?: boolean;\n cacheTtlMs?: number;\n cacheMaxSize?: number;\n}\n","import type { BelocalEngineOptions } from '../types';\nimport { createBaseBrowserTransport } from '../../transports/base/browser';\nimport { BelocalEngine as BaseEngine } from './engine';\n\nexport class BelocalEngine extends BaseEngine {\n constructor(options: BelocalEngineOptions) {\n super(options, createBaseBrowserTransport);\n }\n}\n\nexport type { BelocalEngineOptions, Lang, TranslateOptions, BaseTransport, TranslationCtx, UserCtx } from '../types';\nexport { USER_TYPE_PRODUCT, USER_TYPE_CHAT } from '../types';\nexport { createMultiTransport } from '../../transports/multi';\nexport { BaseBrowserTransport, createBaseBrowserTransport } from '../../transports/base';\n"]}