@diplodoc/cli 4.13.7 → 4.13.9-alpha-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/assets/app.css +1 -1
- package/assets/app.js +1 -1
- package/assets/app.rtl.css +2 -0
- package/assets/print.css +809 -0
- package/assets/print.js +2 -0
- package/assets/react.js +1 -1
- package/assets/vendor.css +136 -292
- package/assets/vendor.js +1 -1
- package/assets/vendor.rtl.css +2653 -0
- package/build/index.js +92793 -3698
- package/build/index.js.map +4 -4
- package/build/linter.js +16186 -73
- package/build/linter.js.map +4 -4
- package/package.json +4 -4
- package/src/cmd/translate/compose.ts +0 -1
- package/src/cmd/translate/extract.ts +0 -1
- package/src/cmd/translate/handler.ts +181 -113
- package/src/cmd/translate/utils/errors.ts +97 -0
- package/src/cmd/translate/utils/index.ts +4 -7
- package/src/cmd/translate/utils/translate.ts +1 -18
- package/src/cmd/translate/yandex/auth.ts +22 -31
- package/src/utils/logger.ts +2 -2
- package/src/packages/credentials/index.ts +0 -1
- package/src/packages/credentials/yandex-oauth.ts +0 -42
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Yandex Data UI Team <data-ui@yandex-team.ru>",
|
|
4
4
|
"description": "Make documentation using yfm-docs in Markdown and HTML formats",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "4.13.
|
|
6
|
+
"version": "4.13.9-alpha-1",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git@github.com:diplodoc-platform/cli.git"
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@aws-sdk/client-s3": "^3.369.0",
|
|
34
|
-
"@diplodoc/client": "^2.
|
|
34
|
+
"@diplodoc/client": "^2.1.1",
|
|
35
35
|
"@diplodoc/latex-extension": "^1.1.0",
|
|
36
36
|
"@diplodoc/mermaid-extension": "^1.2.1",
|
|
37
37
|
"@diplodoc/openapi-extension": "^1.4.13",
|
|
38
38
|
"@diplodoc/transform": "^4.8.2",
|
|
39
|
-
"@diplodoc/translation": "^1.0.
|
|
39
|
+
"@diplodoc/translation": "^1.0.7",
|
|
40
40
|
"@octokit/core": "4.2.4",
|
|
41
|
-
"@yandex-cloud/nodejs-sdk": "^2.2.2",
|
|
42
41
|
"ajv": "^8.11.0",
|
|
43
42
|
"async": "^3.2.4",
|
|
43
|
+
"axios": "^1.6.7",
|
|
44
44
|
"chalk": "4.1.2",
|
|
45
45
|
"glob": "^8.0.3",
|
|
46
46
|
"highlight.js": "^11.7.0",
|
|
@@ -1,26 +1,25 @@
|
|
|
1
|
+
import axios, {AxiosError, AxiosResponse} from 'axios';
|
|
2
|
+
import {green, red} from 'chalk';
|
|
1
3
|
import {Arguments} from 'yargs';
|
|
2
4
|
import {ArgvService} from '../../services';
|
|
3
5
|
import {logger} from '../../utils';
|
|
4
6
|
import {ok} from 'assert';
|
|
5
|
-
import {dirname, extname, resolve} from 'path';
|
|
7
|
+
import {dirname, extname, join, resolve} from 'path';
|
|
6
8
|
import {mkdir} from 'fs/promises';
|
|
7
|
-
import {
|
|
8
|
-
import {asyncify, eachLimit
|
|
9
|
-
import {Session} from '@yandex-cloud/nodejs-sdk/dist/session';
|
|
10
|
-
import {TranslationServiceClient} from '@yandex-cloud/nodejs-sdk/dist/generated/yandex/cloud/service_clients';
|
|
11
|
-
import {
|
|
12
|
-
TranslateRequest_Format as Format,
|
|
13
|
-
TranslateRequest,
|
|
14
|
-
} from '@yandex-cloud/nodejs-sdk/dist/generated/yandex/cloud/ai/translate/v2/translation_service';
|
|
9
|
+
import {getYandexAuth} from './yandex/auth';
|
|
10
|
+
import {asyncify, eachLimit} from 'async';
|
|
15
11
|
|
|
16
12
|
import {
|
|
13
|
+
AuthError,
|
|
17
14
|
Defer,
|
|
15
|
+
LimitExceed,
|
|
16
|
+
RequestError,
|
|
17
|
+
TranslateError,
|
|
18
18
|
TranslateParams,
|
|
19
19
|
bytes,
|
|
20
20
|
compose,
|
|
21
21
|
dumpFile,
|
|
22
22
|
extract,
|
|
23
|
-
flat,
|
|
24
23
|
loadFile,
|
|
25
24
|
normalizeParams,
|
|
26
25
|
} from './utils';
|
|
@@ -29,24 +28,39 @@ const REQUESTS_LIMIT = 20;
|
|
|
29
28
|
const BYTES_LIMIT = 10000;
|
|
30
29
|
const RETRY_LIMIT = 3;
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
type TranslatorParams = {
|
|
32
|
+
input: string;
|
|
33
|
+
output: string;
|
|
34
|
+
sourceLanguage: string;
|
|
35
|
+
targetLanguage: string;
|
|
36
|
+
// yandexCloudTranslateGlossaryPairs: YandexCloudTranslateGlossaryPair[];
|
|
37
|
+
};
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
type RequesterParams = {
|
|
40
|
+
auth: string;
|
|
41
|
+
folderId: string | undefined;
|
|
42
|
+
sourceLanguage: string;
|
|
43
|
+
targetLanguage: string;
|
|
44
|
+
dryRun: boolean;
|
|
45
|
+
};
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
type Request = {
|
|
48
|
+
(texts: string[]): () => Promise<void>;
|
|
49
|
+
stat: {
|
|
50
|
+
bytes: number;
|
|
51
|
+
chunks: number;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
code: string;
|
|
55
|
+
type Split = (path: string, texts: string[]) => Promise<string[]>;
|
|
44
56
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
type Cache = Map<string, Defer>;
|
|
58
|
+
|
|
59
|
+
type Translations = {
|
|
60
|
+
translations: {
|
|
61
|
+
text: string;
|
|
62
|
+
}[];
|
|
63
|
+
};
|
|
50
64
|
|
|
51
65
|
export async function handler(args: Arguments<any>) {
|
|
52
66
|
const params = normalizeParams({
|
|
@@ -91,95 +105,130 @@ export async function handler(args: Arguments<any>) {
|
|
|
91
105
|
try {
|
|
92
106
|
await translate(file);
|
|
93
107
|
} catch (error: any) {
|
|
94
|
-
|
|
108
|
+
if (error instanceof TranslateError) {
|
|
109
|
+
logger.error(file, `${error.message}`, error.code);
|
|
110
|
+
|
|
111
|
+
if (error.fatal) {
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
logger.error(file, error.message);
|
|
116
|
+
}
|
|
95
117
|
}
|
|
96
118
|
}),
|
|
97
119
|
);
|
|
98
120
|
|
|
99
|
-
console.log(
|
|
121
|
+
console.log(
|
|
122
|
+
green('PROCESSED'),
|
|
123
|
+
`bytes: ${request.stat.bytes} chunks: ${request.stat.chunks}`,
|
|
124
|
+
);
|
|
100
125
|
}
|
|
101
126
|
} catch (error: any) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
if (error instanceof TranslateError) {
|
|
128
|
+
console.error(red(error.code), error.message);
|
|
129
|
+
} else {
|
|
130
|
+
console.error(error);
|
|
131
|
+
}
|
|
105
132
|
|
|
106
|
-
|
|
133
|
+
process.exit(1);
|
|
107
134
|
}
|
|
108
135
|
}
|
|
109
136
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
output: string;
|
|
113
|
-
sourceLanguage: string;
|
|
114
|
-
targetLanguage: string;
|
|
115
|
-
// yandexCloudTranslateGlossaryPairs: YandexCloudTranslateGlossaryPair[];
|
|
116
|
-
};
|
|
137
|
+
function scheduler(limit: number, interval: number) {
|
|
138
|
+
const scheduled: Defer<void>[] = [];
|
|
117
139
|
|
|
118
|
-
|
|
119
|
-
auth: AuthInfo;
|
|
120
|
-
folderId: string | undefined;
|
|
121
|
-
sourceLanguage: string;
|
|
122
|
-
targetLanguage: string;
|
|
123
|
-
dryRun: boolean;
|
|
124
|
-
};
|
|
140
|
+
let processing = 0;
|
|
125
141
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
stat: {
|
|
129
|
-
bytes: number;
|
|
130
|
-
chunks: number;
|
|
131
|
-
};
|
|
132
|
-
};
|
|
142
|
+
function idle() {
|
|
143
|
+
const defer = new Defer<void>();
|
|
133
144
|
|
|
134
|
-
|
|
145
|
+
scheduled.push(defer);
|
|
135
146
|
|
|
136
|
-
|
|
147
|
+
return defer.promise;
|
|
148
|
+
}
|
|
137
149
|
|
|
138
|
-
function
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
async function queue() {
|
|
151
|
+
processing++;
|
|
152
|
+
await wait(interval);
|
|
153
|
+
processing--;
|
|
154
|
+
unqueue();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function unqueue() {
|
|
158
|
+
scheduled.shift()?.resolve();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return async function <R>(action: Function): Promise<R> {
|
|
162
|
+
if (processing >= limit) {
|
|
163
|
+
await idle();
|
|
146
164
|
}
|
|
147
|
-
|
|
165
|
+
|
|
166
|
+
queue();
|
|
167
|
+
|
|
168
|
+
return action();
|
|
148
169
|
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function requester(params: RequesterParams, cache: Cache) {
|
|
173
|
+
const {auth, folderId, sourceLanguage, targetLanguage, dryRun} = params;
|
|
174
|
+
const schedule = scheduler(REQUESTS_LIMIT, 1000);
|
|
149
175
|
|
|
150
176
|
const request = function request(texts: string[]) {
|
|
177
|
+
const resolve = (text: string, index: number) => {
|
|
178
|
+
const defer = cache.get(texts[index]);
|
|
179
|
+
if (defer) {
|
|
180
|
+
defer.resolve(text);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
151
184
|
request.stat.bytes += bytes(texts);
|
|
152
185
|
request.stat.chunks++;
|
|
153
186
|
|
|
154
187
|
return async function () {
|
|
155
188
|
if (dryRun) {
|
|
156
|
-
|
|
189
|
+
texts.forEach(resolve);
|
|
157
190
|
}
|
|
158
191
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
192
|
+
try {
|
|
193
|
+
const {data} = await schedule<AxiosResponse<Translations>>(() =>
|
|
194
|
+
axios({
|
|
195
|
+
method: 'POST',
|
|
196
|
+
url: 'https://translate.api.cloud.yandex.net/translate/v2/translate',
|
|
197
|
+
timeout: 5000,
|
|
198
|
+
maxRedirects: 0,
|
|
199
|
+
headers: {
|
|
200
|
+
Authorization: auth,
|
|
201
|
+
'Content-Type': 'application/json',
|
|
202
|
+
'User-Agent': 'github.com/diplodoc-platform/cli',
|
|
203
|
+
},
|
|
204
|
+
data: {
|
|
205
|
+
folderId,
|
|
206
|
+
texts,
|
|
207
|
+
sourceLanguageCode: sourceLanguage,
|
|
208
|
+
targetLanguageCode: targetLanguage,
|
|
209
|
+
format: 'HTML',
|
|
210
|
+
},
|
|
172
211
|
}),
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
return data.translations.map(({text}) => text).forEach(resolve);
|
|
215
|
+
} catch (error: any) {
|
|
216
|
+
if (error instanceof AxiosError) {
|
|
217
|
+
const {response} = error;
|
|
218
|
+
const {status, statusText, data} = response as AxiosResponse;
|
|
219
|
+
|
|
220
|
+
switch (true) {
|
|
221
|
+
case LimitExceed.is(data.message):
|
|
222
|
+
throw new LimitExceed(data.message);
|
|
223
|
+
case AuthError.is(data.message):
|
|
224
|
+
throw new AuthError(data.message);
|
|
225
|
+
default:
|
|
226
|
+
throw new RequestError(status, statusText, data);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
throw new RequestError(0, error.message, {fatal: true});
|
|
231
|
+
}
|
|
183
232
|
};
|
|
184
233
|
};
|
|
185
234
|
|
|
@@ -193,6 +242,8 @@ function requester(params: RequesterParams, cache: Cache) {
|
|
|
193
242
|
|
|
194
243
|
function translator(params: TranslatorParams, split: Split) {
|
|
195
244
|
const {input, output, sourceLanguage, targetLanguage} = params;
|
|
245
|
+
const inputRoot = resolve(input);
|
|
246
|
+
const outputRoot = resolve(output);
|
|
196
247
|
|
|
197
248
|
return async (path: string) => {
|
|
198
249
|
const ext = extname(path);
|
|
@@ -200,8 +251,8 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
200
251
|
return;
|
|
201
252
|
}
|
|
202
253
|
|
|
203
|
-
const inputPath =
|
|
204
|
-
const outputPath =
|
|
254
|
+
const inputPath = join(inputRoot, path);
|
|
255
|
+
const outputPath = join(outputRoot, path.replace(sourceLanguage, targetLanguage));
|
|
205
256
|
const content = await loadFile(inputPath);
|
|
206
257
|
|
|
207
258
|
await mkdir(dirname(outputPath), {recursive: true});
|
|
@@ -227,7 +278,7 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
227
278
|
return;
|
|
228
279
|
}
|
|
229
280
|
|
|
230
|
-
const parts =
|
|
281
|
+
const parts = await split(path, units);
|
|
231
282
|
const composed = compose(skeleton, parts, {useSource: true});
|
|
232
283
|
|
|
233
284
|
await dumpFile(outputPath, composed);
|
|
@@ -235,50 +286,67 @@ function translator(params: TranslatorParams, split: Split) {
|
|
|
235
286
|
}
|
|
236
287
|
|
|
237
288
|
function splitter(request: Request, cache: Cache): Split {
|
|
238
|
-
return function (path: string, texts: string[]) {
|
|
239
|
-
const promises: Promise<string
|
|
289
|
+
return async function (path: string, texts: string[]) {
|
|
290
|
+
const promises: Promise<string>[] = [];
|
|
291
|
+
const requests: Promise<void>[] = [];
|
|
240
292
|
let buffer: string[] = [];
|
|
241
293
|
let bufferSize = 0;
|
|
242
294
|
|
|
243
295
|
const release = () => {
|
|
244
|
-
|
|
296
|
+
requests.push(backoff(request(buffer)));
|
|
245
297
|
buffer = [];
|
|
246
298
|
bufferSize = 0;
|
|
247
299
|
};
|
|
248
300
|
|
|
249
301
|
for (const text of texts) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (defer) {
|
|
253
|
-
promises.push(defer.promise);
|
|
254
|
-
} else if (text.length >= BYTES_LIMIT) {
|
|
302
|
+
if (text.length >= BYTES_LIMIT) {
|
|
255
303
|
logger.warn(path, 'Skip document part for translation. Part is too big.');
|
|
256
|
-
promises.push(Promise.resolve(
|
|
304
|
+
promises.push(Promise.resolve(text));
|
|
257
305
|
} else {
|
|
258
|
-
|
|
259
|
-
|
|
306
|
+
const defer = cache.get(text) || new Defer();
|
|
307
|
+
promises.push(defer.promise);
|
|
308
|
+
|
|
309
|
+
if (!cache.get(text)) {
|
|
310
|
+
if (bufferSize + text.length > BYTES_LIMIT) {
|
|
311
|
+
release();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
buffer.push(text);
|
|
315
|
+
bufferSize += text.length;
|
|
260
316
|
}
|
|
261
317
|
|
|
262
|
-
|
|
263
|
-
bufferSize += text.length;
|
|
264
|
-
cache.set(text, new Defer());
|
|
318
|
+
cache.set(text, defer);
|
|
265
319
|
}
|
|
266
320
|
}
|
|
267
321
|
|
|
268
322
|
if (bufferSize) {
|
|
269
|
-
|
|
323
|
+
release();
|
|
270
324
|
}
|
|
271
325
|
|
|
272
|
-
|
|
326
|
+
await Promise.all(requests);
|
|
327
|
+
|
|
328
|
+
return Promise.all(promises);
|
|
273
329
|
};
|
|
274
330
|
}
|
|
275
331
|
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
332
|
+
function wait(interval: number) {
|
|
333
|
+
const defer = new Defer<void>();
|
|
334
|
+
setTimeout(() => defer.resolve(), interval);
|
|
335
|
+
return defer.promise;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function backoff(action: () => Promise<void>): Promise<void> {
|
|
339
|
+
let retry = 0;
|
|
340
|
+
|
|
341
|
+
while (++retry < RETRY_LIMIT) {
|
|
342
|
+
try {
|
|
343
|
+
await action();
|
|
344
|
+
} catch (error: any) {
|
|
345
|
+
if (RequestError.canRetry(error)) {
|
|
346
|
+
await wait(Math.pow(2, retry) * 1000);
|
|
347
|
+
} else {
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
284
352
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export class TranslateError extends Error {
|
|
2
|
+
code: string;
|
|
3
|
+
|
|
4
|
+
fatal: boolean;
|
|
5
|
+
|
|
6
|
+
constructor(message: string, code: string, fatal = false) {
|
|
7
|
+
super(message);
|
|
8
|
+
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.fatal = fatal;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class RequestError extends TranslateError {
|
|
15
|
+
static canRetry(error: any) {
|
|
16
|
+
if (error instanceof RequestError) {
|
|
17
|
+
switch (true) {
|
|
18
|
+
case error.status === 429:
|
|
19
|
+
return true;
|
|
20
|
+
case error.status === 500:
|
|
21
|
+
return true;
|
|
22
|
+
case error.status === 503:
|
|
23
|
+
return true;
|
|
24
|
+
case error.status === 504:
|
|
25
|
+
return true;
|
|
26
|
+
default:
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
status: number;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
status: number,
|
|
38
|
+
statusText: string,
|
|
39
|
+
info: {code?: number; message?: string; fatal?: boolean} = {},
|
|
40
|
+
) {
|
|
41
|
+
super(`${statusText}\n${info.message || ''}`, 'REQUEST_ERROR', info.fatal);
|
|
42
|
+
|
|
43
|
+
this.status = status;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const INACTIVE_CLOUD = /^The cloud .*? is inactive/;
|
|
48
|
+
const WRONG_APIKEY = /^Unknown api key/;
|
|
49
|
+
const WRONG_TOKEN = /^The token is invalid/;
|
|
50
|
+
|
|
51
|
+
export class AuthError extends TranslateError {
|
|
52
|
+
static is(message: string) {
|
|
53
|
+
return Boolean(AuthError.reason(message));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static reason(message: string) {
|
|
57
|
+
switch (true) {
|
|
58
|
+
case INACTIVE_CLOUD.test(message):
|
|
59
|
+
return 'INACTIVE_CLOUD';
|
|
60
|
+
case WRONG_APIKEY.test(message):
|
|
61
|
+
return 'WRONG_APIKEY';
|
|
62
|
+
case WRONG_TOKEN.test(message):
|
|
63
|
+
return 'WRONG_TOKEN';
|
|
64
|
+
default:
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
constructor(message: string) {
|
|
70
|
+
super(message, AuthError.reason(message) || 'AUTH_ERROR', true);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const LIMIT_EXCEED_RX = /^limit on units was exceeded. (.*)$/;
|
|
75
|
+
|
|
76
|
+
export class LimitExceed extends TranslateError {
|
|
77
|
+
static is(message: string) {
|
|
78
|
+
return Boolean(LIMIT_EXCEED_RX.test(message));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
constructor(message: string) {
|
|
82
|
+
const [, desc] = LIMIT_EXCEED_RX.exec(message) || [];
|
|
83
|
+
super(desc, 'TRANSLATE_LIMIT_EXCEED', true);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export class ExtractError extends TranslateError {
|
|
88
|
+
constructor(error: Error) {
|
|
89
|
+
super('EXTRACT_ERROR', error?.message || String(error));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export class ComposeError extends TranslateError {
|
|
94
|
+
constructor(error: Error) {
|
|
95
|
+
super('COMPOSE_ERROR', error?.message || String(error));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -5,6 +5,7 @@ import glob from 'glob';
|
|
|
5
5
|
|
|
6
6
|
export {dumpFile, loadFile} from './fs';
|
|
7
7
|
export {extract, compose} from './translate';
|
|
8
|
+
export {TranslateError, LimitExceed, RequestError, AuthError} from './errors';
|
|
8
9
|
|
|
9
10
|
type TranslateArgs = {
|
|
10
11
|
input: string;
|
|
@@ -141,16 +142,12 @@ export function resolveSchemas(_path: string) {
|
|
|
141
142
|
return null;
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
export
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export class Defer {
|
|
149
|
-
resolve!: (text: string[]) => void;
|
|
145
|
+
export class Defer<T = string> {
|
|
146
|
+
resolve!: (text: T) => void;
|
|
150
147
|
|
|
151
148
|
reject!: (error: any) => void;
|
|
152
149
|
|
|
153
|
-
promise: Promise<
|
|
150
|
+
promise: Promise<T>;
|
|
154
151
|
|
|
155
152
|
constructor() {
|
|
156
153
|
this.promise = new Promise((resolve, reject) => {
|
|
@@ -1,23 +1,6 @@
|
|
|
1
1
|
import type {ComposeOptions, ExtractOptions} from '@diplodoc/translation';
|
|
2
2
|
import {compose as _compose, extract as _extract} from '@diplodoc/translation';
|
|
3
|
-
|
|
4
|
-
class ExtractError extends Error {
|
|
5
|
-
code: string;
|
|
6
|
-
|
|
7
|
-
constructor(error: Error) {
|
|
8
|
-
super(error?.message || String(error));
|
|
9
|
-
this.code = 'EXTRACT_ERROR';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class ComposeError extends Error {
|
|
14
|
-
code: string;
|
|
15
|
-
|
|
16
|
-
constructor(error: Error) {
|
|
17
|
-
super(error?.message || String(error));
|
|
18
|
-
this.code = 'COMPOSE_ERROR';
|
|
19
|
-
}
|
|
20
|
-
}
|
|
3
|
+
import {ComposeError, ExtractError} from './errors';
|
|
21
4
|
|
|
22
5
|
type Content = Parameters<typeof _extract>[0];
|
|
23
6
|
|
|
@@ -1,41 +1,32 @@
|
|
|
1
1
|
import {readFileSync} from 'fs';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
service_account_id: string;
|
|
6
|
-
public_key: string;
|
|
7
|
-
private_key: string;
|
|
8
|
-
};
|
|
3
|
+
const resolveKey = (data: string) => {
|
|
4
|
+
data = data.trim();
|
|
9
5
|
|
|
10
|
-
|
|
6
|
+
switch (true) {
|
|
7
|
+
case data.startsWith('y0_'):
|
|
8
|
+
return 'Bearer ' + data;
|
|
9
|
+
case data.startsWith('t1.'):
|
|
10
|
+
return 'Bearer ' + data;
|
|
11
|
+
case data.startsWith('AQVN'):
|
|
12
|
+
return 'Api-Key ' + data;
|
|
13
|
+
default:
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
11
17
|
|
|
12
18
|
export function getYandexAuth(path: string) {
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
oauthToken: path,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
19
|
+
let auth = resolveKey(path);
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (auth !== null) {
|
|
22
|
+
return auth;
|
|
23
|
+
}
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
serviceAccountJson: {
|
|
26
|
-
serviceAccountId: json.service_account_id,
|
|
27
|
-
accessKeyId: json.id,
|
|
28
|
-
privateKey: json.private_key,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
} catch {}
|
|
25
|
+
auth = resolveKey(readFileSync(path, 'utf8'));
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
27
|
+
if (auth === null) {
|
|
28
|
+
throw new Error('No Auth');
|
|
29
|
+
}
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
return 'private_key' in json;
|
|
31
|
+
return auth;
|
|
41
32
|
}
|
package/src/utils/logger.ts
CHANGED
|
@@ -32,8 +32,8 @@ export const logger = {
|
|
|
32
32
|
|
|
33
33
|
log.warn(`file: ${pathToFile} ${extraMessage}`);
|
|
34
34
|
},
|
|
35
|
-
error: function (pathToFile: string, extraMessage: string) {
|
|
36
|
-
const message = `${red('ERROR')} file: ${pathToFile} error: ${extraMessage}`;
|
|
35
|
+
error: function (pathToFile: string, extraMessage: string, reason?: string) {
|
|
36
|
+
const message = `${red(reason || 'ERROR')} file: ${pathToFile} error: ${extraMessage}`;
|
|
37
37
|
|
|
38
38
|
writeLog(message, true);
|
|
39
39
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './yandex-oauth';
|