@uniformdev/tms-phrase 19.135.1-alpha.11

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