@belocal/js-sdk 0.1.2 → 0.1.4

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 ADDED
@@ -0,0 +1,175 @@
1
+ 'use strict';
2
+
3
+ // src/transports/browser.ts
4
+ function createBrowserTransport(config) {
5
+ return async ({ text, lang, ctx }) => {
6
+ const url = `${config.baseUrl}${config.path}`;
7
+ const controller = new AbortController();
8
+ const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
9
+ if (config.debug) {
10
+ console.log(`[BeLocal Browser Transport] Translating "${text}" to ${lang} with url ${url}`);
11
+ }
12
+ try {
13
+ const response = await fetch(url, {
14
+ method: "POST",
15
+ headers: {
16
+ "Content-Type": "application/json",
17
+ ...config.headers
18
+ },
19
+ body: JSON.stringify({ text, lang, ctx }),
20
+ credentials: config.credentials,
21
+ signal: controller.signal
22
+ });
23
+ if (!response.ok) {
24
+ const errorMsg = `HTTP ${response.status}: ${response.statusText}`;
25
+ if (config.debug) {
26
+ console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);
27
+ }
28
+ throw new Error(errorMsg);
29
+ }
30
+ const result = await response.json();
31
+ if (config.debug) {
32
+ console.log(`[BeLocal Browser Transport] Translation successful: "${result.text || text}"`);
33
+ }
34
+ return result.text || text;
35
+ } finally {
36
+ if (timeoutId) {
37
+ clearTimeout(timeoutId);
38
+ }
39
+ }
40
+ };
41
+ }
42
+
43
+ // src/transports/node.ts
44
+ function createNodeTransport(config) {
45
+ return async ({ text, lang, ctx }) => {
46
+ const url = `${config.baseUrl}${config.path}`;
47
+ const maxRetries = config.retries || 0;
48
+ let attempt = 0;
49
+ if (config.debug) {
50
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
51
+ }
52
+ while (attempt <= maxRetries) {
53
+ 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
+ }
78
+ }
79
+ } catch (error) {
80
+ attempt++;
81
+ if (config.debug) {
82
+ console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));
83
+ }
84
+ if (attempt > maxRetries) {
85
+ throw error;
86
+ }
87
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3));
88
+ }
89
+ }
90
+ return text;
91
+ };
92
+ }
93
+
94
+ // src/core/engine.ts
95
+ var BelocalEngine = class {
96
+ constructor(options) {
97
+ const {
98
+ apiKey,
99
+ baseUrl = "https://dynamic.belocal.dev",
100
+ transport = "auto",
101
+ timeoutMs = 1e4,
102
+ retries = 3,
103
+ credentials,
104
+ headers = {},
105
+ agent,
106
+ debug = false
107
+ } = options;
108
+ this.debug = debug;
109
+ const authHeaders = {
110
+ "Authorization": `Bearer ${apiKey}`,
111
+ ...headers
112
+ };
113
+ this.transport = this.createTransport(transport, {
114
+ baseUrl,
115
+ timeoutMs,
116
+ retries,
117
+ credentials,
118
+ headers: authHeaders,
119
+ agent,
120
+ debug: this.debug
121
+ });
122
+ }
123
+ async t(text, lang, ctx) {
124
+ return this.transport({ text, lang, ctx });
125
+ }
126
+ createTransport(transportType, config) {
127
+ const actualTransport = transportType === "auto" ? this.detectEnvironment() : transportType;
128
+ const path = "/v1/translate";
129
+ if (config.debug) {
130
+ console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {
131
+ baseUrl: config.baseUrl,
132
+ path,
133
+ timeoutMs: config.timeoutMs,
134
+ ...actualTransport === "browser" && { credentials: config.credentials },
135
+ ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
136
+ });
137
+ }
138
+ if (actualTransport === "browser") {
139
+ return createBrowserTransport({
140
+ baseUrl: config.baseUrl,
141
+ path,
142
+ credentials: config.credentials,
143
+ headers: config.headers,
144
+ timeoutMs: config.timeoutMs,
145
+ debug: config.debug
146
+ });
147
+ } else {
148
+ return createNodeTransport({
149
+ baseUrl: config.baseUrl,
150
+ path,
151
+ headers: config.headers,
152
+ timeoutMs: config.timeoutMs,
153
+ agent: config.agent,
154
+ retries: config.retries,
155
+ debug: config.debug
156
+ });
157
+ }
158
+ }
159
+ /**
160
+ * Автоматически определяет среду выполнения
161
+ */
162
+ detectEnvironment() {
163
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
164
+ return "browser";
165
+ }
166
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
167
+ return "node";
168
+ }
169
+ return "node";
170
+ }
171
+ };
172
+
173
+ exports.BelocalEngine = BelocalEngine;
174
+ //# sourceMappingURL=index.cjs.map
175
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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.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"]}
@@ -0,0 +1,27 @@
1
+ type Lang = string;
2
+ type KV = Record<string, unknown>;
3
+ interface BelocalEngineOptions {
4
+ apiKey: string;
5
+ baseUrl?: string;
6
+ transport?: 'browser' | 'node' | 'auto';
7
+ timeoutMs?: number;
8
+ retries?: number;
9
+ credentials?: RequestCredentials;
10
+ headers?: Record<string, string>;
11
+ agent?: unknown;
12
+ debug?: boolean;
13
+ }
14
+
15
+ declare class BelocalEngine {
16
+ private transport;
17
+ private debug;
18
+ constructor(options: BelocalEngineOptions);
19
+ t(text: string, lang: Lang, ctx?: KV): Promise<string>;
20
+ private createTransport;
21
+ /**
22
+ * Автоматически определяет среду выполнения
23
+ */
24
+ private detectEnvironment;
25
+ }
26
+
27
+ export { BelocalEngine, type BelocalEngineOptions, type KV, type Lang };
package/dist/index.js ADDED
@@ -0,0 +1,173 @@
1
+ // src/transports/browser.ts
2
+ function createBrowserTransport(config) {
3
+ return async ({ text, lang, ctx }) => {
4
+ const url = `${config.baseUrl}${config.path}`;
5
+ const controller = new AbortController();
6
+ const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
7
+ if (config.debug) {
8
+ console.log(`[BeLocal Browser Transport] Translating "${text}" to ${lang} with url ${url}`);
9
+ }
10
+ try {
11
+ const response = await fetch(url, {
12
+ method: "POST",
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ ...config.headers
16
+ },
17
+ body: JSON.stringify({ text, lang, ctx }),
18
+ credentials: config.credentials,
19
+ signal: controller.signal
20
+ });
21
+ if (!response.ok) {
22
+ const errorMsg = `HTTP ${response.status}: ${response.statusText}`;
23
+ if (config.debug) {
24
+ console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);
25
+ }
26
+ throw new Error(errorMsg);
27
+ }
28
+ const result = await response.json();
29
+ if (config.debug) {
30
+ console.log(`[BeLocal Browser Transport] Translation successful: "${result.text || text}"`);
31
+ }
32
+ return result.text || text;
33
+ } finally {
34
+ if (timeoutId) {
35
+ clearTimeout(timeoutId);
36
+ }
37
+ }
38
+ };
39
+ }
40
+
41
+ // src/transports/node.ts
42
+ function createNodeTransport(config) {
43
+ return async ({ text, lang, ctx }) => {
44
+ const url = `${config.baseUrl}${config.path}`;
45
+ const maxRetries = config.retries || 0;
46
+ let attempt = 0;
47
+ if (config.debug) {
48
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
49
+ }
50
+ while (attempt <= maxRetries) {
51
+ 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
+ }
76
+ }
77
+ } catch (error) {
78
+ attempt++;
79
+ if (config.debug) {
80
+ console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));
81
+ }
82
+ if (attempt > maxRetries) {
83
+ throw error;
84
+ }
85
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3));
86
+ }
87
+ }
88
+ return text;
89
+ };
90
+ }
91
+
92
+ // src/core/engine.ts
93
+ var BelocalEngine = class {
94
+ constructor(options) {
95
+ const {
96
+ apiKey,
97
+ baseUrl = "https://dynamic.belocal.dev",
98
+ transport = "auto",
99
+ timeoutMs = 1e4,
100
+ retries = 3,
101
+ credentials,
102
+ headers = {},
103
+ agent,
104
+ debug = false
105
+ } = options;
106
+ this.debug = debug;
107
+ const authHeaders = {
108
+ "Authorization": `Bearer ${apiKey}`,
109
+ ...headers
110
+ };
111
+ this.transport = this.createTransport(transport, {
112
+ baseUrl,
113
+ timeoutMs,
114
+ retries,
115
+ credentials,
116
+ headers: authHeaders,
117
+ agent,
118
+ debug: this.debug
119
+ });
120
+ }
121
+ async t(text, lang, ctx) {
122
+ return this.transport({ text, lang, ctx });
123
+ }
124
+ createTransport(transportType, config) {
125
+ const actualTransport = transportType === "auto" ? this.detectEnvironment() : transportType;
126
+ const path = "/v1/translate";
127
+ if (config.debug) {
128
+ console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {
129
+ baseUrl: config.baseUrl,
130
+ path,
131
+ timeoutMs: config.timeoutMs,
132
+ ...actualTransport === "browser" && { credentials: config.credentials },
133
+ ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
134
+ });
135
+ }
136
+ if (actualTransport === "browser") {
137
+ return createBrowserTransport({
138
+ baseUrl: config.baseUrl,
139
+ path,
140
+ credentials: config.credentials,
141
+ headers: config.headers,
142
+ timeoutMs: config.timeoutMs,
143
+ debug: config.debug
144
+ });
145
+ } else {
146
+ return createNodeTransport({
147
+ baseUrl: config.baseUrl,
148
+ path,
149
+ headers: config.headers,
150
+ timeoutMs: config.timeoutMs,
151
+ agent: config.agent,
152
+ retries: config.retries,
153
+ debug: config.debug
154
+ });
155
+ }
156
+ }
157
+ /**
158
+ * Автоматически определяет среду выполнения
159
+ */
160
+ detectEnvironment() {
161
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
162
+ return "browser";
163
+ }
164
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
165
+ return "node";
166
+ }
167
+ return "node";
168
+ }
169
+ };
170
+
171
+ export { BelocalEngine };
172
+ //# sourceMappingURL=index.js.map
173
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/dist/index.mjs ADDED
@@ -0,0 +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
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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"]}
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@belocal/js-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
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",
7
7
  "build": "tsup",
