@uniformdev/tms-phrase 19.165.2-alpha.0

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.js ADDED
@@ -0,0 +1,477 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __accessCheck = (obj, member, msg) => {
20
+ if (!member.has(obj))
21
+ throw TypeError("Cannot " + msg);
22
+ };
23
+ var __privateGet = (obj, member, getter) => {
24
+ __accessCheck(obj, member, "read from private field");
25
+ return getter ? getter.call(obj) : member.get(obj);
26
+ };
27
+ var __privateAdd = (obj, member, value) => {
28
+ if (member.has(obj))
29
+ throw TypeError("Cannot add the same private member more than once");
30
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
31
+ };
32
+ var __privateSet = (obj, member, value, setter) => {
33
+ __accessCheck(obj, member, "write to private field");
34
+ setter ? setter.call(obj, value) : member.set(obj, value);
35
+ return value;
36
+ };
37
+ var __privateMethod = (obj, member, method) => {
38
+ __accessCheck(obj, member, "access private method");
39
+ return method;
40
+ };
41
+
42
+ // src/index.ts
43
+ var src_exports = {};
44
+ __export(src_exports, {
45
+ PhraseTmsClient: () => PhraseTmsClient,
46
+ buildPhraseJobFileName: () => buildPhraseJobFileName,
47
+ parsePhraseJobFileName: () => parsePhraseJobFileName
48
+ });
49
+ module.exports = __toCommonJS(src_exports);
50
+
51
+ // src/job.ts
52
+ var buildPhraseJobFileName = ({
53
+ uniformProjectId,
54
+ uniformEntityId,
55
+ prefix
56
+ }) => {
57
+ if (!isGuid(uniformProjectId) || !isGuid(uniformEntityId)) {
58
+ return null;
59
+ }
60
+ return `${prefix ? `${prefix}_` : ""}${uniformProjectId}_${uniformEntityId}.json`;
61
+ };
62
+ var parsePhraseJobFileName = (jobFileName) => {
63
+ if (!jobFileName || !jobFileName.endsWith(".json")) {
64
+ return null;
65
+ }
66
+ const withoutExt = jobFileName.slice(0, -1 * ".json".length);
67
+ const segments = withoutExt.split("_").filter((x) => !!x);
68
+ if (segments.length < 2) {
69
+ return null;
70
+ }
71
+ const uniformProjectId = segments[segments.length - 2];
72
+ const uniformEntityId = segments[segments.length - 1];
73
+ if (!isGuid(uniformProjectId) || !isGuid(uniformEntityId)) {
74
+ return null;
75
+ }
76
+ return {
77
+ uniformProjectId,
78
+ uniformEntityId
79
+ };
80
+ };
81
+ var isGuid = (value) => {
82
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
83
+ };
84
+
85
+ // src/PhraseTmsClient.ts
86
+ var import_uuid = require("uuid");
87
+ var EXPIRES_GAP = 5 * 60 * 1e3;
88
+ var AUTH_SESSION_STORAGE_KEY = "uniform_phrase_auth";
89
+ var _options, _authToken, _phraseApiFetcher, _ensureAuthToken, ensureAuthToken_fn, _login, login_fn;
90
+ var PhraseTmsClient = class {
91
+ constructor(options) {
92
+ __privateAdd(this, _ensureAuthToken);
93
+ __privateAdd(this, _login);
94
+ __privateAdd(this, _options, void 0);
95
+ __privateAdd(this, _authToken, void 0);
96
+ __privateAdd(this, _phraseApiFetcher, void 0);
97
+ __privateSet(this, _options, { ...options });
98
+ __privateSet(this, _phraseApiFetcher, options.proxyUrl ? createProxyPhraseApiFetcher(options.proxyUrl) : phraseApiFetcher);
99
+ }
100
+ async checkCredentials() {
101
+ try {
102
+ const authToken = await __privateMethod(this, _login, login_fn).call(this);
103
+ return !!authToken.token;
104
+ } catch (error) {
105
+ return false;
106
+ }
107
+ }
108
+ /**
109
+ * https://cloud.memsource.com/web/docs/api#operation/listProjects
110
+ */
111
+ async listProjects() {
112
+ var _a, _b, _c;
113
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
114
+ const response = await __privateGet(this, _phraseApiFetcher).call(this, {
115
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects`,
116
+ method: "GET",
117
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
118
+ });
119
+ const json = (_b = await response.json()) != null ? _b : {};
120
+ return (_c = json.content) != null ? _c : [];
121
+ }
122
+ async getProject(projectUid) {
123
+ var _a, _b;
124
+ if (!projectUid) {
125
+ throw new Error("missing projectUid");
126
+ }
127
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
128
+ const response = await __privateGet(this, _phraseApiFetcher).call(this, {
129
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}`,
130
+ method: "GET",
131
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
132
+ });
133
+ if (response.status === 404) {
134
+ return null;
135
+ }
136
+ const json = (_b = await response.json()) != null ? _b : {};
137
+ return json.uid ? json : null;
138
+ }
139
+ /**
140
+ * https://cloud.memsource.com/web/docs/api#operation/getImportSettingsForProject
141
+ */
142
+ async getProjectFileImportSettings(projectUid) {
143
+ var _a;
144
+ if (!projectUid) {
145
+ throw new Error("missing projectUid");
146
+ }
147
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
148
+ const rawResponse = await __privateGet(this, _phraseApiFetcher).call(this, {
149
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}/importSettings`,
150
+ method: "GET",
151
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
152
+ });
153
+ try {
154
+ const json = await rawResponse.json();
155
+ return json ? json : null;
156
+ } catch (e) {
157
+ return null;
158
+ }
159
+ }
160
+ async setProjectFileImportSettings(projectUid, importSettings) {
161
+ var _a;
162
+ if (!projectUid) {
163
+ throw new Error("missing projectUid");
164
+ }
165
+ if (!importSettings) {
166
+ throw new Error("missing importSettings");
167
+ }
168
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
169
+ await __privateGet(this, _phraseApiFetcher).call(this, {
170
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}/importSettings`,
171
+ method: "PUT",
172
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token,
173
+ body: importSettings
174
+ });
175
+ }
176
+ /**
177
+ * https://cloud.memsource.com/web/docs/api#operation/listPartsV2
178
+ */
179
+ async listProjectJobs(projectUid, options) {
180
+ if (!projectUid) {
181
+ throw new Error("missing projectUid");
182
+ }
183
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
184
+ const { status = [], fileName = "" } = options != null ? options : {};
185
+ const apiUrl = new URL(`${__privateGet(this, _options).apiHost}/web/api2/v2/projects/${projectUid}/jobs`);
186
+ if (fileName) {
187
+ apiUrl.searchParams.set("filename", fileName);
188
+ }
189
+ if (status.length) {
190
+ status.forEach((x) => apiUrl.searchParams.append("status", x));
191
+ }
192
+ const jobs = await fetchAllPages(apiUrl.toString(), async (pageUrl) => {
193
+ var _a, _b;
194
+ const response = await __privateGet(this, _phraseApiFetcher).call(this, {
195
+ phraseApiUrl: pageUrl,
196
+ method: "GET",
197
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
198
+ });
199
+ return (_b = await response.json()) != null ? _b : {};
200
+ });
201
+ return jobs;
202
+ }
203
+ async listProjectProviders(projectUid) {
204
+ var _a, _b, _c;
205
+ if (!projectUid) {
206
+ throw new Error("missing projectUid");
207
+ }
208
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
209
+ const response = await __privateGet(this, _phraseApiFetcher).call(this, {
210
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}/providers`,
211
+ method: "GET",
212
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
213
+ });
214
+ const json = (_b = await response.json()) != null ? _b : {};
215
+ return (_c = json.content) != null ? _c : [];
216
+ }
217
+ async createTranslationJobFromPayload({
218
+ projectUid,
219
+ dueDate,
220
+ provider,
221
+ payload
222
+ }) {
223
+ var _a, _b, _c, _d;
224
+ if (!projectUid) {
225
+ throw new Error("missing projectUid");
226
+ }
227
+ if (!payload) {
228
+ throw new Error("missing payload");
229
+ }
230
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
231
+ const fileName = buildPhraseJobFileName({
232
+ uniformProjectId: payload.metadata.uniformProjectId,
233
+ uniformEntityId: payload.metadata.entity.id,
234
+ prefix: payload.metadata.entity.slug
235
+ });
236
+ if (!fileName) {
237
+ throw new Error("could not build job file name");
238
+ }
239
+ const rawCreateJobResponse = await __privateGet(this, _phraseApiFetcher).call(this, {
240
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}/jobs`,
241
+ method: "POST",
242
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token,
243
+ headers: {
244
+ "Content-Type": "application/octet-stream",
245
+ "Content-Disposition": `attachment; filename="${fileName}"`,
246
+ Memsource: JSON.stringify({
247
+ targetLangs: [payload.metadata.targetLang],
248
+ due: dueDate,
249
+ assignments: provider ? [
250
+ {
251
+ targetLang: payload.metadata.targetLang,
252
+ providers: [{ id: provider.id, type: provider.type }]
253
+ }
254
+ ] : void 0,
255
+ useProjectFileImportSettings: true
256
+ // now we push real payload on job creation,
257
+ // so `preTranslate` can be configured in Phrase project settings (`Pre-translate on job creation`)
258
+ // preTranslate: true,
259
+ })
260
+ },
261
+ body: payload
262
+ });
263
+ const createJobResponse = (_b = await rawCreateJobResponse.json()) != null ? _b : {};
264
+ const jobUid = (_d = (_c = createJobResponse.jobs) == null ? void 0 : _c.at(0)) == null ? void 0 : _d.uid;
265
+ return jobUid ? jobUid : null;
266
+ }
267
+ async downloadTargetFile({
268
+ projectUid,
269
+ jobUid,
270
+ getAsyncRequestMaxAttempts = 10,
271
+ getAsyncRequestDelayMs = 500
272
+ }) {
273
+ var _a, _b, _c, _d, _e, _f;
274
+ if (!projectUid) {
275
+ throw new Error("missing projectUid");
276
+ }
277
+ if (!jobUid) {
278
+ throw new Error("missing jobUid");
279
+ }
280
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
281
+ const rawAsyncRequestIdResponse = await __privateGet(this, _phraseApiFetcher).call(this, {
282
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v2/projects/${projectUid}/jobs/${jobUid}/targetFile`,
283
+ method: "PUT",
284
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token
285
+ });
286
+ const asyncRequestIdResponse = (_b = await rawAsyncRequestIdResponse.json()) != null ? _b : {};
287
+ const asyncRequestId = (_c = asyncRequestIdResponse == null ? void 0 : asyncRequestIdResponse.asyncRequest) == null ? void 0 : _c.id;
288
+ if (!asyncRequestId) {
289
+ return null;
290
+ }
291
+ let attempts = 0;
292
+ while (attempts < getAsyncRequestMaxAttempts) {
293
+ attempts++;
294
+ const rawAsyncStatusResponse = await __privateGet(this, _phraseApiFetcher).call(this, {
295
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/async/${asyncRequestId}`,
296
+ method: "GET",
297
+ apiToken: (_d = __privateGet(this, _authToken)) == null ? void 0 : _d.token
298
+ });
299
+ const asyncStatusResponse = (_e = await rawAsyncStatusResponse.json()) != null ? _e : {};
300
+ if (!asyncStatusResponse.asyncResponse) {
301
+ await new Promise((r) => setTimeout(r, getAsyncRequestDelayMs));
302
+ } else {
303
+ break;
304
+ }
305
+ }
306
+ const rawFileResponse = await __privateGet(this, _phraseApiFetcher).call(this, {
307
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v2/projects/${projectUid}/jobs/${jobUid}/downloadTargetFile/${asyncRequestId}`,
308
+ method: "GET",
309
+ apiToken: (_f = __privateGet(this, _authToken)) == null ? void 0 : _f.token
310
+ });
311
+ try {
312
+ const json = await rawFileResponse.json();
313
+ return json ? json : null;
314
+ } catch (e) {
315
+ return null;
316
+ }
317
+ }
318
+ async setJobStatus({
319
+ projectUid,
320
+ jobUid,
321
+ jobStatus
322
+ }) {
323
+ var _a;
324
+ if (!projectUid) {
325
+ throw new Error("missing projectUid");
326
+ }
327
+ if (!jobUid) {
328
+ throw new Error("missing jobUid");
329
+ }
330
+ if (!jobStatus) {
331
+ throw new Error("missing jobStatus");
332
+ }
333
+ await __privateMethod(this, _ensureAuthToken, ensureAuthToken_fn).call(this);
334
+ await __privateGet(this, _phraseApiFetcher).call(this, {
335
+ phraseApiUrl: `${__privateGet(this, _options).apiHost}/web/api2/v1/projects/${projectUid}/jobs/${jobUid}/setStatus`,
336
+ method: "POST",
337
+ apiToken: (_a = __privateGet(this, _authToken)) == null ? void 0 : _a.token,
338
+ body: {
339
+ requestedStatus: jobStatus
340
+ }
341
+ });
342
+ }
343
+ };
344
+ _options = new WeakMap();
345
+ _authToken = new WeakMap();
346
+ _phraseApiFetcher = new WeakMap();
347
+ _ensureAuthToken = new WeakSet();
348
+ ensureAuthToken_fn = async function() {
349
+ if (!__privateGet(this, _authToken)) {
350
+ const sessionToken = readSessionStorage(AUTH_SESSION_STORAGE_KEY);
351
+ if ((sessionToken == null ? void 0 : sessionToken.authToken) && sessionToken.hash === calculateSessionTokenHash(__privateGet(this, _options))) {
352
+ __privateSet(this, _authToken, sessionToken.authToken);
353
+ }
354
+ }
355
+ const isExpired = !__privateGet(this, _authToken) || __privateGet(this, _authToken).expires - EXPIRES_GAP <= Date.now();
356
+ if (isExpired) {
357
+ const authToken = await __privateMethod(this, _login, login_fn).call(this);
358
+ writeSessionStorage(AUTH_SESSION_STORAGE_KEY, {
359
+ hash: calculateSessionTokenHash(__privateGet(this, _options)),
360
+ authToken
361
+ });
362
+ __privateSet(this, _authToken, authToken);
363
+ }
364
+ };
365
+ _login = new WeakSet();
366
+ login_fn = async function() {
367
+ var _a;
368
+ const { apiHost, userName, password } = __privateGet(this, _options);
369
+ if (!apiHost) {
370
+ throw new Error("missing apiHost");
371
+ }
372
+ if (!userName) {
373
+ throw new Error("missing userName");
374
+ }
375
+ if (!password) {
376
+ throw new Error("missing password");
377
+ }
378
+ const response = await __privateGet(this, _phraseApiFetcher).call(this, {
379
+ phraseApiUrl: `${apiHost}/web/api2/v3/auth/login`,
380
+ method: "POST",
381
+ body: {
382
+ userName,
383
+ password
384
+ }
385
+ });
386
+ const json = (_a = await response.json()) != null ? _a : {};
387
+ if (!response.ok) {
388
+ throw new Error("Invalid credentials");
389
+ }
390
+ const { token, expires } = json;
391
+ if (!token || !expires) {
392
+ throw new Error("Unknown login API response");
393
+ }
394
+ return {
395
+ token,
396
+ expires: new Date(expires).getTime()
397
+ };
398
+ };
399
+ var fetchAllPages = async (initialApiUrl, fetchPage) => {
400
+ const content = [];
401
+ const initialPage = await fetchPage(initialApiUrl);
402
+ content.push(...initialPage.content);
403
+ const totalPages = initialPage.totalPages;
404
+ if (totalPages > 1) {
405
+ const promises = [];
406
+ for (let i = 1; i < totalPages; i++) {
407
+ const apiUrl = new URL(initialApiUrl);
408
+ apiUrl.searchParams.set("pageNumber", String(i));
409
+ promises.push(fetchPage(apiUrl.toString()));
410
+ }
411
+ (await Promise.all(promises)).forEach((page) => {
412
+ content.push(...page.content);
413
+ });
414
+ }
415
+ return content;
416
+ };
417
+ var phraseApiFetcher = async (payload) => {
418
+ const { phraseApiUrl, method, body, headers, apiToken } = payload;
419
+ const finalHeaders = headers != null ? headers : {};
420
+ if (apiToken) {
421
+ finalHeaders["Authorization"] = `ApiToken ${apiToken}`;
422
+ }
423
+ if (body) {
424
+ finalHeaders["Content-Type"] = finalHeaders["Content-Type"] || "application/json";
425
+ }
426
+ const response = await fetch(phraseApiUrl, {
427
+ method,
428
+ headers: Object.keys(finalHeaders).length ? finalHeaders : void 0,
429
+ body: body ? JSON.stringify(body, null, 2) : void 0
430
+ });
431
+ return response;
432
+ };
433
+ var createProxyPhraseApiFetcher = (proxyUrl) => {
434
+ return async (payload) => {
435
+ const response = await fetch(proxyUrl, {
436
+ method: "POST",
437
+ headers: {
438
+ "Content-Type": "application/json"
439
+ },
440
+ body: JSON.stringify(payload)
441
+ });
442
+ return response;
443
+ };
444
+ };
445
+ var calculateSessionTokenHash = ({
446
+ apiHost,
447
+ userName,
448
+ password
449
+ }) => {
450
+ const NAMESPACE = "a75447fe-9cca-47fe-b4b2-0a21fa96cd88";
451
+ return (0, import_uuid.v5)(JSON.stringify({ apiHost, userName, password }), NAMESPACE);
452
+ };
453
+ var writeSessionStorage = (key, value) => {
454
+ if (isSessionStorageSupported()) {
455
+ sessionStorage.setItem(key, JSON.stringify(value));
456
+ }
457
+ };
458
+ var readSessionStorage = (key) => {
459
+ if (!isSessionStorageSupported()) {
460
+ return null;
461
+ }
462
+ const data = sessionStorage.getItem(key);
463
+ if (!data)
464
+ return null;
465
+ try {
466
+ return JSON.parse(data);
467
+ } catch (e) {
468
+ return null;
469
+ }
470
+ };
471
+ var isSessionStorageSupported = () => typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
472
+ // Annotate the CommonJS export names for ESM import in node:
473
+ 0 && (module.exports = {
474
+ PhraseTmsClient,
475
+ buildPhraseJobFileName,
476
+ parsePhraseJobFileName
477
+ });