@translated/lara 1.0.1
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/LICENSE +19 -0
- package/README.md +3 -0
- package/lib/_test.d.ts +1 -0
- package/lib/_test.js +19 -0
- package/lib/credentials.d.ts +5 -0
- package/lib/credentials.js +10 -0
- package/lib/crypto/browser-crypto.d.ts +1 -0
- package/lib/crypto/browser-crypto.js +28 -0
- package/lib/crypto/index.d.ts +3 -0
- package/lib/crypto/index.js +15 -0
- package/lib/crypto/node-crypto.d.ts +1 -0
- package/lib/crypto/node-crypto.js +45 -0
- package/lib/crypto/portable-crypto.d.ts +1 -0
- package/lib/crypto/portable-crypto.js +2 -0
- package/lib/errors.d.ts +10 -0
- package/lib/errors.js +18 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +14 -0
- package/lib/net/browser-client.d.ts +1 -0
- package/lib/net/browser-client.js +45 -0
- package/lib/net/client.d.ts +1 -0
- package/lib/net/client.js +99 -0
- package/lib/net/index.d.ts +3 -0
- package/lib/net/index.js +23 -0
- package/lib/net/node-client.d.ts +1 -0
- package/lib/net/node-client.js +78 -0
- package/lib/sdk-version.d.ts +1 -0
- package/lib/sdk-version.js +4 -0
- package/lib/translator/models.d.ts +29 -0
- package/lib/translator/models.js +2 -0
- package/lib/translator/translator.d.ts +38 -0
- package/lib/translator/translator.js +121 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (C) 2024 Translated, Srl. (https://translated.com)
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
package/README.md
ADDED
package/lib/_test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/_test.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const credentials_1 = require("./credentials");
|
|
4
|
+
const translator_1 = require("./translator/translator");
|
|
5
|
+
const credentials = new credentials_1.Credentials("7GAFEDT3LDJAJH9HFA1CDJULDU", "EBXxbk71Mx6yR9YG48f1jDyY4s5QQLOff0GcTw2QlfY");
|
|
6
|
+
const lara = new translator_1.Translator(credentials, {
|
|
7
|
+
serverUrl: "http://localhost:8000/"
|
|
8
|
+
});
|
|
9
|
+
async function main() {
|
|
10
|
+
const textResult = await lara.translate("Hello, world!", "en", "it");
|
|
11
|
+
console.log("Text:", textResult.translation);
|
|
12
|
+
const arrayResult = await lara.translate(["Hello, world!", "Goodbye, world!"], "en", "it");
|
|
13
|
+
console.log("Array:", arrayResult.translation);
|
|
14
|
+
const blockResult = await lara.translate([{ text: "Hello, world!" }, { text: "Goodbye, world!" }], "en", "it");
|
|
15
|
+
console.log("Block:", blockResult.translation);
|
|
16
|
+
const blockResult2 = await lara.translate([{ text: "Hello, world!", translatable: false }, { text: "Goodbye, world!" }], "en", "it");
|
|
17
|
+
console.log("Block (2):", blockResult2.translation);
|
|
18
|
+
}
|
|
19
|
+
main().then(() => console.log("done")).catch(console.error);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Credentials = void 0;
|
|
4
|
+
class Credentials {
|
|
5
|
+
constructor(accessKeyId, accessKeySecret) {
|
|
6
|
+
this.accessKeyId = accessKeyId;
|
|
7
|
+
this.accessKeySecret = accessKeySecret;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.Credentials = Credentials;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserCrypto = void 0;
|
|
4
|
+
/** @internal */
|
|
5
|
+
class BrowserCrypto {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.subtle = window.crypto.subtle;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* MD5 in browser is not supported, so we use SHA-256 instead and return the first 16 bytes
|
|
11
|
+
*/
|
|
12
|
+
async digest(data) {
|
|
13
|
+
const encoder = new TextEncoder();
|
|
14
|
+
const buffer = (await this.subtle.digest("sha-256", encoder.encode(data))).slice(0, 16);
|
|
15
|
+
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join('');
|
|
16
|
+
}
|
|
17
|
+
async hmac(key, data) {
|
|
18
|
+
const encoder = new TextEncoder();
|
|
19
|
+
encoder.encode(data);
|
|
20
|
+
const cKey = await this.subtle.importKey("raw", encoder.encode(key), {
|
|
21
|
+
name: "hmac",
|
|
22
|
+
hash: { name: "sha-256" },
|
|
23
|
+
}, false, ["sign"]);
|
|
24
|
+
const buffer = await this.subtle.sign("hmac", cKey, encoder.encode(data));
|
|
25
|
+
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BrowserCrypto = BrowserCrypto;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const browser_crypto_1 = require("./browser-crypto");
|
|
4
|
+
const node_crypto_1 = require("./node-crypto");
|
|
5
|
+
let _instance = undefined;
|
|
6
|
+
function instance() {
|
|
7
|
+
if (_instance === undefined) {
|
|
8
|
+
if (typeof window !== "undefined")
|
|
9
|
+
_instance = new browser_crypto_1.BrowserCrypto();
|
|
10
|
+
else
|
|
11
|
+
_instance = new node_crypto_1.NodeCrypto();
|
|
12
|
+
}
|
|
13
|
+
return _instance;
|
|
14
|
+
}
|
|
15
|
+
exports.default = instance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.NodeCrypto = void 0;
|
|
27
|
+
const crypto = __importStar(require("crypto"));
|
|
28
|
+
/** @internal */
|
|
29
|
+
class NodeCrypto {
|
|
30
|
+
digest(data) {
|
|
31
|
+
return new Promise((resolve) => {
|
|
32
|
+
const hash = crypto.createHash("md5");
|
|
33
|
+
hash.update(data);
|
|
34
|
+
resolve(hash.digest("hex"));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
hmac(key, data) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const hmac = crypto.createHmac("sha256", key);
|
|
40
|
+
hmac.update(data);
|
|
41
|
+
resolve(hmac.digest("base64"));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.NodeCrypto = NodeCrypto;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class LaraError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export declare class TimeoutError extends LaraError {
|
|
4
|
+
}
|
|
5
|
+
export declare class LaraApiError extends LaraError {
|
|
6
|
+
readonly statusCode: number;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly errorMessage: string;
|
|
9
|
+
constructor(statusCode: number, name: string, message: string);
|
|
10
|
+
}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LaraApiError = exports.TimeoutError = exports.LaraError = void 0;
|
|
4
|
+
class LaraError extends Error {
|
|
5
|
+
}
|
|
6
|
+
exports.LaraError = LaraError;
|
|
7
|
+
class TimeoutError extends LaraError {
|
|
8
|
+
}
|
|
9
|
+
exports.TimeoutError = TimeoutError;
|
|
10
|
+
class LaraApiError extends LaraError {
|
|
11
|
+
constructor(statusCode, name, message) {
|
|
12
|
+
super(`[HTTP ${statusCode}] ${name}: ${message}`);
|
|
13
|
+
this.statusCode = statusCode;
|
|
14
|
+
this.name = name;
|
|
15
|
+
this.errorMessage = message;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.LaraApiError = LaraApiError;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { version } from "./sdk-version";
|
|
2
|
+
export { Credentials } from "./credentials";
|
|
3
|
+
export { LaraError, TimeoutError, LaraApiError } from "./errors";
|
|
4
|
+
export { Translator, TranslatorOptions, Memories, MemoryImportCallback, TranslateOptions } from "./translator/translator";
|
|
5
|
+
export { Memory, MemoryImport, TextBlock, TextResult } from "./translator/models";
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Memories = exports.Translator = exports.LaraApiError = exports.TimeoutError = exports.LaraError = exports.Credentials = exports.version = void 0;
|
|
4
|
+
var sdk_version_1 = require("./sdk-version");
|
|
5
|
+
Object.defineProperty(exports, "version", { enumerable: true, get: function () { return sdk_version_1.version; } });
|
|
6
|
+
var credentials_1 = require("./credentials");
|
|
7
|
+
Object.defineProperty(exports, "Credentials", { enumerable: true, get: function () { return credentials_1.Credentials; } });
|
|
8
|
+
var errors_1 = require("./errors");
|
|
9
|
+
Object.defineProperty(exports, "LaraError", { enumerable: true, get: function () { return errors_1.LaraError; } });
|
|
10
|
+
Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function () { return errors_1.TimeoutError; } });
|
|
11
|
+
Object.defineProperty(exports, "LaraApiError", { enumerable: true, get: function () { return errors_1.LaraApiError; } });
|
|
12
|
+
var translator_1 = require("./translator/translator");
|
|
13
|
+
Object.defineProperty(exports, "Translator", { enumerable: true, get: function () { return translator_1.Translator; } });
|
|
14
|
+
Object.defineProperty(exports, "Memories", { enumerable: true, get: function () { return translator_1.Memories; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserLaraClient = void 0;
|
|
4
|
+
const client_1 = require("./client");
|
|
5
|
+
function hasDefaultPort(port, secure) {
|
|
6
|
+
return port === 80 && !secure || port === 443 && secure;
|
|
7
|
+
}
|
|
8
|
+
/** @internal */
|
|
9
|
+
class BrowserLaraClient extends client_1.LaraClient {
|
|
10
|
+
constructor(baseUrl, accessKeyId, accessKeySecret) {
|
|
11
|
+
super(accessKeyId, accessKeySecret);
|
|
12
|
+
let url = `${baseUrl.secure ? "https" : "http"}://${baseUrl.hostname}`;
|
|
13
|
+
if (!hasDefaultPort(baseUrl.port, baseUrl.secure))
|
|
14
|
+
url += `:${baseUrl.port}`;
|
|
15
|
+
this.baseUrl = url;
|
|
16
|
+
}
|
|
17
|
+
async send(path, headers, body) {
|
|
18
|
+
let requestBody = undefined;
|
|
19
|
+
if (body) {
|
|
20
|
+
if (headers["Content-Type"] === "multipart/form-data") {
|
|
21
|
+
delete headers["Content-Type"]; // browser will set it automatically
|
|
22
|
+
const formBody = new FormData();
|
|
23
|
+
for (const [key, value] of Object.entries(body)) {
|
|
24
|
+
if (!value)
|
|
25
|
+
continue;
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
value.forEach(v => formBody.append(key, v));
|
|
28
|
+
else
|
|
29
|
+
formBody.append(key, value);
|
|
30
|
+
}
|
|
31
|
+
requestBody = formBody;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
requestBody = JSON.stringify(body, undefined, 0);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const response = await fetch(this.baseUrl + path, {
|
|
38
|
+
headers: headers,
|
|
39
|
+
method: "POST",
|
|
40
|
+
body: requestBody
|
|
41
|
+
});
|
|
42
|
+
return { statusCode: response.status, body: await response.json() };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.BrowserLaraClient = BrowserLaraClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LaraClient = void 0;
|
|
7
|
+
const sdk_version_1 = require("../sdk-version");
|
|
8
|
+
const crypto_1 = __importDefault(require("../crypto"));
|
|
9
|
+
const errors_1 = require("../errors");
|
|
10
|
+
function parseContent(content) {
|
|
11
|
+
if (content === undefined || content === null)
|
|
12
|
+
return content;
|
|
13
|
+
if (Array.isArray(content))
|
|
14
|
+
return content.map(parseContent);
|
|
15
|
+
if (typeof content === "string") {
|
|
16
|
+
// Test if it's a date
|
|
17
|
+
if (content.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.[0-9]{3}Z$/))
|
|
18
|
+
return new Date(content);
|
|
19
|
+
else
|
|
20
|
+
return content;
|
|
21
|
+
}
|
|
22
|
+
if (typeof content == "object") {
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const [key, value] of Object.entries(content)) {
|
|
25
|
+
const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
26
|
+
result[camelKey] = parseContent(value);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
return content;
|
|
31
|
+
}
|
|
32
|
+
/** @internal */
|
|
33
|
+
class LaraClient {
|
|
34
|
+
constructor(accessKeyId, accessKeySecret) {
|
|
35
|
+
this.crypto = (0, crypto_1.default)();
|
|
36
|
+
this.accessKeyId = accessKeyId;
|
|
37
|
+
this.accessKeySecret = accessKeySecret;
|
|
38
|
+
}
|
|
39
|
+
get(path, params) {
|
|
40
|
+
return this.request("GET", path, params);
|
|
41
|
+
}
|
|
42
|
+
delete(path, params) {
|
|
43
|
+
return this.request("DELETE", path, params);
|
|
44
|
+
}
|
|
45
|
+
post(path, body, files) {
|
|
46
|
+
return this.request("POST", path, body, files);
|
|
47
|
+
}
|
|
48
|
+
put(path, body, files) {
|
|
49
|
+
return this.request("PUT", path, body, files);
|
|
50
|
+
}
|
|
51
|
+
async request(method, path, body, files) {
|
|
52
|
+
if (!path.startsWith("/"))
|
|
53
|
+
path = "/" + path;
|
|
54
|
+
const headers = {
|
|
55
|
+
"X-HTTP-Method-Override": method,
|
|
56
|
+
"X-Lara-Date": new Date().toUTCString(),
|
|
57
|
+
"X-Lara-SDK-Name": "lara-node",
|
|
58
|
+
'X-Lara-SDK-Version': sdk_version_1.version
|
|
59
|
+
};
|
|
60
|
+
if (body) {
|
|
61
|
+
body = Object.fromEntries(Object.entries(body).filter(([_, v]) => v !== undefined && v !== null));
|
|
62
|
+
if (Object.keys(body).length === 0)
|
|
63
|
+
body = undefined;
|
|
64
|
+
if (body) {
|
|
65
|
+
const jsonBody = JSON.stringify(body, undefined, 0);
|
|
66
|
+
headers["Content-MD5"] = await this.crypto.digest(jsonBody);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
let requestBody = undefined;
|
|
70
|
+
if (files) {
|
|
71
|
+
headers["Content-Type"] = "multipart/form-data";
|
|
72
|
+
requestBody = Object.assign({}, files, body);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
headers["Content-Type"] = "application/json";
|
|
76
|
+
if (body)
|
|
77
|
+
requestBody = body;
|
|
78
|
+
}
|
|
79
|
+
const signature = await this.sign(method, path, headers);
|
|
80
|
+
headers["Authorization"] = `Lara ${this.accessKeyId}:${signature}`;
|
|
81
|
+
const response = await this.send(path, headers, requestBody);
|
|
82
|
+
if (200 <= response.statusCode && response.statusCode < 300) {
|
|
83
|
+
return parseContent(response.body.content);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const error = response.body.error || {};
|
|
87
|
+
throw new errors_1.LaraApiError(response.statusCode, error.name || "UnknownError", error.message || "An unknown error occurred");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async sign(method, path, headers) {
|
|
91
|
+
const date = headers["X-Lara-Date"].trim();
|
|
92
|
+
const contentMD5 = (headers["Content-MD5"] || "").trim();
|
|
93
|
+
const contentType = (headers["Content-Type"] || "").trim();
|
|
94
|
+
const httpMethod = (headers["X-HTTP-Method-Override"] || method).trim().toUpperCase();
|
|
95
|
+
const challenge = `${httpMethod}\n${path}\n${contentMD5}\n${contentType}\n${date}`;
|
|
96
|
+
return await this.crypto.hmac(this.accessKeySecret, challenge);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.LaraClient = LaraClient;
|
package/lib/net/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LaraClient = void 0;
|
|
4
|
+
const browser_client_1 = require("./browser-client");
|
|
5
|
+
const node_client_1 = require("./node-client");
|
|
6
|
+
var client_1 = require("./client");
|
|
7
|
+
Object.defineProperty(exports, "LaraClient", { enumerable: true, get: function () { return client_1.LaraClient; } });
|
|
8
|
+
const DEFAULT_BASE_URL = "https://api.hellolara.ai";
|
|
9
|
+
function create(accessKeyId, accessKeySecret, baseUrl) {
|
|
10
|
+
const url = new URL(baseUrl || DEFAULT_BASE_URL);
|
|
11
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
12
|
+
throw new TypeError("Invalid URL (protocol): " + url.protocol);
|
|
13
|
+
const parsedURL = {
|
|
14
|
+
secure: url.protocol === "https:",
|
|
15
|
+
hostname: url.hostname,
|
|
16
|
+
port: url.port ? parseInt(url.port) : url.protocol === "https:" ? 443 : 80
|
|
17
|
+
};
|
|
18
|
+
if (typeof window !== "undefined")
|
|
19
|
+
return new browser_client_1.BrowserLaraClient(parsedURL, accessKeyId, accessKeySecret);
|
|
20
|
+
else
|
|
21
|
+
return new node_client_1.NodeLaraClient(parsedURL, accessKeyId, accessKeySecret);
|
|
22
|
+
}
|
|
23
|
+
exports.default = create;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NodeLaraClient = void 0;
|
|
7
|
+
const http_1 = __importDefault(require("http"));
|
|
8
|
+
const https_1 = __importDefault(require("https"));
|
|
9
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
10
|
+
const client_1 = require("./client");
|
|
11
|
+
/** @internal */
|
|
12
|
+
class NodeLaraClient extends client_1.LaraClient {
|
|
13
|
+
constructor(baseUrl, accessKeyId, accessKeySecret) {
|
|
14
|
+
super(accessKeyId, accessKeySecret);
|
|
15
|
+
this.baseUrl = baseUrl;
|
|
16
|
+
this.agent = baseUrl.secure ? new https_1.default.Agent({ keepAlive: true }) : new http_1.default.Agent({ keepAlive: true });
|
|
17
|
+
}
|
|
18
|
+
async send(path, headers, body) {
|
|
19
|
+
let requestBody = undefined;
|
|
20
|
+
if (body) {
|
|
21
|
+
if (headers["Content-Type"] === "multipart/form-data") {
|
|
22
|
+
const formBody = new form_data_1.default();
|
|
23
|
+
for (const [key, value] of Object.entries(body)) {
|
|
24
|
+
if (!value)
|
|
25
|
+
continue;
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
value.forEach(v => formBody.append(key, v));
|
|
28
|
+
else
|
|
29
|
+
formBody.append(key, value);
|
|
30
|
+
}
|
|
31
|
+
headers = {
|
|
32
|
+
...headers,
|
|
33
|
+
...formBody.getHeaders()
|
|
34
|
+
};
|
|
35
|
+
requestBody = formBody;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
requestBody = JSON.stringify(body, undefined, 0);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const options = {
|
|
43
|
+
host: this.baseUrl.hostname,
|
|
44
|
+
port: this.baseUrl.port,
|
|
45
|
+
path: path,
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: headers,
|
|
48
|
+
agent: this.agent
|
|
49
|
+
};
|
|
50
|
+
const req = (this.baseUrl.secure ? https_1.default : http_1.default).request(options, (res) => {
|
|
51
|
+
let data = "";
|
|
52
|
+
res.on("data", (chunk) => data += chunk);
|
|
53
|
+
res.on("end", () => {
|
|
54
|
+
let json;
|
|
55
|
+
try {
|
|
56
|
+
json = JSON.parse(data);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
reject(new Error("Invalid JSON response"));
|
|
60
|
+
}
|
|
61
|
+
resolve({
|
|
62
|
+
statusCode: res.statusCode,
|
|
63
|
+
body: json
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
req.on("error", reject);
|
|
68
|
+
if (requestBody instanceof form_data_1.default) {
|
|
69
|
+
requestBody.pipe(req);
|
|
70
|
+
}
|
|
71
|
+
else if (requestBody) {
|
|
72
|
+
req.write(requestBody);
|
|
73
|
+
}
|
|
74
|
+
req.end();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.NodeLaraClient = NodeLaraClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const version = "1.0.0";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface Memory {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly createdAt: Date;
|
|
4
|
+
readonly updatedAt: Date;
|
|
5
|
+
readonly sharedAt: Date;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly externalId?: string;
|
|
8
|
+
readonly secret?: string;
|
|
9
|
+
readonly ownerId: string;
|
|
10
|
+
readonly collaboratorsCount: number;
|
|
11
|
+
}
|
|
12
|
+
export interface MemoryImport {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly begin: number;
|
|
15
|
+
readonly end: number;
|
|
16
|
+
readonly channel: number;
|
|
17
|
+
readonly size: number;
|
|
18
|
+
readonly progress: number;
|
|
19
|
+
}
|
|
20
|
+
export interface TextBlock {
|
|
21
|
+
readonly text: string;
|
|
22
|
+
readonly translatable?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface TextResult<T extends string | string[] | TextBlock[]> {
|
|
25
|
+
readonly contentType: string;
|
|
26
|
+
readonly sourceLanguage: string;
|
|
27
|
+
readonly translation: T;
|
|
28
|
+
readonly adaptedTo?: string[];
|
|
29
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Credentials } from "../credentials";
|
|
2
|
+
import { LaraClient } from "../net";
|
|
3
|
+
import { Memory, MemoryImport, TextBlock, TextResult } from "./models";
|
|
4
|
+
export type TranslatorOptions = {
|
|
5
|
+
serverUrl?: string;
|
|
6
|
+
};
|
|
7
|
+
export type MemoryImportCallback = (memoryImport: MemoryImport) => void;
|
|
8
|
+
export declare class Memories {
|
|
9
|
+
private readonly client;
|
|
10
|
+
private readonly pollingInterval;
|
|
11
|
+
constructor(client: LaraClient);
|
|
12
|
+
list(): Promise<Memory[]>;
|
|
13
|
+
create(name: string, externalId?: string): Promise<Memory>;
|
|
14
|
+
get(id: string): Promise<Memory | null>;
|
|
15
|
+
delete(id: string): Promise<Memory>;
|
|
16
|
+
update(id: string, name: string): Promise<Memory>;
|
|
17
|
+
connect<T extends string | string[]>(ids: T): Promise<T extends string ? Memory : Memory[]>;
|
|
18
|
+
importTmx(id: string, tmx: any, gzip?: boolean): Promise<MemoryImport>;
|
|
19
|
+
addTranslation(id: string | string[], source: string, target: string, sentence: string, translation: string, tuid?: string, sentenceBefore?: string, sentenceAfter?: string): Promise<MemoryImport>;
|
|
20
|
+
deleteTranslation(id: string | string[], source: string, target: string, sentence: string, translation: string, tuid?: string, sentenceBefore?: string, sentenceAfter?: string): Promise<MemoryImport>;
|
|
21
|
+
getImportStatus(id: string): Promise<MemoryImport>;
|
|
22
|
+
waitForImport(mImport: MemoryImport, updateCallback?: MemoryImportCallback, maxWaitTime?: number): Promise<MemoryImport>;
|
|
23
|
+
}
|
|
24
|
+
export type TranslateOptions = {
|
|
25
|
+
sourceHint?: string;
|
|
26
|
+
adaptTo?: string[];
|
|
27
|
+
instructions?: string[];
|
|
28
|
+
contentType?: string;
|
|
29
|
+
multiline?: boolean;
|
|
30
|
+
timeoutInMillis?: number;
|
|
31
|
+
};
|
|
32
|
+
export declare class Translator {
|
|
33
|
+
private readonly client;
|
|
34
|
+
readonly memories: Memories;
|
|
35
|
+
constructor(credentials: Credentials, options?: TranslatorOptions);
|
|
36
|
+
getLanguages(): Promise<string[]>;
|
|
37
|
+
translate<T extends string | string[] | TextBlock[]>(text: T, source: string | null, target: string, options?: TranslateOptions): Promise<TextResult<T>>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Translator = exports.Memories = void 0;
|
|
7
|
+
const net_1 = __importDefault(require("../net"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
class Memories {
|
|
10
|
+
constructor(client) {
|
|
11
|
+
this.client = client;
|
|
12
|
+
this.pollingInterval = 2000;
|
|
13
|
+
}
|
|
14
|
+
async list() {
|
|
15
|
+
return await this.client.get("/memories");
|
|
16
|
+
}
|
|
17
|
+
async create(name, externalId) {
|
|
18
|
+
return await this.client.post("/memories", {
|
|
19
|
+
name, external_id: externalId
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async get(id) {
|
|
23
|
+
try {
|
|
24
|
+
return await this.client.get(`/memories/${id}`);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
if (e instanceof errors_1.LaraApiError && e.statusCode === 404) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async delete(id) {
|
|
34
|
+
return await this.client.delete(`/memories/${id}`);
|
|
35
|
+
}
|
|
36
|
+
async update(id, name) {
|
|
37
|
+
return await this.client.put(`/memories/${id}`, { name });
|
|
38
|
+
}
|
|
39
|
+
async connect(ids) {
|
|
40
|
+
const memories = await this.client.post("/memories/connect", {
|
|
41
|
+
ids: Array.isArray(ids) ? ids : [ids]
|
|
42
|
+
});
|
|
43
|
+
return (Array.isArray(ids) ? memories : memories[0]);
|
|
44
|
+
}
|
|
45
|
+
async importTmx(id, tmx, gzip = false) {
|
|
46
|
+
return await this.client.post(`/memories/${id}/import`, {
|
|
47
|
+
compression: gzip ? 'gzip' : undefined
|
|
48
|
+
}, {
|
|
49
|
+
tmx
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async addTranslation(id, source, target, sentence, translation, tuid, sentenceBefore, sentenceAfter) {
|
|
53
|
+
const body = {
|
|
54
|
+
source,
|
|
55
|
+
target,
|
|
56
|
+
sentence,
|
|
57
|
+
translation,
|
|
58
|
+
tuid,
|
|
59
|
+
sentence_before: sentenceBefore,
|
|
60
|
+
sentence_after: sentenceAfter
|
|
61
|
+
};
|
|
62
|
+
if (Array.isArray(id)) {
|
|
63
|
+
body.ids = id;
|
|
64
|
+
return await this.client.put("/memories/content", body);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return await this.client.put(`/memories/${id}/content`, body);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async deleteTranslation(id, source, target, sentence, translation, tuid, sentenceBefore, sentenceAfter) {
|
|
71
|
+
const body = {
|
|
72
|
+
source,
|
|
73
|
+
target,
|
|
74
|
+
sentence,
|
|
75
|
+
translation,
|
|
76
|
+
tuid,
|
|
77
|
+
sentence_before: sentenceBefore,
|
|
78
|
+
sentence_after: sentenceAfter
|
|
79
|
+
};
|
|
80
|
+
if (Array.isArray(id)) {
|
|
81
|
+
body.ids = id;
|
|
82
|
+
return await this.client.delete("/memories/content", body);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return await this.client.delete(`/memories/${id}/content`, body);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async getImportStatus(id) {
|
|
89
|
+
return await this.client.get(`/memories/imports/${id}`);
|
|
90
|
+
}
|
|
91
|
+
async waitForImport(mImport, updateCallback, maxWaitTime) {
|
|
92
|
+
const start = Date.now();
|
|
93
|
+
while (mImport.progress < 1.) {
|
|
94
|
+
if (maxWaitTime && Date.now() - start > maxWaitTime)
|
|
95
|
+
throw new errors_1.TimeoutError();
|
|
96
|
+
await new Promise(resolve => setTimeout(resolve, this.pollingInterval));
|
|
97
|
+
mImport = await this.getImportStatus(mImport.id);
|
|
98
|
+
if (updateCallback)
|
|
99
|
+
updateCallback(mImport);
|
|
100
|
+
}
|
|
101
|
+
return mImport;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.Memories = Memories;
|
|
105
|
+
class Translator {
|
|
106
|
+
constructor(credentials, options) {
|
|
107
|
+
this.client = (0, net_1.default)(credentials.accessKeyId, credentials.accessKeySecret, options === null || options === void 0 ? void 0 : options.serverUrl);
|
|
108
|
+
this.memories = new Memories(this.client);
|
|
109
|
+
}
|
|
110
|
+
async getLanguages() {
|
|
111
|
+
return await this.client.get("/languages");
|
|
112
|
+
}
|
|
113
|
+
async translate(text, source, target, options) {
|
|
114
|
+
return await this.client.post("/translate", {
|
|
115
|
+
q: text, source, target, source_hint: options === null || options === void 0 ? void 0 : options.sourceHint, content_type: options === null || options === void 0 ? void 0 : options.contentType,
|
|
116
|
+
multiline: (options === null || options === void 0 ? void 0 : options.multiline) !== false, adapt_to: options === null || options === void 0 ? void 0 : options.adaptTo,
|
|
117
|
+
instructions: options === null || options === void 0 ? void 0 : options.instructions, timeout: options === null || options === void 0 ? void 0 : options.timeoutInMillis
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.Translator = Translator;
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@translated/lara",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"main": "lib/index.js",
|
|
5
|
+
"types": "lib/index.d.ts",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=12.*"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "rm -rf lib/* lib-browser/* && node scripts/generate-sdk-version.js && tsc && webpack"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"lib",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"lara",
|
|
18
|
+
"ai",
|
|
19
|
+
"translate",
|
|
20
|
+
"translated",
|
|
21
|
+
"api"
|
|
22
|
+
],
|
|
23
|
+
"author": {
|
|
24
|
+
"name": "Davide Caroselli",
|
|
25
|
+
"email": "davide.caroselli@translated.com"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"homepage": "https://lara.translated.com",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+ssh://git@github.com/translated/lara-node.git"
|
|
32
|
+
},
|
|
33
|
+
"description": "Official Lara SDK for JavaScript and Node.js",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"form-data": "^4.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.14.2",
|
|
39
|
+
"typescript": "^5.4.5",
|
|
40
|
+
"webpack": "^5.91.0",
|
|
41
|
+
"webpack-cli": "^5.1.4"
|
|
42
|
+
}
|
|
43
|
+
}
|