@belocal/js-sdk 0.1.2 → 0.1.5

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,182 @@
1
+ 'use strict';
2
+
3
+ var undici = require('undici');
4
+
5
+ // src/transports/browser.ts
6
+ function createBrowserTransport(config) {
7
+ return async ({ text, lang, ctx }) => {
8
+ const url = `${config.baseUrl}${config.path}`;
9
+ const controller = new AbortController();
10
+ const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
11
+ if (config.debug) {
12
+ console.log(`[BeLocal Browser Transport] Translating "${text}" to ${lang} with url ${url}`);
13
+ }
14
+ try {
15
+ const response = await fetch(url, {
16
+ method: "POST",
17
+ headers: {
18
+ "Content-Type": "application/json",
19
+ ...config.headers
20
+ },
21
+ body: JSON.stringify({ text, lang, ctx }),
22
+ credentials: config.credentials,
23
+ signal: controller.signal
24
+ });
25
+ if (!response.ok) {
26
+ const errorMsg = `HTTP ${response.status}: ${response.statusText}`;
27
+ if (config.debug) {
28
+ console.error(`[BeLocal Browser Transport] Request failed:`, errorMsg);
29
+ }
30
+ throw new Error(errorMsg);
31
+ }
32
+ const result = await response.json();
33
+ if (config.debug) {
34
+ console.log(`[BeLocal Browser Transport] Translation successful: "${result.text || text}"`);
35
+ }
36
+ return result.text || text;
37
+ } finally {
38
+ if (timeoutId) {
39
+ clearTimeout(timeoutId);
40
+ }
41
+ }
42
+ };
43
+ }
44
+ undici.setGlobalDispatcher(
45
+ new undici.Agent({
46
+ connections: 200,
47
+ keepAliveTimeout: 1e4,
48
+ keepAliveMaxTimeout: 6e4
49
+ })
50
+ );
51
+ function createNodeTransport(config) {
52
+ return async ({ text, lang, ctx }) => {
53
+ const url = `${config.baseUrl}${config.path}`;
54
+ const maxRetries = config.retries || 0;
55
+ let attempt = 0;
56
+ if (config.debug) {
57
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
58
+ }
59
+ while (attempt <= maxRetries) {
60
+ try {
61
+ const controller = new AbortController();
62
+ const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
63
+ try {
64
+ const response = await fetch(url, {
65
+ method: "POST",
66
+ headers: {
67
+ "Content-Type": "application/json",
68
+ ...config.headers
69
+ },
70
+ body: JSON.stringify({ text, lang, ctx }),
71
+ signal: controller.signal
72
+ });
73
+ if (!response.ok) {
74
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
75
+ }
76
+ const result = await response.json();
77
+ if (config.debug) {
78
+ console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
79
+ }
80
+ return result.text || text;
81
+ } finally {
82
+ if (timeoutId) {
83
+ clearTimeout(timeoutId);
84
+ }
85
+ }
86
+ } catch (error) {
87
+ attempt++;
88
+ if (config.debug) {
89
+ console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));
90
+ }
91
+ if (attempt > maxRetries) {
92
+ throw error;
93
+ }
94
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3));
95
+ }
96
+ }
97
+ return text;
98
+ };
99
+ }
100
+
101
+ // src/core/engine.ts
102
+ var BelocalEngine = class {
103
+ constructor(options) {
104
+ const {
105
+ apiKey,
106
+ baseUrl = "https://dynamic.belocal.dev",
107
+ transport = "auto",
108
+ timeoutMs = 1e4,
109
+ retries = 3,
110
+ credentials,
111
+ headers = {},
112
+ agent,
113
+ debug = false
114
+ } = options;
115
+ this.debug = debug;
116
+ const authHeaders = {
117
+ "Authorization": `Bearer ${apiKey}`,
118
+ ...headers
119
+ };
120
+ this.transport = this.createTransport(transport, {
121
+ baseUrl,
122
+ timeoutMs,
123
+ retries,
124
+ credentials,
125
+ headers: authHeaders,
126
+ agent,
127
+ debug: this.debug
128
+ });
129
+ }
130
+ async t(text, lang, ctx) {
131
+ return this.transport({ text, lang, ctx });
132
+ }
133
+ createTransport(transportType, config) {
134
+ const actualTransport = transportType === "auto" ? this.detectEnvironment() : transportType;
135
+ const path = "/v1/translate";
136
+ if (config.debug) {
137
+ console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {
138
+ baseUrl: config.baseUrl,
139
+ path,
140
+ timeoutMs: config.timeoutMs,
141
+ ...actualTransport === "browser" && { credentials: config.credentials },
142
+ ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
143
+ });
144
+ }
145
+ if (actualTransport === "browser") {
146
+ return createBrowserTransport({
147
+ baseUrl: config.baseUrl,
148
+ path,
149
+ credentials: config.credentials,
150
+ headers: config.headers,
151
+ timeoutMs: config.timeoutMs,
152
+ debug: config.debug
153
+ });
154
+ } else {
155
+ return createNodeTransport({
156
+ baseUrl: config.baseUrl,
157
+ path,
158
+ headers: config.headers,
159
+ timeoutMs: config.timeoutMs,
160
+ agent: config.agent,
161
+ retries: config.retries,
162
+ debug: config.debug
163
+ });
164
+ }
165
+ }
166
+ /**
167
+ * Автоматически определяет среду выполнения
168
+ */
169
+ detectEnvironment() {
170
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
171
+ return "browser";
172
+ }
173
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
174
+ return "node";
175
+ }
176
+ return "node";
177
+ }
178
+ };
179
+
180
+ exports.BelocalEngine = BelocalEngine;
181
+ //# sourceMappingURL=index.cjs.map
182
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transports/browser.ts","../src/transports/node.ts","../src/core/engine.ts"],"names":["setGlobalDispatcher","Agent"],"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 { Agent, setGlobalDispatcher } from 'undici';\nimport type { Transport } from '../core/types';\n\nsetGlobalDispatcher(\n new Agent({\n connections: 200,\n keepAliveTimeout: 10_000,\n keepAliveMaxTimeout: 60_000,\n}));\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\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 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,180 @@
1
+ import { setGlobalDispatcher, Agent } from 'undici';
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
+ setGlobalDispatcher(
43
+ new Agent({
44
+ connections: 200,
45
+ keepAliveTimeout: 1e4,
46
+ keepAliveMaxTimeout: 6e4
47
+ })
48
+ );
49
+ function createNodeTransport(config) {
50
+ return async ({ text, lang, ctx }) => {
51
+ const url = `${config.baseUrl}${config.path}`;
52
+ const maxRetries = config.retries || 0;
53
+ let attempt = 0;
54
+ if (config.debug) {
55
+ console.log(`[BeLocal Node Transport] Translating "${text}" to ${lang} with url ${url}`);
56
+ }
57
+ while (attempt <= maxRetries) {
58
+ try {
59
+ const controller = new AbortController();
60
+ const timeoutId = config.timeoutMs ? setTimeout(() => controller.abort(), config.timeoutMs) : null;
61
+ try {
62
+ const response = await fetch(url, {
63
+ method: "POST",
64
+ headers: {
65
+ "Content-Type": "application/json",
66
+ ...config.headers
67
+ },
68
+ body: JSON.stringify({ text, lang, ctx }),
69
+ signal: controller.signal
70
+ });
71
+ if (!response.ok) {
72
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
73
+ }
74
+ const result = await response.json();
75
+ if (config.debug) {
76
+ console.log(`[BeLocal Node Transport] Translation successful: "${result.text || text}"`);
77
+ }
78
+ return result.text || text;
79
+ } finally {
80
+ if (timeoutId) {
81
+ clearTimeout(timeoutId);
82
+ }
83
+ }
84
+ } catch (error) {
85
+ attempt++;
86
+ if (config.debug) {
87
+ console.error(`[BeLocal Node Transport] Attempt ${attempt} failed:`, error instanceof Error ? error.message : String(error));
88
+ }
89
+ if (attempt > maxRetries) {
90
+ throw error;
91
+ }
92
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3));
93
+ }
94
+ }
95
+ return text;
96
+ };
97
+ }
98
+
99
+ // src/core/engine.ts
100
+ var BelocalEngine = class {
101
+ constructor(options) {
102
+ const {
103
+ apiKey,
104
+ baseUrl = "https://dynamic.belocal.dev",
105
+ transport = "auto",
106
+ timeoutMs = 1e4,
107
+ retries = 3,
108
+ credentials,
109
+ headers = {},
110
+ agent,
111
+ debug = false
112
+ } = options;
113
+ this.debug = debug;
114
+ const authHeaders = {
115
+ "Authorization": `Bearer ${apiKey}`,
116
+ ...headers
117
+ };
118
+ this.transport = this.createTransport(transport, {
119
+ baseUrl,
120
+ timeoutMs,
121
+ retries,
122
+ credentials,
123
+ headers: authHeaders,
124
+ agent,
125
+ debug: this.debug
126
+ });
127
+ }
128
+ async t(text, lang, ctx) {
129
+ return this.transport({ text, lang, ctx });
130
+ }
131
+ createTransport(transportType, config) {
132
+ const actualTransport = transportType === "auto" ? this.detectEnvironment() : transportType;
133
+ const path = "/v1/translate";
134
+ if (config.debug) {
135
+ console.log(`[BeLocal Engine] Creating ${actualTransport} transport with config:`, {
136
+ baseUrl: config.baseUrl,
137
+ path,
138
+ timeoutMs: config.timeoutMs,
139
+ ...actualTransport === "browser" && { credentials: config.credentials },
140
+ ...actualTransport === "node" && { retries: config.retries, hasAgent: !!config.agent }
141
+ });
142
+ }
143
+ if (actualTransport === "browser") {
144
+ return createBrowserTransport({
145
+ baseUrl: config.baseUrl,
146
+ path,
147
+ credentials: config.credentials,
148
+ headers: config.headers,
149
+ timeoutMs: config.timeoutMs,
150
+ debug: config.debug
151
+ });
152
+ } else {
153
+ return createNodeTransport({
154
+ baseUrl: config.baseUrl,
155
+ path,
156
+ headers: config.headers,
157
+ timeoutMs: config.timeoutMs,
158
+ agent: config.agent,
159
+ retries: config.retries,
160
+ debug: config.debug
161
+ });
162
+ }
163
+ }
164
+ /**
165
+ * Автоматически определяет среду выполнения
166
+ */
167
+ detectEnvironment() {
168
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
169
+ return "browser";
170
+ }
171
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
172
+ return "node";
173
+ }
174
+ return "node";
175
+ }
176
+ };
177
+
178
+ export { BelocalEngine };
179
+ //# sourceMappingURL=index.js.map
180
+ //# 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 { Agent, setGlobalDispatcher } from 'undici';\nimport type { Transport } from '../core/types';\n\nsetGlobalDispatcher(\n new Agent({\n connections: 200,\n keepAliveTimeout: 10_000,\n keepAliveMaxTimeout: 60_000,\n}));\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\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 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
+ import {setGlobalDispatcher,Agent}from'undici';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);}}}setGlobalDispatcher(new Agent({connections:200,keepAliveTimeout:1e4,keepAliveMaxTimeout:6e4}));function m(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 b={Authorization:`Bearer ${e}`,...i};this.transport=this.createTransport(n,{baseUrl:o,timeoutMs:u,retries:a,credentials:s,headers:b,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}):m({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","setGlobalDispatcher","Agent","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 { Agent, setGlobalDispatcher } from 'undici';\nimport type { Transport } from '../core/types';\n\nsetGlobalDispatcher(\n new Agent({\n connections: 200,\n keepAliveTimeout: 10_000,\n keepAliveMaxTimeout: 60_000,\n}));\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\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 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.5",
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,13 @@
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
+ ],
48
+ "dependencies": {
49
+ "undici": "^7.16.0"
50
+ }
41
51
  }
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
- ]);