@belocal/js-sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,28 @@
1
1
  'use strict';
2
2
 
3
+ var http2 = require('http2');
4
+ var url = require('url');
5
+
6
+ function _interopNamespace(e) {
7
+ if (e && e.__esModule) return e;
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var http2__namespace = /*#__PURE__*/_interopNamespace(http2);
25
+
3
26
  // src/transports/browser.ts
4
27
  function createBrowserTransport(config) {
5
28
  return async ({ text, lang, ctx }) => {
@@ -39,43 +62,94 @@ function createBrowserTransport(config) {
39
62
  }
40
63
  };
41
64
  }
42
-
43
- // src/transports/node.ts
65
+ var sessionCache = /* @__PURE__ */ new Map();
66
+ function getOrCreateSession(baseUrl) {
67
+ if (sessionCache.has(baseUrl)) {
68
+ const session2 = sessionCache.get(baseUrl);
69
+ if (!session2.destroyed) {
70
+ return session2;
71
+ }
72
+ sessionCache.delete(baseUrl);
73
+ }
74
+ const parsedUrl = new url.URL(baseUrl);
75
+ const session = http2__namespace.connect(parsedUrl.origin);
76
+ session.on("error", () => {
77
+ sessionCache.delete(baseUrl);
78
+ });
79
+ session.on("close", () => {
80
+ sessionCache.delete(baseUrl);
81
+ });
82
+ sessionCache.set(baseUrl, session);
83
+ return session;
84
+ }
85
+ function makeHttp2Request(session, path, headers, body, timeoutMs) {
86
+ return new Promise((resolve, reject) => {
87
+ const req = session.request({
88
+ ":method": "POST",
89
+ ":path": path,
90
+ "content-type": "application/json",
91
+ "content-length": Buffer.byteLength(body),
92
+ ...headers
93
+ });
94
+ let timeout = null;
95
+ if (timeoutMs) {
96
+ timeout = setTimeout(() => {
97
+ req.destroy();
98
+ reject(new Error(`Request timeout after ${timeoutMs}ms`));
99
+ }, timeoutMs);
100
+ }
101
+ let responseData = "";
102
+ let statusCode = 0;
103
+ let responseHeaders = {};
104
+ req.on("response", (headers2) => {
105
+ statusCode = headers2[":status"];
106
+ responseHeaders = headers2;
107
+ });
108
+ req.on("data", (chunk) => {
109
+ responseData += chunk;
110
+ });
111
+ req.on("end", () => {
112
+ if (timeout) clearTimeout(timeout);
113
+ resolve({
114
+ statusCode,
115
+ headers: responseHeaders,
116
+ body: responseData
117
+ });
118
+ });
119
+ req.on("error", (error) => {
120
+ if (timeout) clearTimeout(timeout);
121
+ reject(error);
122
+ });
123
+ req.write(body);
124
+ req.end();
125
+ });
126
+ }
44
127
  function createNodeTransport(config) {
45
128
  return async ({ text, lang, ctx }) => {
46
- const url = `${config.baseUrl}${config.path}`;
47
129
  const maxRetries = config.retries || 0;
48
130
  let attempt = 0;
49
131
  if (config.debug) {
50
- console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
132
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${config.baseUrl}${config.path}`);
51
133
  }
52
134
  while (attempt <= maxRetries) {
53
135
  try {
54
- const controller = new AbortController();
55
- const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
56
- try {
57
- const response = await fetch(url, {
58
- method: "POST",
59
- headers: {
60
- "Content-Type": "application/json",
61
- ...config.headers
62
- },
63
- body: JSON.stringify({ text, lang, ctx }),
64
- signal: controller.signal
65
- });
66
- if (!response.ok) {
67
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
68
- }
69
- const result = await response.json();
70
- if (config.debug) {
71
- console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
72
- }
73
- return result.text || text;
74
- } finally {
75
- if (timeoutId) {
76
- clearTimeout(timeoutId);
77
- }
136
+ const session = getOrCreateSession(config.baseUrl);
137
+ const body = JSON.stringify({ text, lang, ctx });
138
+ const response = await makeHttp2Request(
139
+ session,
140
+ config.path,
141
+ config.headers || {},
142
+ body,
143
+ config.timeoutMs
144
+ );
145
+ if (response.statusCode < 200 || response.statusCode >= 300) {
146
+ throw new Error(`HTTP ${response.statusCode}: Request failed`);
147
+ }
148
+ const result = JSON.parse(response.body);
149
+ if (config.debug) {
150
+ console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
78
151
  }
152
+ return result.text || text;
79
153
  } catch (error) {
80
154
  attempt++;
81
155
  if (config.debug) {
@@ -102,7 +176,6 @@ var BelocalEngine = class {
102
176
  retries = 3,
103
177
  credentials,
104
178
  headers = {},
105
- agent,
106
179
  debug = false
107
180
  } = options;
108
181
  this.debug = debug;
@@ -116,7 +189,6 @@ var BelocalEngine = class {
116
189
  retries,
117
190
  credentials,
118
191
  headers: authHeaders,
119
- agent,
120
192
  debug: this.debug
121
193
  });
122
194
  }
@@ -132,7 +204,7 @@ var BelocalEngine = class {
132
204
  path,
133
205
  timeoutMs: config.timeoutMs,
134
206
  ...actualTransport === "browser" && { credentials: config.credentials },
135
- ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
207
+ ...actualTransport === "node" && { retries: config.retries }
136
208
  });
137
209
  }
138
210
  if (actualTransport === "browser") {
@@ -150,7 +222,6 @@ var BelocalEngine = class {
150
222
  path,
151
223
  headers: config.headers,
152
224
  timeoutMs: config.timeoutMs,
153
- agent: config.agent,
154
225
  retries: config.retries,
155
226
  debug: config.debug
156
227
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":[],"mappings":";;;AAWO,SAAS,uBAAuB,MAAA,EAA2C;AAChF,EAAA,OAAO,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAI,KAAM;AACpC,IAAA,MAAM,MAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,EAAG,OAAO,IAAI,CAAA,CAAA;AAC3C,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,SAAA,GAAY,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,MAAA,CAAO,SAAS,CAAA,GAAI,IAAA;AAE9F,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,OAAA,CAAQ,IAAI,CAAA,yCAAA,EAA4C,IAAI,QAAQ,IAAI,CAAA,UAAA,EAAa,GAAG,CAAA,CAAE,CAAA;AAAA,IAC5F;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAChC,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,GAAG,MAAA,CAAO;AAAA,SACZ;AAAA,QACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,IAAA,EAAM,KAAK,CAAA;AAAA,QACxC,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,WAAW,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAChE,QAAA,IAAI,OAAO,KAAA,EAAO;AAChB,UAAA,OAAA,CAAQ,KAAA,CAAM,+CAA+C,QAAQ,CAAA;AAAA,QACvE;AACA,QAAA,MAAM,IAAI,MAAM,QAAQ,CAAA;AAAA,MAC1B;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,MAAA,IAAI,OAAO,KAAA,EAAO;AAChB,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,qDAAA,EAAwD,MAAA,CAAO,IAAA,IAAQ,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,MAC5F;AACA,MAAA,OAAO,OAAO,IAAA,IAAQ,IAAA;AAAA,IACxB,CAAA,SAAE;AACA,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,YAAA,CAAa,SAAS,CAAA;AAAA,MACxB;AAAA,IACF;AAAA,EACF,CAAA;AACF;;;ACxCO,SAAS,oBAAoB,MAAA,EAAwC;AAC1E,EAAA,OAAO,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAI,KAAM;AACpC,IAAA,MAAM,MAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,EAAG,OAAO,IAAI,CAAA,CAAA;AAC3C,IAAA,MAAM,UAAA,GAAa,OAAO,OAAA,IAAW,CAAA;AACrC,IAAA,IAAI,OAAA,GAAU,CAAA;AAEd,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,OAAA,CAAQ,IAAI,CAAA,sCAAA,EAAyC,IAAI,QAAQ,IAAI,CAAA,UAAA,EAAa,GAAG,CAAA,CAAE,CAAA;AAAA,IACzF;AAEA,IAAA,OAAO,WAAW,UAAA,EAAY;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,QAAA,MAAM,SAAA,GAAY,MAAA,CAAO,SAAA,GAAY,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,MAAA,CAAO,SAAS,CAAA,GAAI,IAAA;AAE9F,QAAA,IAAI;AACF,UAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,YAChC,MAAA,EAAQ,MAAA;AAAA,YACR,OAAA,EAAS;AAAA,cACP,cAAA,EAAgB,kBAAA;AAAA,cAChB,GAAG,MAAA,CAAO;AAAA,aACZ;AAAA,YACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,IAAA,EAAM,KAAK,CAAA;AAAA,YACxC,QAAQ,UAAA,CAAW;AAAA,WACpB,CAAA;AAED,UAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,YAAA,MAAM,IAAI,MAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,UACnE;AAEA,UAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,UAAA,IAAI,OAAO,KAAA,EAAO;AAChB,YAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kDAAA,EAAqD,MAAA,CAAO,IAAA,IAAQ,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,UACzF;AACA,UAAA,OAAO,OAAO,IAAA,IAAQ,IAAA;AAAA,QACxB,CAAA,SAAE;AACA,UAAA,IAAI,SAAA,EAAW;AACb,YAAA,YAAA,CAAa,SAAS,CAAA;AAAA,UACxB;AAAA,QACF;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,EAAA;AACA,QAAA,IAAI,OAAO,KAAA,EAAO;AAChB,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iCAAA,EAAoC,OAAO,CAAA,QAAA,CAAA,EAAY,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,QAC7H;AACA,QAAA,IAAI,UAAU,UAAA,EAAY;AACxB,UAAA,MAAM,KAAA;AAAA,QACR;AAEA,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAA,OAAA,KAAW,UAAA,CAAW,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAA,GAAI,GAAI,CAAC,CAAA;AAAA,MAC/E;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF;;;AC/DO,IAAM,gBAAN,MAAoB;AAAA,EAIzB,YAAY,OAAA,EAA+B;AACzC,IAAA,MAAM;AAAA,MACJ,MAAA;AAAA,MACA,OAAA,GAAU,6BAAA;AAAA,MACV,SAAA,GAAY,MAAA;AAAA,MACZ,SAAA,GAAY,GAAA;AAAA,MACZ,OAAA,GAAU,CAAA;AAAA,MACV,WAAA;AAAA,MACA,UAAU,EAAC;AAAA,MACX,KAAA;AAAA,MACA,KAAA,GAAQ;AAAA,KACV,GAAI,OAAA;AAEJ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAEb,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,eAAA,EAAiB,UAAU,MAAM,CAAA,CAAA;AAAA,MACjC,GAAG;AAAA,KACL;AAEA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,eAAA,CAAgB,SAAA,EAAW;AAAA,MAC/C,OAAA;AAAA,MACA,SAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,WAAA;AAAA,MACT,KAAA;AAAA,MACA,OAAO,IAAA,CAAK;AAAA,KACb,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,CAAA,CAAE,IAAA,EAAc,IAAA,EAAY,GAAA,EAA2B;AAC3D,IAAA,OAAO,KAAK,SAAA,CAAU,EAAE,IAAA,EAAM,IAAA,EAAM,KAAK,CAAA;AAAA,EAC3C;AAAA,EAEQ,eAAA,CACN,eACA,MAAA,EASW;AACX,IAAA,MAAM,eAAA,GAAkB,aAAA,KAAkB,MAAA,GAAS,IAAA,CAAK,mBAAkB,GAAI,aAAA;AAC9E,IAAA,MAAM,IAAA,GAAO,eAAA;AAEb,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,0BAAA,EAA6B,eAAe,CAAA,uBAAA,CAAA,EAA2B;AAAA,QACjF,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,IAAA;AAAA,QACA,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,GAAI,eAAA,KAAoB,SAAA,IAAa,EAAE,WAAA,EAAa,OAAO,WAAA,EAAY;AAAA,QACvE,GAAI,eAAA,KAAoB,MAAA,IAAU,EAAE,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,QAAA,EAAU,CAAC,CAAC,MAAA,CAAO,KAAA;AAAM,OACvF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,oBAAoB,SAAA,EAAW;AACjC,MAAA,OAAO,sBAAA,CAAuB;AAAA,QAC5B,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,IAAA;AAAA,QACA,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,OAAO,MAAA,CAAO;AAAA,OACf,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,OAAO,mBAAA,CAAoB;AAAA,QACzB,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,IAAA;AAAA,QACA,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,OAAO,MAAA,CAAO;AAAA,OACf,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,GAAwC;AAC9C,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,MAAA,CAAO,aAAa,WAAA,EAAa;AAC3E,MAAA,OAAO,SAAA;AAAA,IACT;AAEA,IAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,QAAQ,QAAA,IAAY,OAAA,CAAQ,SAAS,IAAA,EAAM;AAC/E,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF","file":"index.cjs","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n agent?: unknown;\n retries?: number;\n debug?: boolean;\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n // Exponential backoff\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text; // fallback\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n agent,\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n agent,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n agent?: unknown;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries, hasAgent: !!config.agent })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n agent: config.agent,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":["session","URL","http2","headers"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import * as http2 from 'node:http2';\nimport { URL } from 'node:url';\nimport type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n retries?: number;\n debug?: boolean;\n}\n\n// Global session cache for HTTP/2 connections\nconst sessionCache = new Map<string, http2.ClientHttp2Session>();\n\nfunction getOrCreateSession(baseUrl: string): http2.ClientHttp2Session {\n if (sessionCache.has(baseUrl)) {\n const session = sessionCache.get(baseUrl)!;\n if (!session.destroyed) {\n return session;\n }\n sessionCache.delete(baseUrl);\n }\n\n const parsedUrl = new URL(baseUrl);\n const session = http2.connect(parsedUrl.origin);\n \n // Set up session cleanup\n session.on('error', () => {\n sessionCache.delete(baseUrl);\n });\n \n session.on('close', () => {\n sessionCache.delete(baseUrl);\n });\n \n sessionCache.set(baseUrl, session);\n return session;\n}\n\nfunction makeHttp2Request(\n session: http2.ClientHttp2Session,\n path: string,\n headers: Record<string, string>,\n body: string,\n timeoutMs?: number\n): Promise<{ statusCode: number; headers: Record<string, string>; body: string }> {\n return new Promise((resolve, reject) => {\n const req = session.request({\n ':method': 'POST',\n ':path': path,\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(body),\n ...headers,\n });\n\n let timeout: NodeJS.Timeout | null = null;\n if (timeoutMs) {\n timeout = setTimeout(() => {\n req.destroy();\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n }\n\n let responseData = '';\n let statusCode = 0;\n let responseHeaders: Record<string, string> = {};\n\n req.on('response', (headers) => {\n statusCode = headers[':status'] as number;\n responseHeaders = headers as Record<string, string>;\n });\n\n req.on('data', (chunk) => {\n responseData += chunk;\n });\n\n req.on('end', () => {\n if (timeout) clearTimeout(timeout);\n resolve({\n statusCode,\n headers: responseHeaders,\n body: responseData,\n });\n });\n\n req.on('error', (error) => {\n if (timeout) clearTimeout(timeout);\n reject(error);\n });\n\n req.write(body);\n req.end();\n });\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${config.baseUrl}${config.path}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const session = getOrCreateSession(config.baseUrl);\n const body = JSON.stringify({ text, lang, ctx });\n \n const response = await makeHttp2Request(\n session,\n config.path,\n config.headers || {},\n body,\n config.timeoutMs\n );\n\n if (response.statusCode < 200 || response.statusCode >= 300) {\n throw new Error(`HTTP ${response.statusCode}: Request failed`);\n }\n\n const result = JSON.parse(response.body);\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text;\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -8,7 +8,6 @@ interface BelocalEngineOptions {
8
8
  retries?: number;
9
9
  credentials?: RequestCredentials;
10
10
  headers?: Record<string, string>;
11
- agent?: unknown;
12
11
  debug?: boolean;
13
12
  }
14
13
 
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import * as http2 from 'http2';
2
+ import { URL } from 'url';
3
+
1
4
  // src/transports/browser.ts
2
5
  function createBrowserTransport(config) {
3
6
  return async ({ text, lang, ctx }) => {
@@ -37,43 +40,94 @@ function createBrowserTransport(config) {
37
40
  }
38
41
  };
39
42
  }
40
-
41
- // src/transports/node.ts
43
+ var sessionCache = /* @__PURE__ */ new Map();
44
+ function getOrCreateSession(baseUrl) {
45
+ if (sessionCache.has(baseUrl)) {
46
+ const session2 = sessionCache.get(baseUrl);
47
+ if (!session2.destroyed) {
48
+ return session2;
49
+ }
50
+ sessionCache.delete(baseUrl);
51
+ }
52
+ const parsedUrl = new URL(baseUrl);
53
+ const session = http2.connect(parsedUrl.origin);
54
+ session.on("error", () => {
55
+ sessionCache.delete(baseUrl);
56
+ });
57
+ session.on("close", () => {
58
+ sessionCache.delete(baseUrl);
59
+ });
60
+ sessionCache.set(baseUrl, session);
61
+ return session;
62
+ }
63
+ function makeHttp2Request(session, path, headers, body, timeoutMs) {
64
+ return new Promise((resolve, reject) => {
65
+ const req = session.request({
66
+ ":method": "POST",
67
+ ":path": path,
68
+ "content-type": "application/json",
69
+ "content-length": Buffer.byteLength(body),
70
+ ...headers
71
+ });
72
+ let timeout = null;
73
+ if (timeoutMs) {
74
+ timeout = setTimeout(() => {
75
+ req.destroy();
76
+ reject(new Error(`Request timeout after ${timeoutMs}ms`));
77
+ }, timeoutMs);
78
+ }
79
+ let responseData = "";
80
+ let statusCode = 0;
81
+ let responseHeaders = {};
82
+ req.on("response", (headers2) => {
83
+ statusCode = headers2[":status"];
84
+ responseHeaders = headers2;
85
+ });
86
+ req.on("data", (chunk) => {
87
+ responseData += chunk;
88
+ });
89
+ req.on("end", () => {
90
+ if (timeout) clearTimeout(timeout);
91
+ resolve({
92
+ statusCode,
93
+ headers: responseHeaders,
94
+ body: responseData
95
+ });
96
+ });
97
+ req.on("error", (error) => {
98
+ if (timeout) clearTimeout(timeout);
99
+ reject(error);
100
+ });
101
+ req.write(body);
102
+ req.end();
103
+ });
104
+ }
42
105
  function createNodeTransport(config) {
43
106
  return async ({ text, lang, ctx }) => {
44
- const url = `${config.baseUrl}${config.path}`;
45
107
  const maxRetries = config.retries || 0;
46
108
  let attempt = 0;
47
109
  if (config.debug) {
48
- console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
110
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${config.baseUrl}${config.path}`);
49
111
  }
50
112
  while (attempt <= maxRetries) {
51
113
  try {
52
- const controller = new AbortController();
53
- const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
54
- try {
55
- const response = await fetch(url, {
56
- method: "POST",
57
- headers: {
58
- "Content-Type": "application/json",
59
- ...config.headers
60
- },
61
- body: JSON.stringify({ text, lang, ctx }),
62
- signal: controller.signal
63
- });
64
- if (!response.ok) {
65
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
66
- }
67
- const result = await response.json();
68
- if (config.debug) {
69
- console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
70
- }
71
- return result.text || text;
72
- } finally {
73
- if (timeoutId) {
74
- clearTimeout(timeoutId);
75
- }
114
+ const session = getOrCreateSession(config.baseUrl);
115
+ const body = JSON.stringify({ text, lang, ctx });
116
+ const response = await makeHttp2Request(
117
+ session,
118
+ config.path,
119
+ config.headers || {},
120
+ body,
121
+ config.timeoutMs
122
+ );
123
+ if (response.statusCode < 200 || response.statusCode >= 300) {
124
+ throw new Error(`HTTP ${response.statusCode}: Request failed`);
125
+ }
126
+ const result = JSON.parse(response.body);
127
+ if (config.debug) {
128
+ console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
76
129
  }
130
+ return result.text || text;
77
131
  } catch (error) {
78
132
  attempt++;
79
133
  if (config.debug) {
@@ -100,7 +154,6 @@ var BelocalEngine = class {
100
154
  retries = 3,
101
155
  credentials,
102
156
  headers = {},
103
- agent,
104
157
  debug = false
105
158
  } = options;
106
159
  this.debug = debug;
@@ -114,7 +167,6 @@ var BelocalEngine = class {
114
167
  retries,
115
168
  credentials,
116
169
  headers: authHeaders,
117
- agent,
118
170
  debug: this.debug
119
171
  });
120
172
  }
@@ -130,7 +182,7 @@ var BelocalEngine = class {
130
182
  path,
131
183
  timeoutMs: config.timeoutMs,
132
184
  ...actualTransport === "browser" && { credentials: config.credentials },
133
- ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
185
+ ...actualTransport === "node" && { retries: config.retries }
134
186
  });
135
187
  }
136
188
  if (actualTransport === "browser") {
@@ -148,7 +200,6 @@ var BelocalEngine = class {
148
200
  path,
149
201
  headers: config.headers,
150
202
  timeoutMs: config.timeoutMs,
151
- agent: config.agent,
152
203
  retries: config.retries,
153
204
  debug: config.debug
154
205
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n agent?: unknown;\n retries?: number;\n debug?: boolean;\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n // Exponential backoff\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text; // fallback\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n agent,\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n agent,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n agent?: unknown;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries, hasAgent: !!config.agent })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n agent: config.agent,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":["session","headers"],"mappings":"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","file":"index.js","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import * as http2 from 'node:http2';\nimport { URL } from 'node:url';\nimport type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n retries?: number;\n debug?: boolean;\n}\n\n// Global session cache for HTTP/2 connections\nconst sessionCache = new Map<string, http2.ClientHttp2Session>();\n\nfunction getOrCreateSession(baseUrl: string): http2.ClientHttp2Session {\n if (sessionCache.has(baseUrl)) {\n const session = sessionCache.get(baseUrl)!;\n if (!session.destroyed) {\n return session;\n }\n sessionCache.delete(baseUrl);\n }\n\n const parsedUrl = new URL(baseUrl);\n const session = http2.connect(parsedUrl.origin);\n \n // Set up session cleanup\n session.on('error', () => {\n sessionCache.delete(baseUrl);\n });\n \n session.on('close', () => {\n sessionCache.delete(baseUrl);\n });\n \n sessionCache.set(baseUrl, session);\n return session;\n}\n\nfunction makeHttp2Request(\n session: http2.ClientHttp2Session,\n path: string,\n headers: Record<string, string>,\n body: string,\n timeoutMs?: number\n): Promise<{ statusCode: number; headers: Record<string, string>; body: string }> {\n return new Promise((resolve, reject) => {\n const req = session.request({\n ':method': 'POST',\n ':path': path,\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(body),\n ...headers,\n });\n\n let timeout: NodeJS.Timeout | null = null;\n if (timeoutMs) {\n timeout = setTimeout(() => {\n req.destroy();\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n }\n\n let responseData = '';\n let statusCode = 0;\n let responseHeaders: Record<string, string> = {};\n\n req.on('response', (headers) => {\n statusCode = headers[':status'] as number;\n responseHeaders = headers as Record<string, string>;\n });\n\n req.on('data', (chunk) => {\n responseData += chunk;\n });\n\n req.on('end', () => {\n if (timeout) clearTimeout(timeout);\n resolve({\n statusCode,\n headers: responseHeaders,\n body: responseData,\n });\n });\n\n req.on('error', (error) => {\n if (timeout) clearTimeout(timeout);\n reject(error);\n });\n\n req.write(body);\n req.end();\n });\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${config.baseUrl}${config.path}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const session = getOrCreateSession(config.baseUrl);\n const body = JSON.stringify({ text, lang, ctx });\n \n const response = await makeHttp2Request(\n session,\n config.path,\n config.headers || {},\n body,\n config.timeoutMs\n );\n\n if (response.statusCode < 200 || response.statusCode >= 300) {\n throw new Error(`HTTP ${response.statusCode}: Request failed`);\n }\n\n const result = JSON.parse(response.body);\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text;\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- function c(r){return async({text:t,lang:e,ctx:o})=>{let n=`${r.baseUrl}${r.path}`,u=new AbortController,a=r.timeoutMs?setTimeout(()=>u.abort(),r.timeoutMs):null;r.debug&&console.log(`[BeLocal Browser Transport] Translating "${t}" to ${e} with url ${n}`);try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",...r.headers},body:JSON.stringify({text:t,lang:e,ctx:o}),credentials:r.credentials,signal:u.signal});if(!s.ok){let l=`HTTP ${s.status}: ${s.statusText}`;throw r.debug&&console.error("[BeLocal Browser Transport] Request failed:",l),new Error(l)}let i=await s.json();return r.debug&&console.log(`[BeLocal Browser Transport] Translation successful: "${i.text||t}"`),i.text||t}finally{a&&clearTimeout(a);}}}function b(r){return async({text:t,lang:e,ctx:o})=>{let n=`${r.baseUrl}${r.path}`,u=r.retries||0,a=0;for(r.debug&&console.log(`[BeLocal Node Transport] Translating "${t}" to ${e} with url ${n}`);a<=u;)try{let s=new AbortController,i=r.timeoutMs?setTimeout(()=>s.abort(),r.timeoutMs):null;try{let l=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",...r.headers},body:JSON.stringify({text:t,lang:e,ctx:o}),signal:s.signal});if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);let p=await l.json();return r.debug&&console.log(`[BeLocal Node Transport] Translation successful: "${p.text||t}"`),p.text||t}finally{i&&clearTimeout(i);}}catch(s){if(a++,r.debug&&console.error(`[BeLocal Node Transport] Attempt ${a} failed:`,s instanceof Error?s.message:String(s)),a>u)throw s;await new Promise(i=>setTimeout(i,Math.pow(2,a)*1e3));}return t}}var d=class{constructor(t){let{apiKey:e,baseUrl:o="https://dynamic.belocal.dev",transport:n="auto",timeoutMs:u=1e4,retries:a=3,credentials:s,headers:i={},agent:l,debug:p=false}=t;this.debug=p;let m={Authorization:`Bearer ${e}`,...i};this.transport=this.createTransport(n,{baseUrl:o,timeoutMs:u,retries:a,credentials:s,headers:m,agent:l,debug:this.debug});}async t(t,e,o){return this.transport({text:t,lang:e,ctx:o})}createTransport(t,e){let o=t==="auto"?this.detectEnvironment():t,n="/v1/translate";return e.debug&&console.log(`[BeLocal Engine] Creating ${o} transport with config:`,{baseUrl:e.baseUrl,path:n,timeoutMs:e.timeoutMs,...o==="browser"&&{credentials:e.credentials},...o==="node"&&{retries:e.retries,hasAgent:!!e.agent}}),o==="browser"?c({baseUrl:e.baseUrl,path:n,credentials:e.credentials,headers:e.headers,timeoutMs:e.timeoutMs,debug:e.debug}):b({baseUrl:e.baseUrl,path:n,headers:e.headers,timeoutMs:e.timeoutMs,agent:e.agent,retries:e.retries,debug:e.debug})}detectEnvironment(){return typeof window<"u"&&typeof window.document<"u"?"browser":(typeof process<"u"&&process.versions&&process.versions.node,"node")}};
2
- export{d as BelocalEngine};//# sourceMappingURL=index.mjs.map
1
+ import*as g from'http2';import {URL}from'url';function b(t){return async({text:r,lang:e,ctx:s})=>{let n=`${t.baseUrl}${t.path}`,u=new AbortController,i=t.timeoutMs?setTimeout(()=>u.abort(),t.timeoutMs):null;t.debug&&console.log(`[BeLocal Browser Transport] Translating "${r}" to ${e} with url ${n}`);try{let o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify({text:r,lang:e,ctx:s}),credentials:t.credentials,signal:u.signal});if(!o.ok){let d=`HTTP ${o.status}: ${o.statusText}`;throw t.debug&&console.error("[BeLocal Browser Transport] Request failed:",d),new Error(d)}let a=await o.json();return t.debug&&console.log(`[BeLocal Browser Transport] Translation successful: "${a.text||r}"`),a.text||r}finally{i&&clearTimeout(i);}}}var l=new Map;function y(t){if(l.has(t)){let s=l.get(t);if(!s.destroyed)return s;l.delete(t);}let r=new URL(t),e=g.connect(r.origin);return e.on("error",()=>{l.delete(t);}),e.on("close",()=>{l.delete(t);}),l.set(t,e),e}function f(t,r,e,s,n){return new Promise((u,i)=>{let o=t.request({":method":"POST",":path":r,"content-type":"application/json","content-length":Buffer.byteLength(s),...e}),a=null;n&&(a=setTimeout(()=>{o.destroy(),i(new Error(`Request timeout after ${n}ms`));},n));let d="",c=0,h={};o.on("response",p=>{c=p[":status"],h=p;}),o.on("data",p=>{d+=p;}),o.on("end",()=>{a&&clearTimeout(a),u({statusCode:c,headers:h,body:d});}),o.on("error",p=>{a&&clearTimeout(a),i(p);}),o.write(s),o.end();})}function T(t){return async({text:r,lang:e,ctx:s})=>{let n=t.retries||0,u=0;for(t.debug&&console.log(`[BeLocal Node Transport] Translating "${r}" to ${e} with url ${t.baseUrl}${t.path}`);u<=n;)try{let i=y(t.baseUrl),o=JSON.stringify({text:r,lang:e,ctx:s}),a=await f(i,t.path,t.headers||{},o,t.timeoutMs);if(a.statusCode<200||a.statusCode>=300)throw new Error(`HTTP ${a.statusCode}: Request failed`);let d=JSON.parse(a.body);return t.debug&&console.log(`[BeLocal Node Transport] Translation successful: "${d.text||r}"`),d.text||r}catch(i){if(u++,t.debug&&console.error(`[BeLocal Node Transport] Attempt ${u} failed:`,i instanceof Error?i.message:String(i)),u>n)throw i;await new Promise(o=>setTimeout(o,Math.pow(2,u)*1e3));}return r}}var m=class{constructor(r){let{apiKey:e,baseUrl:s="https://dynamic.belocal.dev",transport:n="auto",timeoutMs:u=1e4,retries:i=3,credentials:o,headers:a={},debug:d=false}=r;this.debug=d;let c={Authorization:`Bearer ${e}`,...a};this.transport=this.createTransport(n,{baseUrl:s,timeoutMs:u,retries:i,credentials:o,headers:c,debug:this.debug});}async t(r,e,s){return this.transport({text:r,lang:e,ctx:s})}createTransport(r,e){let s=r==="auto"?this.detectEnvironment():r,n="/v1/translate";return e.debug&&console.log(`[BeLocal Engine] Creating ${s} transport with config:`,{baseUrl:e.baseUrl,path:n,timeoutMs:e.timeoutMs,...s==="browser"&&{credentials:e.credentials},...s==="node"&&{retries:e.retries}}),s==="browser"?b({baseUrl:e.baseUrl,path:n,credentials:e.credentials,headers:e.headers,timeoutMs:e.timeoutMs,debug:e.debug}):T({baseUrl:e.baseUrl,path:n,headers:e.headers,timeoutMs:e.timeoutMs,retries:e.retries,debug:e.debug})}detectEnvironment(){return typeof window<"u"&&typeof window.document<"u"?"browser":(typeof process<"u"&&process.versions&&process.versions.node,"node")}};
2
+ export{m as BelocalEngine};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":["createBrowserTransport","config","text","lang","ctx","url","controller","timeoutId","response","errorMsg","result","createNodeTransport","maxRetries","attempt","error","resolve","BelocalEngine","options","apiKey","baseUrl","transport","timeoutMs","retries","credentials","headers","agent","debug","authHeaders","transportType","actualTransport","path"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n agent?: unknown;\n retries?: number;\n debug?: boolean;\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n // Exponential backoff\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text; // fallback\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n agent,\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n agent,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n agent?: unknown;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries, hasAgent: !!config.agent })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n agent: config.agent,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":["createBrowserTransport","config","text","lang","ctx","url","controller","timeoutId","response","errorMsg","result","sessionCache","getOrCreateSession","baseUrl","session","parsedUrl","URL","makeHttp2Request","path","headers","body","timeoutMs","resolve","reject","req","timeout","responseData","statusCode","responseHeaders","chunk","error","createNodeTransport","maxRetries","attempt","BelocalEngine","options","apiKey","transport","retries","credentials","debug","authHeaders","transportType","actualTransport"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Transport } from '../core/types';\n\nexport interface BrowserTransportConfig {\n baseUrl: string;\n path?: string;\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n timeoutMs?: number;\n debug?: boolean;\n}\n\nexport function createBrowserTransport(config: BrowserTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const url = `${config.baseUrl}${config.path}`;\n const controller = new AbortController();\n const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;\n\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translating \"${text}\" to ${lang} with url ${url}`);\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n body: JSON.stringify({ text, lang, ctx }),\n credentials: config.credentials,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n if (config.debug) {\n console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n const result = await response.json();\n if (config.debug) {\n console.log(`[BeLocal Browser Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n };\n}","import * as http2 from 'node:http2';\nimport { URL } from 'node:url';\nimport type { Transport } from '../core/types';\n\nexport interface NodeTransportConfig {\n baseUrl: string;\n path: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n retries?: number;\n debug?: boolean;\n}\n\n// Global session cache for HTTP/2 connections\nconst sessionCache = new Map<string, http2.ClientHttp2Session>();\n\nfunction getOrCreateSession(baseUrl: string): http2.ClientHttp2Session {\n if (sessionCache.has(baseUrl)) {\n const session = sessionCache.get(baseUrl)!;\n if (!session.destroyed) {\n return session;\n }\n sessionCache.delete(baseUrl);\n }\n\n const parsedUrl = new URL(baseUrl);\n const session = http2.connect(parsedUrl.origin);\n \n // Set up session cleanup\n session.on('error', () => {\n sessionCache.delete(baseUrl);\n });\n \n session.on('close', () => {\n sessionCache.delete(baseUrl);\n });\n \n sessionCache.set(baseUrl, session);\n return session;\n}\n\nfunction makeHttp2Request(\n session: http2.ClientHttp2Session,\n path: string,\n headers: Record<string, string>,\n body: string,\n timeoutMs?: number\n): Promise<{ statusCode: number; headers: Record<string, string>; body: string }> {\n return new Promise((resolve, reject) => {\n const req = session.request({\n ':method': 'POST',\n ':path': path,\n 'content-type': 'application/json',\n 'content-length': Buffer.byteLength(body),\n ...headers,\n });\n\n let timeout: NodeJS.Timeout | null = null;\n if (timeoutMs) {\n timeout = setTimeout(() => {\n req.destroy();\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n }\n\n let responseData = '';\n let statusCode = 0;\n let responseHeaders: Record<string, string> = {};\n\n req.on('response', (headers) => {\n statusCode = headers[':status'] as number;\n responseHeaders = headers as Record<string, string>;\n });\n\n req.on('data', (chunk) => {\n responseData += chunk;\n });\n\n req.on('end', () => {\n if (timeout) clearTimeout(timeout);\n resolve({\n statusCode,\n headers: responseHeaders,\n body: responseData,\n });\n });\n\n req.on('error', (error) => {\n if (timeout) clearTimeout(timeout);\n reject(error);\n });\n\n req.write(body);\n req.end();\n });\n}\n\nexport function createNodeTransport(config: NodeTransportConfig): Transport {\n return async ({ text, lang, ctx }) => {\n const maxRetries = config.retries || 0;\n let attempt = 0;\n\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translating \"${text}\" to ${lang} with url ${config.baseUrl}${config.path}`);\n }\n\n while (attempt <= maxRetries) {\n try {\n const session = getOrCreateSession(config.baseUrl);\n const body = JSON.stringify({ text, lang, ctx });\n \n const response = await makeHttp2Request(\n session,\n config.path,\n config.headers || {},\n body,\n config.timeoutMs\n );\n\n if (response.statusCode < 200 || response.statusCode >= 300) {\n throw new Error(`HTTP ${response.statusCode}: Request failed`);\n }\n\n const result = JSON.parse(response.body);\n if (config.debug) {\n console.log(`[BeLocal Node Transport] Translation successful: \"${result.text || text}\"`);\n }\n return result.text || text;\n } catch (error) {\n attempt++;\n if (config.debug) {\n console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));\n }\n if (attempt > maxRetries) {\n throw error;\n }\n\n await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n }\n }\n\n return text;\n };\n}","import type { BelocalEngineOptions, KV, Lang, Transport } from './types';\nimport { createBrowserTransport } from '../transports/browser';\nimport { createNodeTransport } from '../transports/node';\n\nexport class BelocalEngine {\n private transport: Transport;\n private debug: boolean;\n\n constructor(options: BelocalEngineOptions) {\n const {\n apiKey,\n baseUrl = 'https://dynamic.belocal.dev',\n transport = 'auto',\n timeoutMs = 10000,\n retries = 3,\n credentials,\n headers = {},\n debug = false\n } = options;\n\n this.debug = debug;\n\n const authHeaders = {\n 'Authorization': `Bearer ${apiKey}`,\n ...headers\n };\n\n this.transport = this.createTransport(transport, {\n baseUrl,\n timeoutMs,\n retries,\n credentials,\n headers: authHeaders,\n debug: this.debug\n });\n }\n\n async t(text: string, lang: Lang, ctx?: KV): Promise<string> {\n return this.transport({ text, lang, ctx });\n }\n\n private createTransport(\n transportType: 'browser' | 'node' | 'auto',\n config: {\n baseUrl: string;\n timeoutMs: number;\n retries: number;\n credentials?: RequestCredentials;\n headers: Record<string, string>;\n debug: boolean;\n }\n ): Transport {\n const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;\n const path = '/v1/translate';\n\n if (config.debug) {\n console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {\n baseUrl: config.baseUrl,\n path,\n timeoutMs: config.timeoutMs,\n ...(actualTransport === 'browser' && { credentials: config.credentials }),\n ...(actualTransport === 'node' && { retries: config.retries })\n });\n }\n\n if (actualTransport === 'browser') {\n return createBrowserTransport({\n baseUrl: config.baseUrl,\n path: path,\n credentials: config.credentials,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n debug: config.debug,\n });\n } else {\n return createNodeTransport({\n baseUrl: config.baseUrl,\n path: path,\n headers: config.headers,\n timeoutMs: config.timeoutMs,\n retries: config.retries,\n debug: config.debug,\n });\n }\n }\n\n /**\n * Автоматически определяет среду выполнения\n */\n private detectEnvironment(): 'browser' | 'node' {\n if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {\n return 'browser';\n }\n \n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'node';\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@belocal/js-sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "BeLocal runtime JS SDK for on-demand translation (browser + node)",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -44,5 +44,6 @@
44
44
  "dist",
45
45
  "README.md",
46
46
  "LICENSE"
47
- ]
47
+ ],
48
+ "dependencies": {}
48
49
  }