8
8
  "clean": "rimraf dist",
9
9
  "dev": "tsup --watch",
10
- "typecheck": "tsc --noEmit"
10
+ "typecheck": "tsc --noEmit",
11
+ "prepare": "npm run build",
12
+ "prepublishOnly": "npm run build"
11
13
  },
12
14
  "repository": {
13
15
  "type": "git",
@@ -37,5 +39,10 @@
37
39
  "default": "./dist/index.mjs"
38
40
  }
39
41
  },
40
- "sideEffects": false
42
+ "sideEffects": false,
43
+ "files": [
44
+ "dist",
45
+ "README.md",
46
+ "LICENSE"
47
+ ]
41
48
  }
package/.gitlab-ci.yml DELETED
@@ -1,14 +0,0 @@
1
- stages: [release]
2
-
3
- release:
4
- stage: release
5
- image: docker:27.0.3
6
- services: [docker:27.0.3-dind]
7
- variables:
8
- DOCKER_TLS_CERTDIR: ""
9
- script:
10
- - ./build/run-publish
11
- # rules:
12
- # - if: '$CI_COMMIT_TAG' # публикуем только по тегам
13
- tags:
14
- - production
package/Dockerfile DELETED
@@ -1,46 +0,0 @@
1
- # ---------- deps ----------
2
- FROM node:20-alpine AS deps
3
- WORKDIR /app
4
- COPY package.json package-lock.json ./
5
- RUN npm ci
6
-
7
- # ---------- build ----------
8
- FROM node:20-alpine AS build
9
- WORKDIR /app
10
- COPY --from=deps /app/node_modules ./node_modules
11
- COPY . .
12
- RUN npm run build
13
- RUN test -d dist && ls -la dist
14
- RUN npm pack --silent
15
-
16
- # ---------- publisher ----------
17
- FROM node:20-alpine AS publisher
18
- WORKDIR /app
19
- COPY --from=build /app /app
20
-
21
- ENV NPM_REGISTRY="https://registry.npmjs.org/" \
22
- NPM_TAG="latest" \
23
- DRY_RUN="0"
24
-
25
- CMD ["sh","-ceu", "\
26
- : \"${NPM_TOKEN:?NPM_TOKEN is required}\"; \
27
- echo \"• Registry: ${NPM_REGISTRY}\"; \
28
- echo \"• Tag: ${NPM_TAG}\"; \
29
- printf '%s\\n' \"//registry.npmjs.org/:_authToken=${NPM_TOKEN}\" > ~/.npmrc; \
30
- npm config set registry \"${NPM_REGISTRY}\"; \
31
- PKG_NAME=$(node -p \"require('./package.json').name\"); \
32
- PKG_VER=$(node -p \"require('./package.json').version\"); \
33
- ACCESS=\"\"; case \"$PKG_NAME\" in @*/*) ACCESS=\"--access public\";; esac; \
34
- if [ \"${DRY_RUN}\" = \"1\" ]; then \
35
- echo 'DRY_RUN=1 → публикация пропущена'; \
36
- ls -1 *.tgz 2>/dev/null || true; \
37
- exit 0; \
38
- fi; \
39
- if npm view \"$PKG_NAME@$PKG_VER\" version >/dev/null 2>&1; then \
40
- echo \"• Version $PKG_NAME@$PKG_VER уже опубликована — пропускаю\"; \
41
- exit 0; \
42
- fi; \
43
- echo \"• Publishing $PKG_NAME@$PKG_VER with tag '$NPM_TAG'...\"; \
44
- npm publish --tag \"$NPM_TAG\" $ACCESS; \
45
- echo \"✓ Published $PKG_NAME@$PKG_VER\" \
46
- "]
Binary file
package/build/run-publish DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- : "${NPM_TOKEN:?NPM_TOKEN is required}"
5
- export NPM_TAG="${NPM_TAG:-latest}"
6
- export NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org/}"
7
- export NPM_PROVENANCE="${NPM_PROVENANCE:-true}"
8
- export DRY_RUN="${DRY_RUN:-0}"
9
-
10
- echo "Building publisher image..."
11
- docker compose build publisher
12
-
13
- echo "Running publisher..."
14
- docker compose run --rm \
15
- -e NPM_TOKEN \
16
- -e NPM_TAG \
17
- -e NPM_REGISTRY \
18
- -e NPM_PROVENANCE \
19
- -e DRY_RUN \
20
- publisher
@@ -1,13 +0,0 @@
1
- services:
2
- publisher:
3
- build:
4
- context: .
5
- dockerfile: Dockerfile
6
- target: publisher
7
- environment:
8
- NPM_TOKEN: ${NPM_TOKEN}
9
- NPM_TAG: ${NPM_TAG:-latest}
10
- NPM_REGISTRY: ${NPM_REGISTRY:-https://registry.npmjs.org/}
11
- NPM_PROVENANCE: ${NPM_PROVENANCE:-true}
12
- DRY_RUN: ${DRY_RUN:-0}
13
- tty: false
@@ -1,14 +0,0 @@
1
- import type { ClientOptions, KV, Lang, Transport } from './types';
2
-
3
- export class BeLocalClient {
4
- private transport: Transport;
5
-
6
- constructor(options: ClientOptions) {
7
- this.transport = options.transport;
8
- }
9
-
10
- /** Переводит строку через переданный transport. Возвращает Promise<string>. */
11
- async t(text: string, lang: Lang, ctx?: KV): Promise<string> {
12
- return this.transport({ text, lang, ctx });
13
- }
14
- }
@@ -1,105 +0,0 @@
1
- import type { BelocalEngineOptions, KV, Lang, Transport } from './types';
2
- import { createBrowserTransport } from '../transports/browser';
3
- import { createNodeTransport } from '../transports/node';
4
-
5
- export class BelocalEngine {
6
- private transport: Transport;
7
- private debug: boolean;
8
-
9
- constructor(options: BelocalEngineOptions) {
10
- const {
11
- apiKey,
12
- baseUrl = 'https://dynamic.belocal.dev',
13
- transport = 'auto',
14
- timeoutMs = 10000,
15
- retries = 3,
16
- credentials,
17
- headers = {},
18
- agent,
19
- debug = false
20
- } = options;
21
-
22
- this.debug = debug;
23
-
24
- const authHeaders = {
25
- 'Authorization': `Bearer ${apiKey}`,
26
- ...headers
27
- };
28
-
29
- this.transport = this.createTransport(transport, {
30
- baseUrl,
31
- timeoutMs,
32
- retries,
33
- credentials,
34
- headers: authHeaders,
35
- agent,
36
- debug: this.debug
37
- });
38
- }
39
-
40
- async t(text: string, lang: Lang, ctx?: KV): Promise<string> {
41
- return this.transport({ text, lang, ctx });
42
- }
43
-
44
- private createTransport(
45
- transportType: 'browser' | 'node' | 'auto',
46
- config: {
47
- baseUrl: string;
48
- timeoutMs: number;
49
- retries: number;
50
- credentials?: RequestCredentials;
51
- headers: Record<string, string>;
52
- agent?: unknown;
53
- debug: boolean;
54
- }
55
- ): Transport {
56
- const actualTransport = transportType === 'auto' ? this.detectEnvironment() : transportType;
57
- const path = '/v1/translate';
58
-
59
- if (config.debug) {
60
- console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {
61
- baseUrl: config.baseUrl,
62
- path,
63
- timeoutMs: config.timeoutMs,
64
- ...(actualTransport === 'browser' && { credentials: config.credentials }),
65
- ...(actualTransport === 'node' && { retries: config.retries, hasAgent: !!config.agent })
66
- });
67
- }
68
-
69
- if (actualTransport === 'browser') {
70
- return createBrowserTransport({
71
- baseUrl: config.baseUrl,
72
- path: path,
73
- credentials: config.credentials,
74
- headers: config.headers,
75
- timeoutMs: config.timeoutMs,
76
- debug: config.debug,
77
- });
78
- } else {
79
- return createNodeTransport({
80
- baseUrl: config.baseUrl,
81
- path: path,
82
- headers: config.headers,
83
- timeoutMs: config.timeoutMs,
84
- agent: config.agent,
85
- retries: config.retries,
86
- debug: config.debug,
87
- });
88
- }
89
- }
90
-
91
- /**
92
- * Автоматически определяет среду выполнения
93
- */
94
- private detectEnvironment(): 'browser' | 'node' {
95
- if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
96
- return 'browser';
97
- }
98
-
99
- if (typeof process !== 'undefined' && process.versions && process.versions.node) {
100
- return 'node';
101
- }
102
-
103
- return 'node';
104
- }
105
- }
package/src/core/types.ts DELETED
@@ -1,20 +0,0 @@
1
- export type Lang = string;
2
- export type KV = Record<string, unknown>;
3
-
4
- export type Transport = (params: { text: string; lang: Lang; ctx?: KV }) => Promise<string>;
5
-
6
- export interface ClientOptions {
7
- transport: Transport;
8
- }
9
-
10
- export interface BelocalEngineOptions {
11
- apiKey: string;
12
- baseUrl?: string;
13
- transport?: 'browser' | 'node' | 'auto';
14
- timeoutMs?: number;
15
- retries?: number;
16
- credentials?: RequestCredentials;
17
- headers?: Record<string, string>;
18
- agent?: unknown;
19
- debug?: boolean; // default: false - включает логирование
20
- }
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- // Основной API
2
- export { BelocalEngine } from './core/engine';
3
- export type { BelocalEngineOptions } from './core/types';
4
-
5
- // Низкоуровневый API
6
- export type { Lang, KV } from './core/types';
@@ -1,53 +0,0 @@
1
- import type { Transport } from '../core/types';
2
-
3
- export interface BrowserTransportConfig {
4
- baseUrl: string;
5
- path?: string;
6
- credentials?: RequestCredentials;
7
- headers?: Record<string, string>;
8
- timeoutMs?: number;
9
- debug?: boolean;
10
- }
11
-
12
- export function createBrowserTransport(config: BrowserTransportConfig): Transport {
13
- return async ({ text, lang, ctx }) => {
14
- const url = `${config.baseUrl}${config.path}`;
15
- const controller = new AbortController();
16
- const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
17
-
18
- if (config.debug) {
19
- console.log(`[BeLocal Browser Transport] Translating "${text}" to ${lang} with url ${url}`);
20
- }
21
-
22
- try {
23
- const response = await fetch(url, {
24
- method: 'POST',
25
- headers: {
26
- 'Content-Type': 'application/json',
27
- ...config.headers,
28
- },
29
- body: JSON.stringify({ text, lang, ctx }),
30
- credentials: config.credentials,
31
- signal: controller.signal,
32
- });
33
-
34
- if (!response.ok) {
35
- const errorMsg = `HTTP ${response.status}: ${response.statusText}`;
36
- if (config.debug) {
37
- console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);
38
- }
39
- throw new Error(errorMsg);
40
- }
41
-
42
- const result = await response.json();
43
- if (config.debug) {
44
- console.log(`[BeLocal Browser Transport] Translation successful: "${result.text || text}"`);
45
- }
46
- return result.text || text;
47
- } finally {
48
- if (timeoutId) {
49
- clearTimeout(timeoutId);
50
- }
51
- }
52
- };
53
- }
@@ -1,68 +0,0 @@
1
- import type { Transport } from '../core/types';
2
-
3
- export interface NodeTransportConfig {
4
- baseUrl: string;
5
- path: string;
6
- headers?: Record<string, string>;
7
- timeoutMs?: number;
8
- agent?: unknown;
9
- retries?: number;
10
- debug?: boolean;
11
- }
12
-
13
- export function createNodeTransport(config: NodeTransportConfig): Transport {
14
- return async ({ text, lang, ctx }) => {
15
- const url = `${config.baseUrl}${config.path}`;
16
- const maxRetries = config.retries || 0;
17
- let attempt = 0;
18
-
19
- if (config.debug) {
20
- console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
21
- }
22
-
23
- while (attempt <= maxRetries) {
24
- try {
25
- const controller = new AbortController();
26
- const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
27
-
28
- try {
29
- const response = await fetch(url, {
30
- method: 'POST',
31
- headers: {
32
- 'Content-Type': 'application/json',
33
- ...config.headers,
34
- },
35
- body: JSON.stringify({ text, lang, ctx }),
36
- signal: controller.signal,
37
- });
38
-
39
- if (!response.ok) {
40
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
41
- }
42
-
43
- const result = await response.json();
44
- if (config.debug) {
45
- console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
46
- }
47
- return result.text || text;
48
- } finally {
49
- if (timeoutId) {
50
- clearTimeout(timeoutId);
51
- }
52
- }
53
- } catch (error) {
54
- attempt++;
55
- if (config.debug) {
56
- console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));
57
- }
58
- if (attempt > maxRetries) {
59
- throw error;
60
- }
61
- // Exponential backoff
62
- await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
63
- }
64
- }
65
-
66
- return text; // fallback
67
- };
68
- }
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "lib": ["ES2020", "DOM"],
6
- "moduleResolution": "Bundler",
7
- "strict": true,
8
- "declaration": true,
9
- "emitDeclarationOnly": false,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "resolveJsonModule": true,
14
- "isolatedModules": true,
15
- "baseUrl": ".",
16
- "outDir": "dist",
17
- "noEmit": true
18
- }
19
- }
package/tsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "extends": "./tsconfig.base.json",
3
- "compilerOptions": {
4
- "composite": false
5
- },
6
- "include": ["src"]
7
- }
package/tsup.config.js DELETED
@@ -1,45 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig([
4
- // Browser ESM build
5
- {
6
- entry: ['src/index.ts'],
7
- format: ['esm'],
8
- platform: 'browser',
9
- dts: true,
10
- sourcemap: true,
11
- minify: true,
12
- treeshake: true,
13
- outExtension() {
14
- return { js: '.mjs' };
15
- },
16
- outDir: 'dist',
17
- target: 'es2020',
18
- clean: true,
19
- env: {
20
- NODE_ENV: 'production'
21
- },
22
- define: {
23
- __BUILD_TARGET__: '"browser"'
24
- }
25
- },
26
- // Node ESM + (optional) CJS build
27
- {
28
- entry: ['src/index.ts'],
29
- format: ['esm', 'cjs'],
30
- platform: 'node',
31
- dts: false, // d.ts уже сгенерены предыдущей сборкой
32
- sourcemap: true,
33
- minify: false,
34
- treeshake: true,
35
- outDir: 'dist',
36
- target: 'node18',
37
- clean: false,
38
- env: {
39
- NODE_ENV: 'production'
40
- },
41
- define: {
42
- __BUILD_TARGET__: '"node"'
43
- }
44
- }
45
- ]);