sanity-plugin-studio-smartling 4.3.3 → 5.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/README.md +1 -5
- package/dist/index.d.ts +7 -47
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -219
- package/dist/index.js.map +1 -1
- package/package.json +34 -66
- package/dist/index.esm.js +0 -268
- package/dist/index.esm.js.map +0 -1
- package/sanity.json +0 -8
- package/src/adapter/createTask.ts +0 -166
- package/src/adapter/getLocales.ts +0 -18
- package/src/adapter/getTranslation.ts +0 -36
- package/src/adapter/getTranslationTask.ts +0 -89
- package/src/adapter/helpers.ts +0 -84
- package/src/adapter/index.ts +0 -12
- package/src/index.ts +0 -52
- package/src/types.d.ts +0 -0
- package/v2-incompatible.js +0 -11
package/README.md
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
## Installation
|
|
3
2
|
|
|
4
3
|
```sh
|
|
5
4
|
npm install sanity-plugin-studio-smartling
|
|
6
5
|
```
|
|
7
6
|
|
|
8
|
-
## Usage
|
|
9
|
-
|
|
10
7
|
# Studio Plugin for Sanity & Smartling
|
|
11
8
|
|
|
12
9
|

|
|
@@ -59,7 +56,7 @@ client.createOrReplace({
|
|
|
59
56
|
organization: 'YOUR_SMARTLING_ORGANIZATION_HERE',
|
|
60
57
|
project: 'YOUR_SMARTLING_PROJECT_HERE',
|
|
61
58
|
secret: '{"userIdentifier":"xxxxxx","userSecret":"xxxx"}', //in this format from Smartling when you press the button "copy token" on creation
|
|
62
|
-
proxy: 'my-proxy-endpoint.com/api/proxy' //the endpoint you set up in step 2
|
|
59
|
+
proxy: 'my-proxy-endpoint.com/api/proxy', //the endpoint you set up in step 2
|
|
63
60
|
})
|
|
64
61
|
```
|
|
65
62
|
|
|
@@ -126,7 +123,6 @@ Since we often find users want to use the [Document internationalization plugin]
|
|
|
126
123
|
|
|
127
124
|
_Important_: The above is true if you are using the Document Internationalization Plugin at version 2 or above. If you are using version 1 please use the `legacyDocumentLevelConfig` configuration exported from this plugin. This configuration assumes your translations follow the pattern `{id-of-base-language-document}__i18n_{locale}`
|
|
128
125
|
|
|
129
|
-
|
|
130
126
|
### Final note
|
|
131
127
|
|
|
132
128
|
It's okay if your data doesn't follow these patterns and you don't want to change them! You will simply have to override how the plugin gets and patches back information from your documents. Please see [Overriding defaults](#overriding-defaults).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,47 +1,7 @@
|
|
|
1
|
-
import {Adapter} from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {fieldLevelPatch} from 'sanity-translations-tab'
|
|
9
|
-
import {findLatestDraft} from 'sanity-translations-tab'
|
|
10
|
-
import {legacyDocumentLevelPatch} from 'sanity-translations-tab'
|
|
11
|
-
import {TranslationFunctionContext} from 'sanity-translations-tab'
|
|
12
|
-
import {TranslationsTab} from 'sanity-translations-tab'
|
|
13
|
-
import {TranslationsTabConfigOptions} from 'sanity-translations-tab'
|
|
14
|
-
|
|
15
|
-
export {BaseDocumentDeserializer}
|
|
16
|
-
|
|
17
|
-
export {BaseDocumentMerger}
|
|
18
|
-
|
|
19
|
-
export {BaseDocumentSerializer}
|
|
20
|
-
|
|
21
|
-
export {customSerializers}
|
|
22
|
-
|
|
23
|
-
export declare const defaultDocumentLevelConfig: TranslationsTabConfigOptions
|
|
24
|
-
|
|
25
|
-
export declare const defaultFieldLevelConfig: TranslationsTabConfigOptions
|
|
26
|
-
|
|
27
|
-
export {defaultStopTypes}
|
|
28
|
-
|
|
29
|
-
export {documentLevelPatch}
|
|
30
|
-
|
|
31
|
-
export {fieldLevelPatch}
|
|
32
|
-
|
|
33
|
-
export {findLatestDraft}
|
|
34
|
-
|
|
35
|
-
export declare const legacyDocumentLevelConfig: TranslationsTabConfigOptions
|
|
36
|
-
|
|
37
|
-
export {legacyDocumentLevelPatch}
|
|
38
|
-
|
|
39
|
-
export declare const SmartlingAdapter: Adapter
|
|
40
|
-
|
|
41
|
-
export {TranslationFunctionContext}
|
|
42
|
-
|
|
43
|
-
export {TranslationsTab}
|
|
44
|
-
|
|
45
|
-
export {TranslationsTabConfigOptions}
|
|
46
|
-
|
|
47
|
-
export {}
|
|
1
|
+
import { Adapter, BaseDocumentDeserializer, BaseDocumentMerger, BaseDocumentSerializer, TranslationFunctionContext, TranslationsTab, TranslationsTabConfigOptions, TranslationsTabConfigOptions as TranslationsTabConfigOptions$1, customSerializers, defaultStopTypes, documentLevelPatch, fieldLevelPatch, findLatestDraft, legacyDocumentLevelPatch } from "sanity-translations-tab";
|
|
2
|
+
declare const SmartlingAdapter: Adapter;
|
|
3
|
+
declare const defaultDocumentLevelConfig: TranslationsTabConfigOptions$1;
|
|
4
|
+
declare const legacyDocumentLevelConfig: TranslationsTabConfigOptions$1;
|
|
5
|
+
declare const defaultFieldLevelConfig: TranslationsTabConfigOptions$1;
|
|
6
|
+
export { BaseDocumentDeserializer, BaseDocumentMerger, BaseDocumentSerializer, SmartlingAdapter, type TranslationFunctionContext, TranslationsTab, type TranslationsTabConfigOptions, customSerializers, defaultDocumentLevelConfig, defaultFieldLevelConfig, defaultStopTypes, documentLevelPatch, fieldLevelPatch, findLatestDraft, legacyDocumentLevelConfig, legacyDocumentLevelPatch };
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/adapter/index.ts","../src/index.ts"],"mappings":";cAOa,gBAAA,EAAkB,OAK9B;AAAA,cCcK,0BAAA,EAA4B,8BAGjC;AAAA,cAEK,yBAAA,EAA2B,8BAGhC;AAAA,cAEK,uBAAA,EAAyB,8BAG9B"}
|
package/dist/index.js
CHANGED
|
@@ -1,50 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var sanityTranslationsTab = require('sanity-translations-tab');
|
|
7
|
-
var buffer = require('buffer');
|
|
8
|
-
const authenticate = secrets => {
|
|
9
|
-
const url = "https://api.smartling.com/auth-api/v2/authenticate";
|
|
1
|
+
import { baseDocumentLevelConfig, baseFieldLevelConfig, legacyDocumentLevelConfig as legacyDocumentLevelConfig$1 } from "sanity-translations-tab";
|
|
2
|
+
import { BaseDocumentDeserializer, BaseDocumentMerger, BaseDocumentSerializer, TranslationsTab, customSerializers, defaultStopTypes, documentLevelPatch, fieldLevelPatch, findLatestDraft, legacyDocumentLevelPatch } from "sanity-translations-tab";
|
|
3
|
+
const authenticate = (secrets) => {
|
|
10
4
|
const headers = {
|
|
11
5
|
"content-type": "application/json",
|
|
12
|
-
"X-URL":
|
|
13
|
-
}
|
|
14
|
-
const {
|
|
6
|
+
"X-URL": "https://api.smartling.com/auth-api/v2/authenticate"
|
|
7
|
+
}, {
|
|
15
8
|
secret,
|
|
16
9
|
proxy
|
|
17
10
|
} = secrets;
|
|
18
|
-
if (!secret || !proxy)
|
|
11
|
+
if (!secret || !proxy)
|
|
19
12
|
throw new Error("The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
20
|
-
}
|
|
21
13
|
return fetch(proxy, {
|
|
22
14
|
headers,
|
|
23
15
|
method: "POST",
|
|
24
16
|
body: JSON.stringify(secret)
|
|
25
|
-
}).then(res => res.json()).then(res => res.response.data.accessToken);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
Authorization: "Bearer ".concat(accessToken),
|
|
17
|
+
}).then((res) => res.json()).then((res) => res.response.data.accessToken);
|
|
18
|
+
}, getHeaders = (url, accessToken) => ({
|
|
19
|
+
Authorization: `Bearer ${accessToken}`,
|
|
29
20
|
"X-URL": url
|
|
30
|
-
})
|
|
31
|
-
const findExistingJob = async (documentId, secrets, accessToken) => {
|
|
21
|
+
}), findExistingJob = async (documentId, secrets, accessToken) => {
|
|
32
22
|
const {
|
|
33
23
|
project,
|
|
34
24
|
proxy
|
|
35
25
|
} = secrets;
|
|
36
|
-
if (!project || !proxy)
|
|
26
|
+
if (!project || !proxy)
|
|
37
27
|
throw new Error("The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
38
|
-
}
|
|
39
|
-
const url = "https://api.smartling.com/jobs-api/v3/projects/".concat(project, "/jobs?jobName=").concat(documentId);
|
|
28
|
+
const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`;
|
|
40
29
|
let items = await fetch(proxy, {
|
|
41
30
|
headers: getHeaders(url, accessToken)
|
|
42
|
-
}).then(res => res.json()).then(res =>
|
|
43
|
-
var _a, _b;
|
|
44
|
-
return (_b = (_a = res == null ? void 0 : res.response) == null ? void 0 : _a.data) == null ? void 0 : _b.items;
|
|
45
|
-
});
|
|
31
|
+
}).then((res) => res.json()).then((res) => res?.response?.data?.items);
|
|
46
32
|
if (!items || !items.length) {
|
|
47
|
-
const refUrl =
|
|
33
|
+
const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`;
|
|
48
34
|
items = await fetch(proxy, {
|
|
49
35
|
headers: {
|
|
50
36
|
...getHeaders(refUrl, accessToken),
|
|
@@ -54,97 +40,62 @@ const findExistingJob = async (documentId, secrets, accessToken) => {
|
|
|
54
40
|
body: JSON.stringify({
|
|
55
41
|
fileUris: [documentId]
|
|
56
42
|
})
|
|
57
|
-
}).then(res => res.json()).then(res =>
|
|
58
|
-
var _a, _b;
|
|
59
|
-
return (_b = (_a = res == null ? void 0 : res.response) == null ? void 0 : _a.data) == null ? void 0 : _b.items;
|
|
60
|
-
});
|
|
43
|
+
}).then((res) => res.json()).then((res) => res?.response?.data?.items);
|
|
61
44
|
}
|
|
62
45
|
if (items.length) {
|
|
63
|
-
const correctJob = items.filter(item => item.jobStatus !== "DELETED").find(item => item.jobName && item.jobName === documentId || item.referenceNumber && item.referenceNumber === documentId);
|
|
64
|
-
if (correctJob)
|
|
46
|
+
const correctJob = items.filter((item) => item.jobStatus !== "DELETED").find((item) => item.jobName && item.jobName === documentId || item.referenceNumber && item.referenceNumber === documentId);
|
|
47
|
+
if (correctJob)
|
|
65
48
|
return correctJob.translationJobUid;
|
|
66
|
-
}
|
|
67
49
|
}
|
|
68
50
|
return "";
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!(secrets == null ? void 0 : secrets.project) || !(secrets == null ? void 0 : secrets.secret) || !(secrets == null ? void 0 : secrets.proxy)) {
|
|
72
|
-
return [];
|
|
73
|
-
}
|
|
74
|
-
const {
|
|
75
|
-
project,
|
|
76
|
-
proxy
|
|
77
|
-
} = secrets;
|
|
78
|
-
const url = "https://api.smartling.com/projects-api/v2/projects/".concat(project);
|
|
79
|
-
const accessToken = await authenticate(secrets);
|
|
80
|
-
return fetch(proxy, {
|
|
81
|
-
method: "GET",
|
|
82
|
-
headers: getHeaders(url, accessToken)
|
|
83
|
-
}).then(res => res.json()).then(res => res.response.data.targetLocales);
|
|
84
|
-
};
|
|
85
|
-
const getTranslationTask = async (documentId, secrets) => {
|
|
86
|
-
if (!(secrets == null ? void 0 : secrets.project) || !(secrets == null ? void 0 : secrets.secret) || !(secrets == null ? void 0 : secrets.proxy)) {
|
|
51
|
+
}, getTranslationTask = async (documentId, secrets) => {
|
|
52
|
+
if (!secrets?.project || !secrets?.secret || !secrets?.proxy)
|
|
87
53
|
return {
|
|
88
54
|
documentId,
|
|
89
55
|
taskId: documentId,
|
|
90
56
|
locales: []
|
|
91
57
|
};
|
|
92
|
-
}
|
|
93
58
|
const {
|
|
94
59
|
project,
|
|
95
60
|
proxy
|
|
96
|
-
} = secrets;
|
|
97
|
-
|
|
98
|
-
const taskId = await findExistingJob(documentId, secrets, accessToken);
|
|
99
|
-
if (!taskId) {
|
|
61
|
+
} = secrets, accessToken = await authenticate(secrets), taskId = await findExistingJob(documentId, secrets, accessToken);
|
|
62
|
+
if (!taskId)
|
|
100
63
|
return {
|
|
101
64
|
documentId,
|
|
102
65
|
taskId: documentId,
|
|
103
66
|
locales: []
|
|
104
67
|
};
|
|
105
|
-
}
|
|
106
|
-
const progressUrl = "https://api.smartling.com/jobs-api/v3/projects/".concat(project, "/jobs/").concat(taskId, "/progress");
|
|
107
|
-
const smartlingTask = await fetch(proxy, {
|
|
68
|
+
const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`, smartlingTask = await fetch(proxy, {
|
|
108
69
|
method: "GET",
|
|
109
70
|
headers: getHeaders(progressUrl, accessToken)
|
|
110
|
-
}).then(res => res.json()).then(res => res.response.data);
|
|
71
|
+
}).then((res) => res.json()).then((res) => res.response.data);
|
|
111
72
|
let locales = [];
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
return {
|
|
126
|
-
localeId: item.targetLocaleId,
|
|
127
|
-
progress
|
|
128
|
-
};
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
73
|
+
return smartlingTask && smartlingTask.contentProgressReport && (locales = smartlingTask.contentProgressReport.map((item) => {
|
|
74
|
+
let progress = item.progress ? item.progress.percentComplete : 0;
|
|
75
|
+
const progressItem = item.workflowProgressReportList?.[0];
|
|
76
|
+
if (progressItem && item.progress && progressItem.workflowStepSummaryReportItemList && progressItem.workflowStepSummaryReportItemList.length > 1) {
|
|
77
|
+
const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1);
|
|
78
|
+
lastStep && lastStep.wordCount >= 0 && (progress = Math.floor(lastStep.wordCount / item.progress.totalWordCount * 100) ?? 0);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
localeId: item.targetLocaleId,
|
|
82
|
+
progress
|
|
83
|
+
};
|
|
84
|
+
})), {
|
|
132
85
|
documentId,
|
|
133
86
|
locales,
|
|
134
87
|
//since our download is tied to document id for smartling, keep track of it as a task
|
|
135
88
|
taskId: documentId,
|
|
136
|
-
linkToVendorTask:
|
|
89
|
+
linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`
|
|
137
90
|
};
|
|
138
|
-
}
|
|
139
|
-
const createJob = (jobName, secrets, localeIds, accessToken, documentId) => {
|
|
91
|
+
}, createJob = (jobName, secrets, localeIds, accessToken, documentId) => {
|
|
140
92
|
const {
|
|
141
93
|
project,
|
|
142
94
|
proxy
|
|
143
95
|
} = secrets;
|
|
144
|
-
if (!project || !proxy)
|
|
96
|
+
if (!project || !proxy)
|
|
145
97
|
throw new Error("The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
146
|
-
}
|
|
147
|
-
const url = "https://api.smartling.com/jobs-api/v3/projects/".concat(project, "/jobs");
|
|
98
|
+
const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs`;
|
|
148
99
|
return fetch(proxy, {
|
|
149
100
|
method: "POST",
|
|
150
101
|
headers: {
|
|
@@ -156,180 +107,110 @@ const createJob = (jobName, secrets, localeIds, accessToken, documentId) => {
|
|
|
156
107
|
targetLocaleIds: localeIds,
|
|
157
108
|
referenceNumber: documentId
|
|
158
109
|
})
|
|
159
|
-
}).then(res => res.json()).then(res => res.response.data.translationJobUid);
|
|
160
|
-
}
|
|
161
|
-
const createJobBatch = (jobId, secrets, documentId, accessToken, localeIds, workflowUid) => {
|
|
110
|
+
}).then((res) => res.json()).then((res) => res.response.data.translationJobUid);
|
|
111
|
+
}, createJobBatch = (jobId, secrets, documentId, accessToken, localeIds, workflowUid) => {
|
|
162
112
|
const {
|
|
163
113
|
project,
|
|
164
114
|
proxy
|
|
165
115
|
} = secrets;
|
|
166
|
-
if (!project || !proxy)
|
|
116
|
+
if (!project || !proxy)
|
|
167
117
|
throw new Error("The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const reqBody = {
|
|
171
|
-
authorize: true,
|
|
118
|
+
const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches`, reqBody = {
|
|
119
|
+
authorize: !0,
|
|
172
120
|
translationJobUid: jobId,
|
|
173
121
|
fileUris: [documentId]
|
|
174
122
|
};
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
return fetch(proxy, {
|
|
123
|
+
return workflowUid && (reqBody.localeWorkflows = localeIds.map((l) => ({
|
|
124
|
+
targetLocaleId: l,
|
|
125
|
+
workflowUid
|
|
126
|
+
}))), fetch(proxy, {
|
|
182
127
|
method: "POST",
|
|
183
128
|
headers: {
|
|
184
129
|
...getHeaders(url, accessToken),
|
|
185
130
|
"content-type": "application/json"
|
|
186
131
|
},
|
|
187
132
|
body: JSON.stringify(reqBody)
|
|
188
|
-
}).then(res => res.json()).then(res => res.response.data.batchUid);
|
|
189
|
-
}
|
|
190
|
-
const uploadFileToBatch = (batchUid, documentId, document, secrets, localeIds, accessToken, callbackUrl) => {
|
|
133
|
+
}).then((res) => res.json()).then((res) => res.response.data.batchUid);
|
|
134
|
+
}, uploadFileToBatch = (batchUid, documentId, document, secrets, localeIds, accessToken, callbackUrl) => {
|
|
191
135
|
const {
|
|
192
136
|
project,
|
|
193
137
|
proxy
|
|
194
138
|
} = secrets;
|
|
195
|
-
if (!project || !proxy)
|
|
139
|
+
if (!project || !proxy)
|
|
196
140
|
throw new Error("The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const formData = new FormData();
|
|
200
|
-
formData.append("fileUri", documentId);
|
|
201
|
-
formData.append("fileType", "html");
|
|
202
|
-
const htmlBuffer = buffer.Buffer.from(document.content, "utf-8");
|
|
203
|
-
formData.append("file", new Blob([htmlBuffer]), "".concat(document.name, ".html"));
|
|
204
|
-
localeIds.forEach(localeId => formData.append("localeIdsToAuthorize[]", localeId));
|
|
205
|
-
if (callbackUrl) {
|
|
206
|
-
formData.append("callbackUrl", callbackUrl);
|
|
207
|
-
}
|
|
208
|
-
return fetch(proxy, {
|
|
141
|
+
const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches/${batchUid}/file`, formData = new FormData();
|
|
142
|
+
return formData.append("fileUri", documentId), formData.append("fileType", "html"), formData.append("file", new Blob([document.content]), `${document.name}.html`), localeIds.forEach((localeId) => formData.append("localeIdsToAuthorize[]", localeId)), callbackUrl && formData.append("callbackUrl", callbackUrl), fetch(proxy, {
|
|
209
143
|
method: "POST",
|
|
210
144
|
headers: getHeaders(url, accessToken),
|
|
211
145
|
body: formData
|
|
212
|
-
}).then(res => res.json());
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (!(secrets == null ? void 0 : secrets.project) || !(secrets == null ? void 0 : secrets.secret) || !(secrets == null ? void 0 : secrets.proxy)) {
|
|
146
|
+
}).then((res) => res.json());
|
|
147
|
+
}, createTask = async (documentId, document, localeIds, secrets, workflowUid, callbackUrl) => {
|
|
148
|
+
if (!secrets?.project || !secrets?.secret || !secrets?.proxy)
|
|
216
149
|
throw new Error("The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
217
|
-
}
|
|
218
150
|
const accessToken = await authenticate(secrets);
|
|
219
151
|
let taskId = await findExistingJob(document.name, secrets, accessToken);
|
|
220
|
-
|
|
221
|
-
taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId);
|
|
222
|
-
}
|
|
152
|
+
taskId || (taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId));
|
|
223
153
|
const batchUid = await createJobBatch(taskId, secrets, documentId, accessToken, localeIds, workflowUid);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
154
|
+
return await uploadFileToBatch(batchUid, documentId, document, secrets, localeIds, accessToken, callbackUrl), getTranslationTask(documentId, secrets);
|
|
155
|
+
}, getLocales = async (secrets) => {
|
|
156
|
+
if (!secrets?.project || !secrets?.secret || !secrets?.proxy)
|
|
157
|
+
return [];
|
|
158
|
+
const {
|
|
159
|
+
project,
|
|
160
|
+
proxy
|
|
161
|
+
} = secrets, url = `https://api.smartling.com/projects-api/v2/projects/${project}`, accessToken = await authenticate(secrets);
|
|
162
|
+
return fetch(proxy, {
|
|
163
|
+
method: "GET",
|
|
164
|
+
headers: getHeaders(url, accessToken)
|
|
165
|
+
}).then((res) => res.json()).then((res) => res.response.data.targetLocales);
|
|
166
|
+
}, getTranslation = async (taskId, localeId, secrets) => {
|
|
167
|
+
if (!secrets?.project || !secrets?.secret || !secrets?.proxy)
|
|
230
168
|
throw new Error("The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
|
|
231
|
-
}
|
|
232
169
|
const {
|
|
233
170
|
project,
|
|
234
171
|
proxy
|
|
235
|
-
} = secrets;
|
|
236
|
-
|
|
237
|
-
const accessToken = await authenticate(secrets);
|
|
238
|
-
const translatedHTML = await fetch(proxy, {
|
|
172
|
+
} = secrets, url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`, accessToken = await authenticate(secrets);
|
|
173
|
+
return await fetch(proxy, {
|
|
239
174
|
method: "GET",
|
|
240
175
|
headers: getHeaders(url, accessToken)
|
|
241
|
-
}).then(res => res.json()).then(res => {
|
|
242
|
-
|
|
243
|
-
if (res.body) {
|
|
176
|
+
}).then((res) => res.json()).then((res) => {
|
|
177
|
+
if (res.body)
|
|
244
178
|
return res.body;
|
|
245
|
-
|
|
246
|
-
const errMsg =
|
|
179
|
+
if (res.response.errors) {
|
|
180
|
+
const errMsg = res.response.errors[0]?.message || "Error retrieving translation from Smartling";
|
|
247
181
|
throw new Error(errMsg);
|
|
248
182
|
}
|
|
249
183
|
return "";
|
|
250
184
|
});
|
|
251
|
-
|
|
252
|
-
};
|
|
253
|
-
const SmartlingAdapter = {
|
|
185
|
+
}, SmartlingAdapter = {
|
|
254
186
|
getLocales,
|
|
255
187
|
getTranslationTask,
|
|
256
188
|
createTask,
|
|
257
189
|
getTranslation
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
...sanityTranslationsTab.baseDocumentLevelConfig,
|
|
190
|
+
}, defaultDocumentLevelConfig = {
|
|
191
|
+
...baseDocumentLevelConfig,
|
|
261
192
|
adapter: SmartlingAdapter
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
...sanityTranslationsTab.legacyDocumentLevelConfig,
|
|
193
|
+
}, legacyDocumentLevelConfig = {
|
|
194
|
+
...legacyDocumentLevelConfig$1,
|
|
265
195
|
adapter: SmartlingAdapter
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
...sanityTranslationsTab.baseFieldLevelConfig,
|
|
196
|
+
}, defaultFieldLevelConfig = {
|
|
197
|
+
...baseFieldLevelConfig,
|
|
269
198
|
adapter: SmartlingAdapter
|
|
270
199
|
};
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
Object.defineProperty(exports, 'TranslationsTab', {
|
|
290
|
-
enumerable: true,
|
|
291
|
-
get: function () {
|
|
292
|
-
return sanityTranslationsTab.TranslationsTab;
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
Object.defineProperty(exports, 'customSerializers', {
|
|
296
|
-
enumerable: true,
|
|
297
|
-
get: function () {
|
|
298
|
-
return sanityTranslationsTab.customSerializers;
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
Object.defineProperty(exports, 'defaultStopTypes', {
|
|
302
|
-
enumerable: true,
|
|
303
|
-
get: function () {
|
|
304
|
-
return sanityTranslationsTab.defaultStopTypes;
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
Object.defineProperty(exports, 'documentLevelPatch', {
|
|
308
|
-
enumerable: true,
|
|
309
|
-
get: function () {
|
|
310
|
-
return sanityTranslationsTab.documentLevelPatch;
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
Object.defineProperty(exports, 'fieldLevelPatch', {
|
|
314
|
-
enumerable: true,
|
|
315
|
-
get: function () {
|
|
316
|
-
return sanityTranslationsTab.fieldLevelPatch;
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
Object.defineProperty(exports, 'findLatestDraft', {
|
|
320
|
-
enumerable: true,
|
|
321
|
-
get: function () {
|
|
322
|
-
return sanityTranslationsTab.findLatestDraft;
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
Object.defineProperty(exports, 'legacyDocumentLevelPatch', {
|
|
326
|
-
enumerable: true,
|
|
327
|
-
get: function () {
|
|
328
|
-
return sanityTranslationsTab.legacyDocumentLevelPatch;
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
exports.SmartlingAdapter = SmartlingAdapter;
|
|
332
|
-
exports.defaultDocumentLevelConfig = defaultDocumentLevelConfig;
|
|
333
|
-
exports.defaultFieldLevelConfig = defaultFieldLevelConfig;
|
|
334
|
-
exports.legacyDocumentLevelConfig = legacyDocumentLevelConfig;
|
|
200
|
+
export {
|
|
201
|
+
BaseDocumentDeserializer,
|
|
202
|
+
BaseDocumentMerger,
|
|
203
|
+
BaseDocumentSerializer,
|
|
204
|
+
SmartlingAdapter,
|
|
205
|
+
TranslationsTab,
|
|
206
|
+
customSerializers,
|
|
207
|
+
defaultDocumentLevelConfig,
|
|
208
|
+
defaultFieldLevelConfig,
|
|
209
|
+
defaultStopTypes,
|
|
210
|
+
documentLevelPatch,
|
|
211
|
+
fieldLevelPatch,
|
|
212
|
+
findLatestDraft,
|
|
213
|
+
legacyDocumentLevelConfig,
|
|
214
|
+
legacyDocumentLevelPatch
|
|
215
|
+
};
|
|
335
216
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/adapter/helpers.ts","../src/adapter/getLocales.ts","../src/adapter/getTranslationTask.ts","../src/adapter/createTask.ts","../src/adapter/getTranslation.ts","../src/adapter/index.ts","../src/index.ts"],"sourcesContent":["import {Secrets} from 'sanity-translations-tab'\n\ninterface Headers {\n [key: string]: string\n}\n\nexport const authenticate = (secrets: Secrets): Promise<string> => {\n const url = 'https://api.smartling.com/auth-api/v2/authenticate'\n const headers = {\n 'content-type': 'application/json',\n 'X-URL': url,\n }\n const {secret, proxy} = secrets\n if (!secret || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n return fetch(proxy, {\n headers,\n method: 'POST',\n body: JSON.stringify(secret),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.accessToken)\n}\n\nexport const getHeaders = (url: string, accessToken: string): Headers => ({\n Authorization: `Bearer ${accessToken}`,\n 'X-URL': url,\n})\n\nexport const findExistingJob = async (\n documentId: string,\n secrets: Secrets,\n accessToken: string,\n): Promise<string> => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`\n //first, try fetching from name resolution\n let items = await fetch(proxy, {\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res?.response?.data?.items)\n\n if (!items || !items.length) {\n //if that fails, try fetching by fileUri and check the referenceNumber\n const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`\n items = await fetch(proxy, {\n headers: {\n ...getHeaders(refUrl, accessToken),\n 'content-type': 'application/json',\n },\n method: 'POST',\n body: JSON.stringify({\n fileUris: [documentId],\n }),\n })\n .then((res) => res.json())\n .then((res) => res?.response?.data?.items)\n }\n\n if (items.length) {\n //smartling will fuzzy match job names. We need to be precise.\n const correctJob = items\n .filter((item: {jobStatus: string}) => item.jobStatus !== 'DELETED')\n .find(\n (item: {jobName: string; referenceNumber: string}) =>\n (item.jobName && item.jobName === documentId) ||\n (item.referenceNumber && item.referenceNumber === documentId),\n )\n\n if (correctJob) {\n return correctJob.translationJobUid\n }\n }\n return ''\n}\n","import {authenticate, getHeaders} from './helpers'\nimport {Secrets} from 'sanity-translations-tab'\nimport {Adapter} from 'sanity-translations-tab'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n return []\n }\n const {project, proxy} = secrets\n const url = `https://api.smartling.com/projects-api/v2/projects/${project}`\n const accessToken = await authenticate(secrets)\n return fetch(proxy, {\n method: 'GET',\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.targetLocales)\n}\n","import {authenticate, getHeaders, findExistingJob} from './helpers'\nimport {Adapter, Secrets} from 'sanity-translations-tab'\n\ninterface WorkflowProgressItem {\n workflowStepSummaryReportItemList: {\n wordCount: number\n }[]\n}\n\ninterface SmartlingProgressItem {\n targetLocaleId: string\n progress: {\n percentComplete: number\n totalWordCount: number\n }\n workflowProgressReportList: WorkflowProgressItem[]\n}\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n documentId: string,\n secrets: Secrets | null,\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n return {\n documentId,\n taskId: documentId,\n locales: [],\n }\n }\n\n const {project, proxy} = secrets\n\n const accessToken = await authenticate(secrets)\n const taskId = await findExistingJob(documentId, secrets, accessToken)\n if (!taskId) {\n return {\n documentId,\n taskId: documentId,\n locales: [],\n }\n }\n\n const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`\n const smartlingTask = await fetch(proxy, {\n method: 'GET',\n headers: getHeaders(progressUrl, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res.response.data)\n\n let locales = []\n if (smartlingTask && smartlingTask.contentProgressReport) {\n locales = smartlingTask.contentProgressReport.map((item: SmartlingProgressItem) => {\n let progress = item.progress ? item.progress.percentComplete : 0\n if (\n item.workflowProgressReportList &&\n item.workflowProgressReportList.length > 0 &&\n item.progress\n ) {\n //default to the first workflow -- it's likely what is being used\n const progressItem = item.workflowProgressReportList[0]\n //this is a list of the various steps in the workflow\n if (\n progressItem.workflowStepSummaryReportItemList &&\n progressItem.workflowStepSummaryReportItemList.length > 1\n ) {\n //get the last step in the workflow -- usually \"published\"\n const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1)\n //get the percentage of how many words have reached the last step\n if (lastStep && lastStep.wordCount >= 0) {\n progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100) ?? 0\n }\n }\n }\n return {\n localeId: item.targetLocaleId,\n progress,\n }\n })\n }\n\n return {\n documentId,\n locales,\n //since our download is tied to document id for smartling, keep track of it as a task\n taskId: documentId,\n linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`,\n }\n}\n","import {authenticate, getHeaders, findExistingJob} from './helpers'\nimport {Adapter, Secrets, SerializedDocument} from 'sanity-translations-tab'\nimport {getTranslationTask} from './getTranslationTask'\nimport {Buffer} from 'buffer'\n\nconst createJob = (\n jobName: string,\n secrets: Secrets,\n localeIds: string[],\n accessToken: string,\n documentId: string,\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs`\n return fetch(proxy, {\n method: 'POST',\n headers: {\n ...getHeaders(url, accessToken),\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n jobName,\n targetLocaleIds: localeIds,\n referenceNumber: documentId,\n }),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.translationJobUid)\n}\n\n/* we're using batches here because it eliminates some\n * new string authorization issues for updating existing jobs,\n * and is able to be used for new bulk\n * job functionality.\n */\n\nconst createJobBatch = (\n jobId: string,\n secrets: Secrets,\n documentId: string,\n accessToken: string,\n localeIds: string[],\n workflowUid?: string,\n //eslint-disable-next-line max-params\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches`\n const reqBody: {\n authorize: boolean\n translationJobUid: string\n fileUris: string[]\n localeWorkflows?: {targetLocaleId: string; workflowUid: string}[]\n } = {\n authorize: true,\n translationJobUid: jobId,\n fileUris: [documentId],\n }\n\n if (workflowUid) {\n reqBody.localeWorkflows = localeIds.map((l) => ({\n targetLocaleId: l,\n workflowUid,\n }))\n }\n\n return fetch(proxy, {\n method: 'POST',\n headers: {\n ...getHeaders(url, accessToken),\n 'content-type': 'application/json',\n },\n body: JSON.stringify(reqBody),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.batchUid)\n}\n\nconst uploadFileToBatch = (\n batchUid: string,\n documentId: string,\n document: SerializedDocument,\n secrets: Secrets,\n localeIds: string[],\n accessToken: string,\n callbackUrl?: string,\n //eslint-disable-next-line max-params\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches/${batchUid}/file`\n const formData = new FormData()\n formData.append('fileUri', documentId)\n formData.append('fileType', 'html')\n const htmlBuffer = Buffer.from(document.content, 'utf-8')\n formData.append('file', new Blob([htmlBuffer]), `${document.name}.html`)\n localeIds.forEach((localeId) => formData.append('localeIdsToAuthorize[]', localeId))\n if (callbackUrl) {\n formData.append('callbackUrl', callbackUrl)\n }\n\n return fetch(proxy, {\n method: 'POST',\n headers: getHeaders(url, accessToken),\n body: formData,\n }).then((res) => res.json())\n}\n\nexport const createTask: Adapter['createTask'] = async (\n documentId: string,\n document: SerializedDocument,\n localeIds: string[],\n secrets: Secrets | null,\n workflowUid?: string,\n callbackUrl?: string,\n // eslint-disable-next-line max-params\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n throw new Error(\n 'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const accessToken = await authenticate(secrets)\n\n let taskId = await findExistingJob(document.name, secrets, accessToken)\n if (!taskId) {\n taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId)\n }\n\n const batchUid = await createJobBatch(\n taskId,\n secrets,\n documentId,\n accessToken,\n localeIds,\n workflowUid,\n )\n const uploadFileRes = await uploadFileToBatch(\n batchUid,\n documentId,\n document,\n secrets,\n localeIds,\n accessToken,\n callbackUrl,\n )\n //eslint-disable-next-line no-console -- for developer debugging\n console.info('Upload status from Smartling: ', uploadFileRes)\n\n return getTranslationTask(documentId, secrets)\n}\n","import {authenticate, getHeaders} from './helpers'\nimport {Adapter, Secrets} from 'sanity-translations-tab'\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n taskId: string,\n localeId: string,\n secrets: Secrets | null,\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n throw new Error(\n 'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const {project, proxy} = secrets\n\n const url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`\n const accessToken = await authenticate(secrets)\n const translatedHTML = await fetch(proxy, {\n method: 'GET',\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => {\n if (res.body) {\n return res.body\n } else if (res.response.errors) {\n const errMsg =\n res.response.errors[0]?.message || 'Error retrieving translation from Smartling'\n throw new Error(errMsg)\n }\n return ''\n })\n\n return translatedHTML\n}\n","import {Adapter} from 'sanity-translations-tab'\nimport {getLocales} from './getLocales'\nimport {getTranslationTask} from './getTranslationTask'\nimport {createTask} from './createTask'\nimport {getTranslation} from './getTranslation'\n\nexport const SmartlingAdapter: Adapter = {\n getLocales,\n getTranslationTask,\n createTask,\n getTranslation,\n}\n","import {\n TranslationsTab,\n baseDocumentLevelConfig,\n legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n baseFieldLevelConfig,\n findLatestDraft,\n BaseDocumentDeserializer,\n BaseDocumentSerializer,\n BaseDocumentMerger,\n defaultStopTypes,\n customSerializers,\n legacyDocumentLevelPatch,\n documentLevelPatch,\n fieldLevelPatch,\n TranslationFunctionContext,\n TranslationsTabConfigOptions,\n} from 'sanity-translations-tab'\nimport {SmartlingAdapter} from './adapter'\n\nconst defaultDocumentLevelConfig: TranslationsTabConfigOptions = {\n ...baseDocumentLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nconst legacyDocumentLevelConfig: TranslationsTabConfigOptions = {\n ...baseLegacyDocumentLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nconst defaultFieldLevelConfig: TranslationsTabConfigOptions = {\n ...baseFieldLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nexport {\n TranslationsTab,\n findLatestDraft,\n legacyDocumentLevelPatch,\n documentLevelPatch,\n fieldLevelPatch,\n BaseDocumentDeserializer,\n BaseDocumentSerializer,\n BaseDocumentMerger,\n defaultStopTypes,\n customSerializers,\n SmartlingAdapter,\n legacyDocumentLevelConfig,\n defaultDocumentLevelConfig,\n defaultFieldLevelConfig,\n}\n\nexport type {TranslationFunctionContext, TranslationsTabConfigOptions}\n"],"names":["authenticate","secrets","url","headers","secret","proxy","Error","fetch","method","body","JSON","stringify","then","res","json","response","data","accessToken","getHeaders","Authorization","concat","findExistingJob","documentId","project","items","_a","_b","length","refUrl","fileUris","correctJob","filter","item","jobStatus","find","jobName","referenceNumber","translationJobUid","getLocales","targetLocales","getTranslationTask","taskId","locales","progressUrl","smartlingTask","contentProgressReport","map","progress","percentComplete","workflowProgressReportList","progressItem","workflowStepSummaryReportItemList","lastStep","at","wordCount","Math","floor","totalWordCount","localeId","targetLocaleId","linkToVendorTask","createJob","localeIds","targetLocaleIds","createJobBatch","jobId","workflowUid","reqBody","authorize","localeWorkflows","l","batchUid","uploadFileToBatch","document","callbackUrl","formData","FormData","append","htmlBuffer","Buffer","from","content","Blob","name","forEach","createTask","uploadFileRes","console","info","getTranslation","translatedHTML","errors","errMsg","message","SmartlingAdapter","defaultDocumentLevelConfig","baseDocumentLevelConfig","adapter","legacyDocumentLevelConfig","baseLegacyDocumentLevelConfig","defaultFieldLevelConfig","baseFieldLevelConfig"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/adapter/helpers.ts","../src/adapter/getTranslationTask.ts","../src/adapter/createTask.ts","../src/adapter/getLocales.ts","../src/adapter/getTranslation.ts","../src/adapter/index.ts","../src/index.ts"],"sourcesContent":["import type {Secrets} from 'sanity-translations-tab'\n\nexport const authenticate = (secrets: Secrets): Promise<string> => {\n const url = 'https://api.smartling.com/auth-api/v2/authenticate'\n const headers = {\n 'content-type': 'application/json',\n 'X-URL': url,\n }\n const {secret, proxy} = secrets\n if (!secret || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n return fetch(proxy, {\n headers,\n method: 'POST',\n body: JSON.stringify(secret),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.accessToken)\n}\n\nexport const getHeaders = (url: string, accessToken: string): Record<string, string> => ({\n 'Authorization': `Bearer ${accessToken}`,\n 'X-URL': url,\n})\n\nexport const findExistingJob = async (\n documentId: string,\n secrets: Secrets,\n accessToken: string,\n): Promise<string> => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`\n //first, try fetching from name resolution\n let items = await fetch(proxy, {\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res?.response?.data?.items)\n\n if (!items || !items.length) {\n //if that fails, try fetching by fileUri and check the referenceNumber\n const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`\n items = await fetch(proxy, {\n headers: {\n ...getHeaders(refUrl, accessToken),\n 'content-type': 'application/json',\n },\n method: 'POST',\n body: JSON.stringify({\n fileUris: [documentId],\n }),\n })\n .then((res) => res.json())\n .then((res) => res?.response?.data?.items)\n }\n\n if (items.length) {\n //smartling will fuzzy match job names. We need to be precise.\n const correctJob = items\n .filter((item: {jobStatus: string}) => item.jobStatus !== 'DELETED')\n .find(\n (item: {jobName: string; referenceNumber: string}) =>\n (item.jobName && item.jobName === documentId) ||\n (item.referenceNumber && item.referenceNumber === documentId),\n )\n\n if (correctJob) {\n return correctJob.translationJobUid\n }\n }\n return ''\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\ninterface WorkflowProgressItem {\n workflowStepSummaryReportItemList: {\n wordCount: number\n }[]\n}\n\ninterface SmartlingProgressItem {\n targetLocaleId: string\n progress: {\n percentComplete: number\n totalWordCount: number\n }\n workflowProgressReportList: WorkflowProgressItem[]\n}\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n documentId: string,\n secrets: Secrets | null,\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n return {\n documentId,\n taskId: documentId,\n locales: [],\n }\n }\n\n const {project, proxy} = secrets\n\n const accessToken = await authenticate(secrets)\n const taskId = await findExistingJob(documentId, secrets, accessToken)\n if (!taskId) {\n return {\n documentId,\n taskId: documentId,\n locales: [],\n }\n }\n\n const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`\n const smartlingTask = await fetch(proxy, {\n method: 'GET',\n headers: getHeaders(progressUrl, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res.response.data)\n\n let locales = []\n if (smartlingTask && smartlingTask.contentProgressReport) {\n locales = smartlingTask.contentProgressReport.map((item: SmartlingProgressItem) => {\n let progress = item.progress ? item.progress.percentComplete : 0\n //default to the first workflow -- it's likely what is being used\n const progressItem = item.workflowProgressReportList?.[0]\n if (progressItem && item.progress) {\n //this is a list of the various steps in the workflow\n if (\n progressItem.workflowStepSummaryReportItemList &&\n progressItem.workflowStepSummaryReportItemList.length > 1\n ) {\n //get the last step in the workflow -- usually \"published\"\n const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1)\n //get the percentage of how many words have reached the last step\n if (lastStep && lastStep.wordCount >= 0) {\n progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100) ?? 0\n }\n }\n }\n return {\n localeId: item.targetLocaleId,\n progress,\n }\n })\n }\n\n return {\n documentId,\n locales,\n //since our download is tied to document id for smartling, keep track of it as a task\n taskId: documentId,\n linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`,\n }\n}\n","import type {Adapter, Secrets, SerializedDocument} from 'sanity-translations-tab'\n\nimport {getTranslationTask} from './getTranslationTask'\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\nconst createJob = (\n jobName: string,\n secrets: Secrets,\n localeIds: string[],\n accessToken: string,\n documentId: string,\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs`\n return fetch(proxy, {\n method: 'POST',\n headers: {\n ...getHeaders(url, accessToken),\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n jobName,\n targetLocaleIds: localeIds,\n referenceNumber: documentId,\n }),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.translationJobUid)\n}\n\n/* we're using batches here because it eliminates some\n * new string authorization issues for updating existing jobs,\n * and is able to be used for new bulk\n * job functionality.\n */\n\nconst createJobBatch = (\n jobId: string,\n secrets: Secrets,\n documentId: string,\n accessToken: string,\n localeIds: string[],\n workflowUid?: string,\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches`\n const reqBody: {\n authorize: boolean\n translationJobUid: string\n fileUris: string[]\n localeWorkflows?: {targetLocaleId: string; workflowUid: string}[]\n } = {\n authorize: true,\n translationJobUid: jobId,\n fileUris: [documentId],\n }\n\n if (workflowUid) {\n reqBody.localeWorkflows = localeIds.map((l) => ({\n targetLocaleId: l,\n workflowUid,\n }))\n }\n\n return fetch(proxy, {\n method: 'POST',\n headers: {\n ...getHeaders(url, accessToken),\n 'content-type': 'application/json',\n },\n body: JSON.stringify(reqBody),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.batchUid)\n}\n\nconst uploadFileToBatch = (\n batchUid: string,\n documentId: string,\n document: SerializedDocument,\n secrets: Secrets,\n localeIds: string[],\n accessToken: string,\n callbackUrl?: string,\n) => {\n const {project, proxy} = secrets\n if (!project || !proxy) {\n throw new Error(\n 'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches/${batchUid}/file`\n const formData = new FormData()\n formData.append('fileUri', documentId)\n formData.append('fileType', 'html')\n formData.append('file', new Blob([document.content]), `${document.name}.html`)\n localeIds.forEach((localeId) => formData.append('localeIdsToAuthorize[]', localeId))\n if (callbackUrl) {\n formData.append('callbackUrl', callbackUrl)\n }\n\n return fetch(proxy, {\n method: 'POST',\n headers: getHeaders(url, accessToken),\n body: formData,\n }).then((res) => res.json())\n}\n\nexport const createTask: Adapter['createTask'] = async (\n documentId: string,\n document: SerializedDocument,\n localeIds: string[],\n secrets: Secrets | null,\n workflowUid?: string,\n callbackUrl?: string,\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n throw new Error(\n 'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const accessToken = await authenticate(secrets)\n\n let taskId = await findExistingJob(document.name, secrets, accessToken)\n if (!taskId) {\n taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId)\n }\n\n const batchUid = await createJobBatch(\n taskId,\n secrets,\n documentId,\n accessToken,\n localeIds,\n workflowUid,\n )\n await uploadFileToBatch(\n batchUid,\n documentId,\n document,\n secrets,\n localeIds,\n accessToken,\n callbackUrl,\n )\n\n return getTranslationTask(documentId, secrets)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n return []\n }\n const {project, proxy} = secrets\n const url = `https://api.smartling.com/projects-api/v2/projects/${project}`\n const accessToken = await authenticate(secrets)\n return fetch(proxy, {\n method: 'GET',\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => res.response.data.targetLocales)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n taskId: string,\n localeId: string,\n secrets: Secrets | null,\n) => {\n if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n throw new Error(\n 'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n )\n }\n\n const {project, proxy} = secrets\n\n const url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`\n const accessToken = await authenticate(secrets)\n const translatedHTML = await fetch(proxy, {\n method: 'GET',\n headers: getHeaders(url, accessToken),\n })\n .then((res) => res.json())\n .then((res) => {\n if (res.body) {\n return res.body\n } else if (res.response.errors) {\n const errMsg =\n res.response.errors[0]?.message || 'Error retrieving translation from Smartling'\n throw new Error(errMsg)\n }\n return ''\n })\n\n return translatedHTML\n}\n","import type {Adapter} from 'sanity-translations-tab'\n\nimport {createTask} from './createTask'\nimport {getLocales} from './getLocales'\nimport {getTranslation} from './getTranslation'\nimport {getTranslationTask} from './getTranslationTask'\n\nexport const SmartlingAdapter: Adapter = {\n getLocales,\n getTranslationTask,\n createTask,\n getTranslation,\n}\n","import {\n baseDocumentLevelConfig,\n baseFieldLevelConfig,\n legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n} from 'sanity-translations-tab'\nimport type {TranslationsTabConfigOptions} from 'sanity-translations-tab'\n\nimport {SmartlingAdapter} from './adapter'\n\nexport {\n BaseDocumentDeserializer,\n BaseDocumentMerger,\n BaseDocumentSerializer,\n customSerializers,\n defaultStopTypes,\n documentLevelPatch,\n fieldLevelPatch,\n findLatestDraft,\n legacyDocumentLevelPatch,\n TranslationsTab,\n} from 'sanity-translations-tab'\nexport type {\n TranslationFunctionContext,\n TranslationsTabConfigOptions,\n} from 'sanity-translations-tab'\n\nconst defaultDocumentLevelConfig: TranslationsTabConfigOptions = {\n ...baseDocumentLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nconst legacyDocumentLevelConfig: TranslationsTabConfigOptions = {\n ...baseLegacyDocumentLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nconst defaultFieldLevelConfig: TranslationsTabConfigOptions = {\n ...baseFieldLevelConfig,\n adapter: SmartlingAdapter,\n}\n\nexport {\n defaultDocumentLevelConfig,\n defaultFieldLevelConfig,\n legacyDocumentLevelConfig,\n SmartlingAdapter,\n}\n"],"names":["authenticate","secrets","headers","secret","proxy","Error","fetch","method","body","JSON","stringify","then","res","json","response","data","accessToken","getHeaders","url","findExistingJob","documentId","project","items","length","refUrl","fileUris","correctJob","filter","item","jobStatus","find","jobName","referenceNumber","translationJobUid","getTranslationTask","taskId","locales","progressUrl","smartlingTask","contentProgressReport","map","progress","percentComplete","progressItem","workflowProgressReportList","workflowStepSummaryReportItemList","lastStep","at","wordCount","Math","floor","totalWordCount","localeId","targetLocaleId","linkToVendorTask","createJob","localeIds","targetLocaleIds","createJobBatch","jobId","workflowUid","reqBody","authorize","localeWorkflows","l","batchUid","uploadFileToBatch","document","callbackUrl","formData","FormData","append","Blob","content","name","forEach","createTask","getLocales","targetLocales","getTranslation","errors","errMsg","message","SmartlingAdapter","defaultDocumentLevelConfig","baseDocumentLevelConfig","adapter","legacyDocumentLevelConfig","baseLegacyDocumentLevelConfig","defaultFieldLevelConfig","baseFieldLevelConfig"],"mappings":"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"}
|