@lingo.dev/_sdk 0.16.4 → 0.16.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/build/index.cjs +92 -14
- package/build/index.d.cts +24 -0
- package/build/index.d.ts +24 -0
- package/build/index.mjs +84 -6
- package/package.json +1 -1
package/build/index.cjs
CHANGED
|
@@ -114,7 +114,13 @@ var engineParamsSchema = _zod2.default.object({
|
|
|
114
114
|
apiUrl: _zod2.default.string().url().default("https://api.lingo.dev"),
|
|
115
115
|
batchSize: _zod2.default.number().int().gt(0).lte(250).default(25),
|
|
116
116
|
idealBatchItemSize: _zod2.default.number().int().gt(0).lte(2500).default(250),
|
|
117
|
-
engineId: _zod2.default.string().optional()
|
|
117
|
+
engineId: _zod2.default.string().optional(),
|
|
118
|
+
// Number of times a localization request is retried after a transient
|
|
119
|
+
// failure (5xx response or network error). `0` disables retries.
|
|
120
|
+
maxRetries: _zod2.default.number().int().gte(0).default(3),
|
|
121
|
+
// Base delay (ms) for the exponential backoff between retries. The actual
|
|
122
|
+
// wait grows as `retryDelayMs * 2 ** attempt` plus a small random jitter.
|
|
123
|
+
retryDelayMs: _zod2.default.number().int().gte(0).default(500)
|
|
118
124
|
}).passthrough();
|
|
119
125
|
var normalizedLocaleCodeSchema = __spec.localeCodeSchema.transform(__spec.normalizeLocale);
|
|
120
126
|
var payloadSchema = _zod2.default.record(_zod2.default.string(), _zod2.default.any());
|
|
@@ -166,6 +172,74 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
166
172
|
}
|
|
167
173
|
throw new Error(context ? `${context}: ${msg}` : msg);
|
|
168
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Sleep for `ms` milliseconds, rejecting early if the signal is aborted.
|
|
177
|
+
*/
|
|
178
|
+
static sleep(ms, signal) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
if (_optionalChain([signal, 'optionalAccess', _4 => _4.aborted])) {
|
|
181
|
+
reject(new Error("Operation was aborted"));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const onAbort = () => {
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
reject(new Error("Operation was aborted"));
|
|
187
|
+
};
|
|
188
|
+
const timer = setTimeout(() => {
|
|
189
|
+
_optionalChain([signal, 'optionalAccess', _5 => _5.removeEventListener, 'call', _6 => _6("abort", onAbort)]);
|
|
190
|
+
resolve();
|
|
191
|
+
}, ms);
|
|
192
|
+
_optionalChain([signal, 'optionalAccess', _7 => _7.addEventListener, 'call', _8 => _8("abort", onAbort, { once: true })]);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Exponential backoff with full jitter: a random delay in
|
|
197
|
+
* `[0, retryDelayMs * 2 ** attempt]`. Jitter spreads out retries from many
|
|
198
|
+
* clients so a recovering server is not hit by a synchronized wave.
|
|
199
|
+
*/
|
|
200
|
+
backoffDelay(attempt) {
|
|
201
|
+
const ceiling = this.config.retryDelayMs * 2 ** attempt;
|
|
202
|
+
return Math.round(Math.random() * ceiling);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Perform a fetch, retrying on transient failures (5xx responses and
|
|
206
|
+
* network errors) with exponential backoff. The retry decision is made on
|
|
207
|
+
* the HTTP status code (>= 500), so non-retryable responses (e.g. 4xx) are
|
|
208
|
+
* returned immediately for the caller to handle. Aborted requests are never
|
|
209
|
+
* retried.
|
|
210
|
+
* @param url - The request URL
|
|
211
|
+
* @param init - Fetch init options (should include the AbortSignal)
|
|
212
|
+
* @param signal - Optional AbortSignal used to short-circuit retries
|
|
213
|
+
* @returns The fetch Response (which may still be a non-retryable error)
|
|
214
|
+
*/
|
|
215
|
+
async fetchWithRetry(url, init, signal) {
|
|
216
|
+
const { maxRetries } = this.config;
|
|
217
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
218
|
+
if (_optionalChain([signal, 'optionalAccess', _9 => _9.aborted])) {
|
|
219
|
+
throw new Error("Operation was aborted");
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const res = await fetch(url, init);
|
|
223
|
+
const isServerError = res.status >= 500 && res.status < 600;
|
|
224
|
+
if (isServerError && attempt < maxRetries) {
|
|
225
|
+
await _optionalChain([res, 'access', _10 => _10.body, 'optionalAccess', _11 => _11.cancel, 'call', _12 => _12()]);
|
|
226
|
+
await _LingoDotDevEngine.sleep(this.backoffDelay(attempt), signal);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
return res;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
if (_optionalChain([signal, 'optionalAccess', _13 => _13.aborted])) {
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
if (attempt < maxRetries) {
|
|
235
|
+
await _LingoDotDevEngine.sleep(this.backoffDelay(attempt), signal);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
throw new Error("Localization request failed after exhausting retries");
|
|
242
|
+
}
|
|
169
243
|
/**
|
|
170
244
|
* Create a new LingoDotDevEngine instance
|
|
171
245
|
* @param config - Configuration options for the Engine
|
|
@@ -233,12 +307,16 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
233
307
|
metadata: filePath ? { filePath } : void 0,
|
|
234
308
|
...this.config.engineId && { engineId: this.config.engineId }
|
|
235
309
|
};
|
|
236
|
-
const res = await
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
310
|
+
const res = await this.fetchWithRetry(
|
|
311
|
+
url,
|
|
312
|
+
{
|
|
313
|
+
method: "POST",
|
|
314
|
+
headers: this.headers,
|
|
315
|
+
body: JSON.stringify(body, null, 2),
|
|
316
|
+
signal
|
|
317
|
+
},
|
|
240
318
|
signal
|
|
241
|
-
|
|
319
|
+
);
|
|
242
320
|
await _LingoDotDevEngine.throwOnHttpError(res);
|
|
243
321
|
const jsonResponse = await res.json();
|
|
244
322
|
if (!jsonResponse.data && jsonResponse.error) {
|
|
@@ -579,7 +657,7 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
579
657
|
break;
|
|
580
658
|
}
|
|
581
659
|
const siblings = Array.from(parent.childNodes).filter(
|
|
582
|
-
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access',
|
|
660
|
+
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _14 => _14.textContent, 'optionalAccess', _15 => _15.trim, 'call', _16 => _16()])
|
|
583
661
|
);
|
|
584
662
|
const index = siblings.indexOf(current);
|
|
585
663
|
if (index !== -1) {
|
|
@@ -599,7 +677,7 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
599
677
|
parent = parent.parentElement;
|
|
600
678
|
}
|
|
601
679
|
if (node.nodeType === 3) {
|
|
602
|
-
const text = _optionalChain([node, 'access',
|
|
680
|
+
const text = _optionalChain([node, 'access', _17 => _17.textContent, 'optionalAccess', _18 => _18.trim, 'call', _19 => _19()]) || "";
|
|
603
681
|
if (text) {
|
|
604
682
|
extractedContent[getPath(node)] = text;
|
|
605
683
|
}
|
|
@@ -614,15 +692,15 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
614
692
|
}
|
|
615
693
|
});
|
|
616
694
|
Array.from(element.childNodes).filter(
|
|
617
|
-
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access',
|
|
695
|
+
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _20 => _20.textContent, 'optionalAccess', _21 => _21.trim, 'call', _22 => _22()])
|
|
618
696
|
).forEach(processNode);
|
|
619
697
|
}
|
|
620
698
|
};
|
|
621
699
|
Array.from(document.head.childNodes).filter(
|
|
622
|
-
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access',
|
|
700
|
+
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _23 => _23.textContent, 'optionalAccess', _24 => _24.trim, 'call', _25 => _25()])
|
|
623
701
|
).forEach(processNode);
|
|
624
702
|
Array.from(document.body.childNodes).filter(
|
|
625
|
-
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access',
|
|
703
|
+
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _26 => _26.textContent, 'optionalAccess', _27 => _27.trim, 'call', _28 => _28()])
|
|
626
704
|
).forEach(processNode);
|
|
627
705
|
const localizedContent = await this._localizeRaw(
|
|
628
706
|
extractedContent,
|
|
@@ -638,10 +716,10 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
638
716
|
let current = parent;
|
|
639
717
|
for (const index of indices) {
|
|
640
718
|
const siblings = Array.from(parent.childNodes).filter(
|
|
641
|
-
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access',
|
|
719
|
+
(n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _29 => _29.textContent, 'optionalAccess', _30 => _30.trim, 'call', _31 => _31()])
|
|
642
720
|
);
|
|
643
721
|
current = siblings[parseInt(index)] || null;
|
|
644
|
-
if (_optionalChain([current, 'optionalAccess',
|
|
722
|
+
if (_optionalChain([current, 'optionalAccess', _32 => _32.nodeType]) === 1) {
|
|
645
723
|
parent = current;
|
|
646
724
|
}
|
|
647
725
|
}
|
|
@@ -730,7 +808,7 @@ var LingoDotDevEngine = (_class = class _LingoDotDevEngine {
|
|
|
730
808
|
});
|
|
731
809
|
if (res.ok) {
|
|
732
810
|
const payload = await res.json();
|
|
733
|
-
if (!_optionalChain([payload, 'optionalAccess',
|
|
811
|
+
if (!_optionalChain([payload, 'optionalAccess', _33 => _33.email])) {
|
|
734
812
|
return null;
|
|
735
813
|
}
|
|
736
814
|
return {
|
package/build/index.d.cts
CHANGED
|
@@ -7,6 +7,8 @@ declare const engineParamsSchema: Z.ZodObject<{
|
|
|
7
7
|
batchSize: Z.ZodDefault<Z.ZodNumber>;
|
|
8
8
|
idealBatchItemSize: Z.ZodDefault<Z.ZodNumber>;
|
|
9
9
|
engineId: Z.ZodOptional<Z.ZodString>;
|
|
10
|
+
maxRetries: Z.ZodDefault<Z.ZodNumber>;
|
|
11
|
+
retryDelayMs: Z.ZodDefault<Z.ZodNumber>;
|
|
10
12
|
}, Z.core.$loose>;
|
|
11
13
|
declare const payloadSchema: Z.ZodRecord<Z.ZodString, Z.ZodAny>;
|
|
12
14
|
declare const localizationParamsSchema: Z.ZodObject<{
|
|
@@ -32,6 +34,28 @@ declare class LingoDotDevEngine {
|
|
|
32
34
|
private get headers();
|
|
33
35
|
private static extractErrorMessage;
|
|
34
36
|
private static throwOnHttpError;
|
|
37
|
+
/**
|
|
38
|
+
* Sleep for `ms` milliseconds, rejecting early if the signal is aborted.
|
|
39
|
+
*/
|
|
40
|
+
private static sleep;
|
|
41
|
+
/**
|
|
42
|
+
* Exponential backoff with full jitter: a random delay in
|
|
43
|
+
* `[0, retryDelayMs * 2 ** attempt]`. Jitter spreads out retries from many
|
|
44
|
+
* clients so a recovering server is not hit by a synchronized wave.
|
|
45
|
+
*/
|
|
46
|
+
private backoffDelay;
|
|
47
|
+
/**
|
|
48
|
+
* Perform a fetch, retrying on transient failures (5xx responses and
|
|
49
|
+
* network errors) with exponential backoff. The retry decision is made on
|
|
50
|
+
* the HTTP status code (>= 500), so non-retryable responses (e.g. 4xx) are
|
|
51
|
+
* returned immediately for the caller to handle. Aborted requests are never
|
|
52
|
+
* retried.
|
|
53
|
+
* @param url - The request URL
|
|
54
|
+
* @param init - Fetch init options (should include the AbortSignal)
|
|
55
|
+
* @param signal - Optional AbortSignal used to short-circuit retries
|
|
56
|
+
* @returns The fetch Response (which may still be a non-retryable error)
|
|
57
|
+
*/
|
|
58
|
+
private fetchWithRetry;
|
|
35
59
|
/**
|
|
36
60
|
* Create a new LingoDotDevEngine instance
|
|
37
61
|
* @param config - Configuration options for the Engine
|
package/build/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ declare const engineParamsSchema: Z.ZodObject<{
|
|
|
7
7
|
batchSize: Z.ZodDefault<Z.ZodNumber>;
|
|
8
8
|
idealBatchItemSize: Z.ZodDefault<Z.ZodNumber>;
|
|
9
9
|
engineId: Z.ZodOptional<Z.ZodString>;
|
|
10
|
+
maxRetries: Z.ZodDefault<Z.ZodNumber>;
|
|
11
|
+
retryDelayMs: Z.ZodDefault<Z.ZodNumber>;
|
|
10
12
|
}, Z.core.$loose>;
|
|
11
13
|
declare const payloadSchema: Z.ZodRecord<Z.ZodString, Z.ZodAny>;
|
|
12
14
|
declare const localizationParamsSchema: Z.ZodObject<{
|
|
@@ -32,6 +34,28 @@ declare class LingoDotDevEngine {
|
|
|
32
34
|
private get headers();
|
|
33
35
|
private static extractErrorMessage;
|
|
34
36
|
private static throwOnHttpError;
|
|
37
|
+
/**
|
|
38
|
+
* Sleep for `ms` milliseconds, rejecting early if the signal is aborted.
|
|
39
|
+
*/
|
|
40
|
+
private static sleep;
|
|
41
|
+
/**
|
|
42
|
+
* Exponential backoff with full jitter: a random delay in
|
|
43
|
+
* `[0, retryDelayMs * 2 ** attempt]`. Jitter spreads out retries from many
|
|
44
|
+
* clients so a recovering server is not hit by a synchronized wave.
|
|
45
|
+
*/
|
|
46
|
+
private backoffDelay;
|
|
47
|
+
/**
|
|
48
|
+
* Perform a fetch, retrying on transient failures (5xx responses and
|
|
49
|
+
* network errors) with exponential backoff. The retry decision is made on
|
|
50
|
+
* the HTTP status code (>= 500), so non-retryable responses (e.g. 4xx) are
|
|
51
|
+
* returned immediately for the caller to handle. Aborted requests are never
|
|
52
|
+
* retried.
|
|
53
|
+
* @param url - The request URL
|
|
54
|
+
* @param init - Fetch init options (should include the AbortSignal)
|
|
55
|
+
* @param signal - Optional AbortSignal used to short-circuit retries
|
|
56
|
+
* @returns The fetch Response (which may still be a non-retryable error)
|
|
57
|
+
*/
|
|
58
|
+
private fetchWithRetry;
|
|
35
59
|
/**
|
|
36
60
|
* Create a new LingoDotDevEngine instance
|
|
37
61
|
* @param config - Configuration options for the Engine
|
package/build/index.mjs
CHANGED
|
@@ -114,7 +114,13 @@ var engineParamsSchema = Z.object({
|
|
|
114
114
|
apiUrl: Z.string().url().default("https://api.lingo.dev"),
|
|
115
115
|
batchSize: Z.number().int().gt(0).lte(250).default(25),
|
|
116
116
|
idealBatchItemSize: Z.number().int().gt(0).lte(2500).default(250),
|
|
117
|
-
engineId: Z.string().optional()
|
|
117
|
+
engineId: Z.string().optional(),
|
|
118
|
+
// Number of times a localization request is retried after a transient
|
|
119
|
+
// failure (5xx response or network error). `0` disables retries.
|
|
120
|
+
maxRetries: Z.number().int().gte(0).default(3),
|
|
121
|
+
// Base delay (ms) for the exponential backoff between retries. The actual
|
|
122
|
+
// wait grows as `retryDelayMs * 2 ** attempt` plus a small random jitter.
|
|
123
|
+
retryDelayMs: Z.number().int().gte(0).default(500)
|
|
118
124
|
}).passthrough();
|
|
119
125
|
var normalizedLocaleCodeSchema = localeCodeSchema.transform(normalizeLocale);
|
|
120
126
|
var payloadSchema = Z.record(Z.string(), Z.any());
|
|
@@ -166,6 +172,74 @@ var LingoDotDevEngine = class _LingoDotDevEngine {
|
|
|
166
172
|
}
|
|
167
173
|
throw new Error(context ? `${context}: ${msg}` : msg);
|
|
168
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Sleep for `ms` milliseconds, rejecting early if the signal is aborted.
|
|
177
|
+
*/
|
|
178
|
+
static sleep(ms, signal) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
if (signal?.aborted) {
|
|
181
|
+
reject(new Error("Operation was aborted"));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const onAbort = () => {
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
reject(new Error("Operation was aborted"));
|
|
187
|
+
};
|
|
188
|
+
const timer = setTimeout(() => {
|
|
189
|
+
signal?.removeEventListener("abort", onAbort);
|
|
190
|
+
resolve();
|
|
191
|
+
}, ms);
|
|
192
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Exponential backoff with full jitter: a random delay in
|
|
197
|
+
* `[0, retryDelayMs * 2 ** attempt]`. Jitter spreads out retries from many
|
|
198
|
+
* clients so a recovering server is not hit by a synchronized wave.
|
|
199
|
+
*/
|
|
200
|
+
backoffDelay(attempt) {
|
|
201
|
+
const ceiling = this.config.retryDelayMs * 2 ** attempt;
|
|
202
|
+
return Math.round(Math.random() * ceiling);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Perform a fetch, retrying on transient failures (5xx responses and
|
|
206
|
+
* network errors) with exponential backoff. The retry decision is made on
|
|
207
|
+
* the HTTP status code (>= 500), so non-retryable responses (e.g. 4xx) are
|
|
208
|
+
* returned immediately for the caller to handle. Aborted requests are never
|
|
209
|
+
* retried.
|
|
210
|
+
* @param url - The request URL
|
|
211
|
+
* @param init - Fetch init options (should include the AbortSignal)
|
|
212
|
+
* @param signal - Optional AbortSignal used to short-circuit retries
|
|
213
|
+
* @returns The fetch Response (which may still be a non-retryable error)
|
|
214
|
+
*/
|
|
215
|
+
async fetchWithRetry(url, init, signal) {
|
|
216
|
+
const { maxRetries } = this.config;
|
|
217
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
218
|
+
if (signal?.aborted) {
|
|
219
|
+
throw new Error("Operation was aborted");
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const res = await fetch(url, init);
|
|
223
|
+
const isServerError = res.status >= 500 && res.status < 600;
|
|
224
|
+
if (isServerError && attempt < maxRetries) {
|
|
225
|
+
await res.body?.cancel();
|
|
226
|
+
await _LingoDotDevEngine.sleep(this.backoffDelay(attempt), signal);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
return res;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
if (signal?.aborted) {
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
if (attempt < maxRetries) {
|
|
235
|
+
await _LingoDotDevEngine.sleep(this.backoffDelay(attempt), signal);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
throw new Error("Localization request failed after exhausting retries");
|
|
242
|
+
}
|
|
169
243
|
/**
|
|
170
244
|
* Create a new LingoDotDevEngine instance
|
|
171
245
|
* @param config - Configuration options for the Engine
|
|
@@ -233,12 +307,16 @@ var LingoDotDevEngine = class _LingoDotDevEngine {
|
|
|
233
307
|
metadata: filePath ? { filePath } : void 0,
|
|
234
308
|
...this.config.engineId && { engineId: this.config.engineId }
|
|
235
309
|
};
|
|
236
|
-
const res = await
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
310
|
+
const res = await this.fetchWithRetry(
|
|
311
|
+
url,
|
|
312
|
+
{
|
|
313
|
+
method: "POST",
|
|
314
|
+
headers: this.headers,
|
|
315
|
+
body: JSON.stringify(body, null, 2),
|
|
316
|
+
signal
|
|
317
|
+
},
|
|
240
318
|
signal
|
|
241
|
-
|
|
319
|
+
);
|
|
242
320
|
await _LingoDotDevEngine.throwOnHttpError(res);
|
|
243
321
|
const jsonResponse = await res.json();
|
|
244
322
|
if (!jsonResponse.data && jsonResponse.error) {
|