@azure-rest/ai-translation-document 1.0.0-beta.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/CHANGELOG.md +23 -0
- package/README.md +346 -0
- package/dist/index.js +299 -0
- package/dist/index.js.map +1 -0
- package/dist-esm/src/clientDefinitions.js +4 -0
- package/dist-esm/src/clientDefinitions.js.map +1 -0
- package/dist-esm/src/documentTranslationClient.js +30 -0
- package/dist-esm/src/documentTranslationClient.js.map +1 -0
- package/dist-esm/src/index.js +15 -0
- package/dist-esm/src/index.js.map +1 -0
- package/dist-esm/src/isUnexpected.js +77 -0
- package/dist-esm/src/isUnexpected.js.map +1 -0
- package/dist-esm/src/logger.js +5 -0
- package/dist-esm/src/logger.js.map +1 -0
- package/dist-esm/src/models.js +4 -0
- package/dist-esm/src/models.js.map +1 -0
- package/dist-esm/src/outputModels.js +4 -0
- package/dist-esm/src/outputModels.js.map +1 -0
- package/dist-esm/src/paginateHelper.js +70 -0
- package/dist-esm/src/paginateHelper.js.map +1 -0
- package/dist-esm/src/parameters.js +4 -0
- package/dist-esm/src/parameters.js.map +1 -0
- package/dist-esm/src/pollingHelper.js +97 -0
- package/dist-esm/src/pollingHelper.js.map +1 -0
- package/dist-esm/src/responses.js +4 -0
- package/dist-esm/src/responses.js.map +1 -0
- package/package.json +123 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Release History
|
|
2
|
+
## 1.0.0-beta.1 (2024-06-27)
|
|
3
|
+
- Initial release. Please see the README and wiki for information on the new design.
|
|
4
|
+
|
|
5
|
+
Version 1.0.0-beta.1 is preview of our efforts in creating a client library that is developer-friendly, idiomatic
|
|
6
|
+
to the JS/TS ecosystem, and as consistent across different languages and platforms as possible.
|
|
7
|
+
|
|
8
|
+
This package's
|
|
9
|
+
[documentation](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/README.md)
|
|
10
|
+
and
|
|
11
|
+
[samples](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples)
|
|
12
|
+
demonstrate the new API.
|
|
13
|
+
|
|
14
|
+
### Features Added
|
|
15
|
+
- Added support for Synchronous document translation - [translate-document API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/translate-document)
|
|
16
|
+
- Added support for Batch Translation - [start Translation API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/start-batch-translation)
|
|
17
|
+
- Added support for Get Translations Status - [get translations status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-translations-status)
|
|
18
|
+
- Added support for Get Translation Status - [get translation status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-translation-status)
|
|
19
|
+
- Added support for Get Documents Status - [get documents status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-documents-status)
|
|
20
|
+
- Added support for Get Document Status - [get document status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-document-status)
|
|
21
|
+
- Added support for Cancel Translation - [cancel translation API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/cancel-translation)
|
|
22
|
+
- Added support for Get Supported Document Formats - [get supported document formats API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-supported-document-formats)
|
|
23
|
+
- Added support for Get Supported Glossary Formats - [get supported glossary formats API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-supported-glossary-formats)
|
package/README.md
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# DocumentTranslation REST client library for JavaScript
|
|
2
|
+
|
|
3
|
+
Document Translation is a cloud-based machine translation feature of the Azure AI Translator service. You can translate multiple and complex documents across all supported languages and dialects while preserving original document structure and data format. The Document translation API supports two translation processes:
|
|
4
|
+
|
|
5
|
+
Asynchronous batch translation supports the processing of multiple documents and large files. The batch translation process requires an Azure Blob storage account with storage containers for your source and translated documents.
|
|
6
|
+
|
|
7
|
+
Synchronous single file supports the processing of single file translations. The file translation process doesn't require an Azure Blob storage account. The final response contains the translated document and is returned directly to the calling client.
|
|
8
|
+
|
|
9
|
+
The following operations are supported by the Document Translation feature:
|
|
10
|
+
|
|
11
|
+
- **Synchronous document translation**: Used to synchronously translate a single document. The method doesn't require an Azure Blob storage account.
|
|
12
|
+
|
|
13
|
+
- **Start batch translation**: Used to execute an asynchronous batch translation request. The method requires an Azure Blob storage account with storage containers for your source and translated documents.
|
|
14
|
+
|
|
15
|
+
- **Get status for all translation jobs**: Used to request a list and the status of all translation jobs submitted by the user (associated with the resource).
|
|
16
|
+
|
|
17
|
+
- **Get status for a specific translation job**: Used to request the status of a specific translation job. The response includes the overall job status and the status for documents that are being translated as part of that job.
|
|
18
|
+
|
|
19
|
+
- **Get status for all documents**: Used to request the status for all documents in a translation job.
|
|
20
|
+
|
|
21
|
+
- **Get status for a specific document**: This returns the status for a specific document in a job as indicated in the request by the id and documentId query parameters.
|
|
22
|
+
|
|
23
|
+
- **Cancel translation**: This cancels a translation job that is currently processing or queued (pending) as indicated in the request by the id query parameter. An operation isn't canceled if already completed, failed, or still canceling. In those instances, a bad request is returned. Completed translations can't be canceled and are charged.
|
|
24
|
+
|
|
25
|
+
- **Get supported formats**: This returns a list of document or glossary formats supported by the Document Translation feature. The list includes common file extensions and content-type if using the upload API.
|
|
26
|
+
|
|
27
|
+
Key links:
|
|
28
|
+
|
|
29
|
+
- [Source code](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest)
|
|
30
|
+
- [Package (NPM)](https://www.npmjs.com/package/@azure-rest/ai-translation-document)
|
|
31
|
+
- [Samples](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest/samples)
|
|
32
|
+
|
|
33
|
+
## Getting started
|
|
34
|
+
|
|
35
|
+
### Currently supported environments
|
|
36
|
+
|
|
37
|
+
- LTS versions of Node.js
|
|
38
|
+
- Latest versions of Edge, Chrome, Safar and Firefox
|
|
39
|
+
|
|
40
|
+
### Prerequisites
|
|
41
|
+
|
|
42
|
+
- An existing Translator service or Cognitive Services resource. More info on [Pre-requisites][pre_requisities].
|
|
43
|
+
|
|
44
|
+
### Install the `@azure-rest/ai-translation-document` package
|
|
45
|
+
|
|
46
|
+
Install the Document Translation REST client library for JavaScript with `npm`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @azure-rest/ai-translation-document
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### Create a Translator service resource
|
|
53
|
+
|
|
54
|
+
You can create Translator resource following [Create a Translator resource][translator_resource_create].
|
|
55
|
+
|
|
56
|
+
### Create a `DocumentTranslationClient` using an endpoint URL and API key `KeyCredential`
|
|
57
|
+
|
|
58
|
+
Once you have the value for API key, create a credential
|
|
59
|
+
```typescript
|
|
60
|
+
const credentials = { key: apiKey ?? "" };
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
With the value of the `KeyCredential` you can create the `DocumentTranslationClient` using the `createClient` method of [documentTranslationClient_class]:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const client = createClient(endpoint, credentials);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Examples
|
|
70
|
+
|
|
71
|
+
The following section provides several code snippets using the `client`, and covers the main features present in this client library.
|
|
72
|
+
|
|
73
|
+
### Synchronous Document Translation
|
|
74
|
+
|
|
75
|
+
Used to synchronously translate a single document. The method doesn't require an Azure Blob storage account.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
console.log("== Synchronous Document Translation ==");
|
|
79
|
+
const client = createClient(endpoint, credentials);
|
|
80
|
+
const options: DocumentTranslateParameters = {
|
|
81
|
+
queryParameters: {
|
|
82
|
+
targetLanguage: "hi",
|
|
83
|
+
},
|
|
84
|
+
contentType: "multipart/form-data",
|
|
85
|
+
body: [
|
|
86
|
+
{
|
|
87
|
+
name: "document",
|
|
88
|
+
body: "This is a test.",
|
|
89
|
+
filename: "test-input.txt",
|
|
90
|
+
contentType: "text/html",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const response = await client.path("/document:translate").post(options);
|
|
96
|
+
if (isUnexpected(response)) {
|
|
97
|
+
throw response.body;
|
|
98
|
+
}
|
|
99
|
+
console.log('Response code: ' + response.status + ', Response body: ' + response.body);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Batch Document Translation
|
|
103
|
+
Used to execute an asynchronous batch translation request. The method requires an Azure Blob storage account with storage containers for your source and translated documents.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
console.log("== Batch Document Translation ==");
|
|
107
|
+
const client = createClient(endpoint, credentials);
|
|
108
|
+
|
|
109
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
110
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
111
|
+
const targetUrl = await createTargetContainer();
|
|
112
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
113
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
114
|
+
|
|
115
|
+
//Start translation
|
|
116
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
117
|
+
const poller = await client.path("/document/batches").post({
|
|
118
|
+
body: batchRequests
|
|
119
|
+
});
|
|
120
|
+
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
|
121
|
+
console.log('Translation started and the operationID is: ' + id);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Cancel Document Translation
|
|
125
|
+
This cancels a translation job that is currently processing or queued (pending) as indicated in the request by the id query parameter. An operation isn't canceled if already completed, failed, or still canceling. In those instances, a bad request is returned. Completed translations can't be canceled and are charged.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
console.log("== Cancel Translation ==");
|
|
129
|
+
const client = createClient(endpoint, credentials);
|
|
130
|
+
|
|
131
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
132
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
133
|
+
const targetUrl = await createTargetContainer();
|
|
134
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
135
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
136
|
+
|
|
137
|
+
//Start translation
|
|
138
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
139
|
+
const poller = await client.path("/document/batches").post({
|
|
140
|
+
body: batchRequests
|
|
141
|
+
});
|
|
142
|
+
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
|
143
|
+
|
|
144
|
+
//Cancel translation
|
|
145
|
+
await client.path("/document/batches/{id}", id).delete();
|
|
146
|
+
|
|
147
|
+
//get translation status and verify the job is cancelled, cancelling or notStarted
|
|
148
|
+
const response = await client.path("/document/batches/{id}", id).get();
|
|
149
|
+
if (isUnexpected(response)) {
|
|
150
|
+
throw response.body;
|
|
151
|
+
}
|
|
152
|
+
console.log("The status after cancelling the batch operation is:" + response.body.status);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Get Documents Status
|
|
156
|
+
Used to request the status for all documents in a translation job.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
console.log("== Gets Documents Status ==");
|
|
160
|
+
const client = createClient(endpoint, credentials);
|
|
161
|
+
|
|
162
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
163
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
164
|
+
const targetUrl = await createTargetContainer();
|
|
165
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
166
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
167
|
+
|
|
168
|
+
//Start translation
|
|
169
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
170
|
+
const response = await StartTranslationAndWait(client, batchRequests);
|
|
171
|
+
|
|
172
|
+
const operationLocationUrl = response.headers["operation-location"]
|
|
173
|
+
const operationId = getTranslationOperationID(operationLocationUrl);
|
|
174
|
+
|
|
175
|
+
//get Documents Status
|
|
176
|
+
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
|
177
|
+
if (isUnexpected(documentResponse)) {
|
|
178
|
+
throw documentResponse.body;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const responseBody = documentResponse.body;
|
|
182
|
+
for (const documentStatus of responseBody.value) {
|
|
183
|
+
console.log("Document Status is: " + documentStatus.status);
|
|
184
|
+
console.log("Characters charged is: " + documentStatus.characterCharged);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Get Document Status
|
|
190
|
+
This returns the status for a specific document in a job as indicated in the request by the id and documentId query parameters.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
console.log("== Get Document Status ==");
|
|
194
|
+
const client = createClient(endpoint, credentials);
|
|
195
|
+
|
|
196
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
197
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
198
|
+
const targetUrl = await createTargetContainer();
|
|
199
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
200
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
201
|
+
|
|
202
|
+
//Start translation
|
|
203
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
204
|
+
const response = await StartTranslationAndWait(client, batchRequests);
|
|
205
|
+
const operationLocationUrl = response.headers["operation-location"]
|
|
206
|
+
const operationId = getTranslationOperationID(operationLocationUrl);
|
|
207
|
+
|
|
208
|
+
//get Documents Status
|
|
209
|
+
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
|
210
|
+
if (isUnexpected(documentResponse)) {
|
|
211
|
+
throw documentResponse.body;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const responseBody = documentResponse.body;
|
|
215
|
+
for (const document of responseBody.value) {
|
|
216
|
+
//get document status
|
|
217
|
+
const documentStatus = await client.path("/document/batches/{id}/documents/{documentId}", operationId, document.id).get();
|
|
218
|
+
console.log("Document Status = " + documentStatus.status);
|
|
219
|
+
const documentStatusOutput = documentStatus.body as DocumentStatusOutput;
|
|
220
|
+
console.log("Document ID = " +documentStatusOutput.id);
|
|
221
|
+
console.log("Document source path = " + documentStatusOutput.sourcePath);
|
|
222
|
+
console.log("Document path = " + documentStatusOutput.path);
|
|
223
|
+
console.log("Target language = " + documentStatusOutput.to);
|
|
224
|
+
console.log("Document created dateTime = " + documentStatusOutput.createdDateTimeUtc);
|
|
225
|
+
console.log("Document last action date time = " + documentStatusOutput.lastActionDateTimeUtc);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Get Translations Status
|
|
230
|
+
Used to request a list and the status of all translation jobs submitted by the user (associated with the resource).
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
console.log("== Get Translations Status ==");
|
|
234
|
+
const client = createClient(endpoint, credentials);
|
|
235
|
+
|
|
236
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
237
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
238
|
+
const targetUrl = await createTargetContainer();
|
|
239
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
240
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
241
|
+
|
|
242
|
+
//Start translation
|
|
243
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
244
|
+
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
|
245
|
+
const operationLocationUrl = translationResponse.headers["operation-location"]
|
|
246
|
+
const operationId = getTranslationOperationID(operationLocationUrl);
|
|
247
|
+
|
|
248
|
+
//get Translation Statusby ID filter
|
|
249
|
+
const queryParams = {
|
|
250
|
+
ids: [operationId]
|
|
251
|
+
};
|
|
252
|
+
const response = await client.path("/document/batches").get({
|
|
253
|
+
queryParameters: queryParams
|
|
254
|
+
});
|
|
255
|
+
if (isUnexpected(response)) {
|
|
256
|
+
throw response.body;
|
|
257
|
+
}
|
|
258
|
+
const responseBody = response.body;
|
|
259
|
+
for (const translationStatus of responseBody.value) {
|
|
260
|
+
console.log("Translation ID = " + translationStatus.id);
|
|
261
|
+
console.log("Translation Status = " + translationStatus.status);
|
|
262
|
+
console.log("Translation createdDateTimeUtc = " + translationStatus.createdDateTimeUtc);
|
|
263
|
+
console.log("Translation lastActionDateTimeUtc = " + translationStatus.lastActionDateTimeUtc);
|
|
264
|
+
console.log("Total documents submitted for translation = " + translationStatus.summary.total);
|
|
265
|
+
console.log("Total characters charged = " + translationStatus.summary.totalCharacterCharged);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Get Translation Status
|
|
270
|
+
Used to request the status of a specific translation job. The response includes the overall job status and the status for documents that are being translated as part of that job.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
console.log("== Get Translation Status ==");
|
|
274
|
+
const client = createClient(endpoint, credentials);
|
|
275
|
+
|
|
276
|
+
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
|
277
|
+
const sourceInput = createSourceInput(sourceUrl);
|
|
278
|
+
const targetUrl = await createTargetContainer();
|
|
279
|
+
const targetInput = createTargetInput(targetUrl, "fr");
|
|
280
|
+
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
|
281
|
+
|
|
282
|
+
//Start translation
|
|
283
|
+
const batchRequests = {inputs: [batchRequest]};
|
|
284
|
+
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
|
285
|
+
|
|
286
|
+
const operationLocationUrl = translationResponse.headers["operation-location"]
|
|
287
|
+
const operationId = getTranslationOperationID(operationLocationUrl);
|
|
288
|
+
|
|
289
|
+
//get Translation Status
|
|
290
|
+
const response = await client.path("/document/batches/{id}",operationId).get() as GetTranslationStatus200Response;
|
|
291
|
+
if (isUnexpected(response)) {
|
|
292
|
+
throw response.body;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
console.log("Translation ID = " + response.body.id);
|
|
296
|
+
console.log("Translation Status = " + response.body.status);
|
|
297
|
+
console.log("Translation createdDateTimeUtc = " + response.body.createdDateTimeUtc);
|
|
298
|
+
console.log("Translation lastActionDateTimeUtc = " + response.body.lastActionDateTimeUtc);
|
|
299
|
+
console.log("Total documents submitted for translation = " + response.body.summary.total);
|
|
300
|
+
console.log("Total characters charged = " + response.body.summary.totalCharacterCharged);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
### Get Supported Formats
|
|
305
|
+
|
|
306
|
+
This returns a list of document or glossary formats supported by the Document Translation feature. The list includes common file extensions and content-type if using the upload API.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
console.log("== List Supported Format Types ==");
|
|
310
|
+
|
|
311
|
+
const documentTranslationClient = DocumentTranslationClient(endpoint);
|
|
312
|
+
const response = await documentTranslationClient.path("/document/formats").get();
|
|
313
|
+
|
|
314
|
+
const fileFormatTypes = response.body;
|
|
315
|
+
fileFormatTypes.value.forEach((fileFormatType: { format: any; contentTypes: any; fileExtensions: any; }) => {
|
|
316
|
+
console.log(fileFormatType.format);
|
|
317
|
+
console.log(fileFormatType.contentTypes);
|
|
318
|
+
console.log(fileFormatType.fileExtensions);
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Troubleshooting
|
|
323
|
+
|
|
324
|
+
When you interact with the Translator Service using the DocumentTranslator client library, errors returned by the Translator service correspond to the same HTTP status codes returned for REST API requests.
|
|
325
|
+
|
|
326
|
+
For example, if you submit a translation request without a target translate language, a `400` error is returned, indicating "Bad Request".
|
|
327
|
+
|
|
328
|
+
You can find the different error codes returned by the service in the [Service Documentation][service_errors].
|
|
329
|
+
|
|
330
|
+
### Logging
|
|
331
|
+
|
|
332
|
+
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
const { setLogLevel } = require("@azure/logger");
|
|
336
|
+
|
|
337
|
+
setLogLevel("info");
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
|
|
341
|
+
Please refer to the service documentation for a conceptual discussion of [languages][languages_doc].
|
|
342
|
+
|
|
343
|
+
[service_errors]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#common-http-status-codes
|
|
344
|
+
[translator_resource_create]: https://learn.microsoft.com/azure/cognitive-services/Translator/create-translator-resource
|
|
345
|
+
[documentTranslationClient_class]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/src/documentTranslationClient.ts
|
|
346
|
+
[pre_requisities]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#prerequisites
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var coreClient = require('@azure-rest/core-client');
|
|
6
|
+
var logger$1 = require('@azure/logger');
|
|
7
|
+
var corePaging = require('@azure/core-paging');
|
|
8
|
+
var coreLro = require('@azure/core-lro');
|
|
9
|
+
var coreRestPipeline = require('@azure/core-rest-pipeline');
|
|
10
|
+
|
|
11
|
+
// Copyright (c) Microsoft Corporation.
|
|
12
|
+
// Licensed under the MIT license.
|
|
13
|
+
const logger = logger$1.createClientLogger("ai-translation-document");
|
|
14
|
+
|
|
15
|
+
// Copyright (c) Microsoft Corporation.
|
|
16
|
+
// Licensed under the MIT license.
|
|
17
|
+
/**
|
|
18
|
+
* Initialize a new instance of `DocumentTranslationClient`
|
|
19
|
+
* @param endpointParam - Supported document Translation endpoint, protocol and hostname, for example: https://{TranslatorResourceName}.cognitiveservices.azure.com/translator.
|
|
20
|
+
* @param credentials - uniquely identify client credential
|
|
21
|
+
* @param options - the parameter for all optional parameters
|
|
22
|
+
*/
|
|
23
|
+
function createClient(endpointParam, credentials, options = {}) {
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
25
|
+
const endpointUrl = (_b = (_a = options.endpoint) !== null && _a !== void 0 ? _a : options.baseUrl) !== null && _b !== void 0 ? _b : `${endpointParam}/translator`;
|
|
26
|
+
options.apiVersion = (_c = options.apiVersion) !== null && _c !== void 0 ? _c : "2024-05-01";
|
|
27
|
+
const userAgentInfo = `azsdk-js-ai-translation-document-rest/1.0.0-beta.1`;
|
|
28
|
+
const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix
|
|
29
|
+
? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}`
|
|
30
|
+
: `${userAgentInfo}`;
|
|
31
|
+
options = Object.assign(Object.assign({}, options), { userAgentOptions: {
|
|
32
|
+
userAgentPrefix,
|
|
33
|
+
}, loggingOptions: {
|
|
34
|
+
logger: (_e = (_d = options.loggingOptions) === null || _d === void 0 ? void 0 : _d.logger) !== null && _e !== void 0 ? _e : logger.info,
|
|
35
|
+
}, credentials: {
|
|
36
|
+
scopes: (_g = (_f = options.credentials) === null || _f === void 0 ? void 0 : _f.scopes) !== null && _g !== void 0 ? _g : ["https://cognitiveservices.azure.com/.default"],
|
|
37
|
+
apiKeyHeaderName: (_j = (_h = options.credentials) === null || _h === void 0 ? void 0 : _h.apiKeyHeaderName) !== null && _j !== void 0 ? _j : "Ocp-Apim-Subscription-Key",
|
|
38
|
+
} });
|
|
39
|
+
const client = coreClient.getClient(endpointUrl, credentials, options);
|
|
40
|
+
return client;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Copyright (c) Microsoft Corporation.
|
|
44
|
+
// Licensed under the MIT license.
|
|
45
|
+
const responseMap = {
|
|
46
|
+
"POST /document:translate": ["200"],
|
|
47
|
+
"GET /document/batches": ["200"],
|
|
48
|
+
"POST /document/batches": ["202"],
|
|
49
|
+
"GET /document/batches/{id}/documents/{documentId}": ["200"],
|
|
50
|
+
"GET /document/batches/{id}": ["200"],
|
|
51
|
+
"DELETE /document/batches/{id}": ["200"],
|
|
52
|
+
"GET /document/batches/{id}/documents": ["200"],
|
|
53
|
+
"GET /document/formats": ["200"],
|
|
54
|
+
};
|
|
55
|
+
function isUnexpected(response) {
|
|
56
|
+
const lroOriginal = response.headers["x-ms-original-url"];
|
|
57
|
+
const url = new URL(lroOriginal !== null && lroOriginal !== void 0 ? lroOriginal : response.request.url);
|
|
58
|
+
const method = response.request.method;
|
|
59
|
+
let pathDetails = responseMap[`${method} ${url.pathname}`];
|
|
60
|
+
if (!pathDetails) {
|
|
61
|
+
pathDetails = getParametrizedPathSuccess(method, url.pathname);
|
|
62
|
+
}
|
|
63
|
+
return !pathDetails.includes(response.status);
|
|
64
|
+
}
|
|
65
|
+
function getParametrizedPathSuccess(method, path) {
|
|
66
|
+
var _a, _b, _c, _d;
|
|
67
|
+
const pathParts = path.split("/");
|
|
68
|
+
// Traverse list to match the longest candidate
|
|
69
|
+
// matchedLen: the length of candidate path
|
|
70
|
+
// matchedValue: the matched status code array
|
|
71
|
+
let matchedLen = -1, matchedValue = [];
|
|
72
|
+
// Iterate the responseMap to find a match
|
|
73
|
+
for (const [key, value] of Object.entries(responseMap)) {
|
|
74
|
+
// Extracting the path from the map key which is in format
|
|
75
|
+
// GET /path/foo
|
|
76
|
+
if (!key.startsWith(method)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const candidatePath = getPathFromMapKey(key);
|
|
80
|
+
// Get each part of the url path
|
|
81
|
+
const candidateParts = candidatePath.split("/");
|
|
82
|
+
// track if we have found a match to return the values found.
|
|
83
|
+
let found = true;
|
|
84
|
+
for (let i = candidateParts.length - 1, j = pathParts.length - 1; i >= 1 && j >= 1; i--, j--) {
|
|
85
|
+
if (((_a = candidateParts[i]) === null || _a === void 0 ? void 0 : _a.startsWith("{")) && ((_b = candidateParts[i]) === null || _b === void 0 ? void 0 : _b.indexOf("}")) !== -1) {
|
|
86
|
+
const start = candidateParts[i].indexOf("}") + 1, end = (_c = candidateParts[i]) === null || _c === void 0 ? void 0 : _c.length;
|
|
87
|
+
// If the current part of the candidate is a "template" part
|
|
88
|
+
// Try to use the suffix of pattern to match the path
|
|
89
|
+
// {guid} ==> $
|
|
90
|
+
// {guid}:export ==> :export$
|
|
91
|
+
const isMatched = new RegExp(`${(_d = candidateParts[i]) === null || _d === void 0 ? void 0 : _d.slice(start, end)}`).test(pathParts[j] || "");
|
|
92
|
+
if (!isMatched) {
|
|
93
|
+
found = false;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// If the candidate part is not a template and
|
|
99
|
+
// the parts don't match mark the candidate as not found
|
|
100
|
+
// to move on with the next candidate path.
|
|
101
|
+
if (candidateParts[i] !== pathParts[j]) {
|
|
102
|
+
found = false;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// We finished evaluating the current candidate parts
|
|
107
|
+
// Update the matched value if and only if we found the longer pattern
|
|
108
|
+
if (found && candidatePath.length > matchedLen) {
|
|
109
|
+
matchedLen = candidatePath.length;
|
|
110
|
+
matchedValue = value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return matchedValue;
|
|
114
|
+
}
|
|
115
|
+
function getPathFromMapKey(mapKey) {
|
|
116
|
+
const pathStart = mapKey.indexOf("/");
|
|
117
|
+
return mapKey.slice(pathStart);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Copyright (c) Microsoft Corporation.
|
|
121
|
+
// Licensed under the MIT license.
|
|
122
|
+
/**
|
|
123
|
+
* Helper to paginate results from an initial response that follows the specification of Autorest `x-ms-pageable` extension
|
|
124
|
+
* @param client - Client to use for sending the next page requests
|
|
125
|
+
* @param initialResponse - Initial response containing the nextLink and current page of elements
|
|
126
|
+
* @param customGetPage - Optional - Function to define how to extract the page and next link to be used to paginate the results
|
|
127
|
+
* @returns - PagedAsyncIterableIterator to iterate the elements
|
|
128
|
+
*/
|
|
129
|
+
function paginate(client, initialResponse, options = {}) {
|
|
130
|
+
let firstRun = true;
|
|
131
|
+
const itemName = "value";
|
|
132
|
+
const nextLinkName = "nextLink";
|
|
133
|
+
const { customGetPage } = options;
|
|
134
|
+
const pagedResult = {
|
|
135
|
+
firstPageLink: "",
|
|
136
|
+
getPage: typeof customGetPage === "function"
|
|
137
|
+
? customGetPage
|
|
138
|
+
: async (pageLink) => {
|
|
139
|
+
const result = firstRun ? initialResponse : await client.pathUnchecked(pageLink).get();
|
|
140
|
+
firstRun = false;
|
|
141
|
+
checkPagingRequest(result);
|
|
142
|
+
const nextLink = getNextLink(result.body, nextLinkName);
|
|
143
|
+
const values = getElements(result.body, itemName);
|
|
144
|
+
return {
|
|
145
|
+
page: values,
|
|
146
|
+
nextPageLink: nextLink,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
return corePaging.getPagedAsyncIterator(pagedResult);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets for the value of nextLink in the body
|
|
154
|
+
*/
|
|
155
|
+
function getNextLink(body, nextLinkName) {
|
|
156
|
+
if (!nextLinkName) {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
const nextLink = body[nextLinkName];
|
|
160
|
+
if (typeof nextLink !== "string" && typeof nextLink !== "undefined") {
|
|
161
|
+
throw new Error(`Body Property ${nextLinkName} should be a string or undefined`);
|
|
162
|
+
}
|
|
163
|
+
return nextLink;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Gets the elements of the current request in the body.
|
|
167
|
+
*/
|
|
168
|
+
function getElements(body, itemName) {
|
|
169
|
+
const value = body[itemName];
|
|
170
|
+
// value has to be an array according to the x-ms-pageable extension.
|
|
171
|
+
// The fact that this must be an array is used above to calculate the
|
|
172
|
+
// type of elements in the page in PaginateReturn
|
|
173
|
+
if (!Array.isArray(value)) {
|
|
174
|
+
throw new Error(`Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`);
|
|
175
|
+
}
|
|
176
|
+
return value !== null && value !== void 0 ? value : [];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Checks if a request failed
|
|
180
|
+
*/
|
|
181
|
+
function checkPagingRequest(response) {
|
|
182
|
+
const Http2xxStatusCodes = ["200", "201", "202", "203", "204", "205", "206", "207", "208", "226"];
|
|
183
|
+
if (!Http2xxStatusCodes.includes(response.status)) {
|
|
184
|
+
throw coreClient.createRestError(`Pagination failed with unexpected statusCode ${response.status}`, response);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Copyright (c) Microsoft Corporation.
|
|
189
|
+
// Licensed under the MIT license.
|
|
190
|
+
async function getLongRunningPoller(client, initialResponse, options = {}) {
|
|
191
|
+
var _a;
|
|
192
|
+
const abortController = new AbortController();
|
|
193
|
+
const poller = {
|
|
194
|
+
sendInitialRequest: async () => {
|
|
195
|
+
// In the case of Rest Clients we are building the LRO poller object from a response that's the reason
|
|
196
|
+
// we are not triggering the initial request here, just extracting the information from the
|
|
197
|
+
// response we were provided.
|
|
198
|
+
return getLroResponse(initialResponse);
|
|
199
|
+
},
|
|
200
|
+
sendPollRequest: async (path, sendPollRequestOptions) => {
|
|
201
|
+
// This is the callback that is going to be called to poll the service
|
|
202
|
+
// to get the latest status. We use the client provided and the polling path
|
|
203
|
+
// which is an opaque URL provided by caller, the service sends this in one of the following headers: operation-location, azure-asyncoperation or location
|
|
204
|
+
// depending on the lro pattern that the service implements. If non is provided we default to the initial path.
|
|
205
|
+
function abortListener() {
|
|
206
|
+
abortController.abort();
|
|
207
|
+
}
|
|
208
|
+
const inputAbortSignal = sendPollRequestOptions === null || sendPollRequestOptions === void 0 ? void 0 : sendPollRequestOptions.abortSignal;
|
|
209
|
+
const abortSignal = abortController.signal;
|
|
210
|
+
if (inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.aborted) {
|
|
211
|
+
abortController.abort();
|
|
212
|
+
}
|
|
213
|
+
else if (!abortSignal.aborted) {
|
|
214
|
+
inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.addEventListener("abort", abortListener, {
|
|
215
|
+
once: true,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
let response;
|
|
219
|
+
try {
|
|
220
|
+
response = await client
|
|
221
|
+
.pathUnchecked(path !== null && path !== void 0 ? path : initialResponse.request.url)
|
|
222
|
+
.get({ abortSignal });
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.removeEventListener("abort", abortListener);
|
|
226
|
+
}
|
|
227
|
+
const lroResponse = getLroResponse(response);
|
|
228
|
+
lroResponse.rawResponse.headers["x-ms-original-url"] = initialResponse.request.url;
|
|
229
|
+
return lroResponse;
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
options.resolveOnUnsuccessful = (_a = options.resolveOnUnsuccessful) !== null && _a !== void 0 ? _a : true;
|
|
233
|
+
const httpPoller = coreLro.createHttpPoller(poller, options);
|
|
234
|
+
const simplePoller = {
|
|
235
|
+
isDone() {
|
|
236
|
+
return httpPoller.isDone;
|
|
237
|
+
},
|
|
238
|
+
isStopped() {
|
|
239
|
+
return httpPoller.isStopped;
|
|
240
|
+
},
|
|
241
|
+
getOperationState() {
|
|
242
|
+
if (!httpPoller.operationState) {
|
|
243
|
+
throw new Error("Operation state is not available. The poller may not have been started and you could await submitted() before calling getOperationState().");
|
|
244
|
+
}
|
|
245
|
+
return httpPoller.operationState;
|
|
246
|
+
},
|
|
247
|
+
getResult() {
|
|
248
|
+
return httpPoller.result;
|
|
249
|
+
},
|
|
250
|
+
toString() {
|
|
251
|
+
if (!httpPoller.operationState) {
|
|
252
|
+
throw new Error("Operation state is not available. The poller may not have been started and you could await submitted() before calling getOperationState().");
|
|
253
|
+
}
|
|
254
|
+
return JSON.stringify({
|
|
255
|
+
state: httpPoller.operationState,
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
stopPolling() {
|
|
259
|
+
abortController.abort();
|
|
260
|
+
},
|
|
261
|
+
onProgress: httpPoller.onProgress,
|
|
262
|
+
poll: httpPoller.poll,
|
|
263
|
+
pollUntilDone: httpPoller.pollUntilDone,
|
|
264
|
+
serialize: httpPoller.serialize,
|
|
265
|
+
submitted: httpPoller.submitted,
|
|
266
|
+
};
|
|
267
|
+
return simplePoller;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Converts a Rest Client response to a response that the LRO implementation understands
|
|
271
|
+
* @param response - a rest client http response
|
|
272
|
+
* @returns - An LRO response that the LRO implementation understands
|
|
273
|
+
*/
|
|
274
|
+
function getLroResponse(response) {
|
|
275
|
+
if (Number.isNaN(response.status)) {
|
|
276
|
+
throw new TypeError(`Status code of the response is not a number. Value: ${response.status}`);
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
flatResponse: response,
|
|
280
|
+
rawResponse: Object.assign(Object.assign({}, response), { statusCode: Number.parseInt(response.status), body: response.body }),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Copyright (c) Microsoft Corporation.
|
|
285
|
+
// Licensed under the MIT license.
|
|
286
|
+
|
|
287
|
+
Object.defineProperty(exports, "createFile", {
|
|
288
|
+
enumerable: true,
|
|
289
|
+
get: function () { return coreRestPipeline.createFile; }
|
|
290
|
+
});
|
|
291
|
+
Object.defineProperty(exports, "createFileFromStream", {
|
|
292
|
+
enumerable: true,
|
|
293
|
+
get: function () { return coreRestPipeline.createFileFromStream; }
|
|
294
|
+
});
|
|
295
|
+
exports.default = createClient;
|
|
296
|
+
exports.getLongRunningPoller = getLongRunningPoller;
|
|
297
|
+
exports.isUnexpected = isUnexpected;
|
|
298
|
+
exports.paginate = paginate;
|
|
299
|
+
//# sourceMappingURL=index.js.map
|