@diplodoc/cli 4.13.7 → 4.13.8

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/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.7",
6
+ "version": "4.13.8",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git@github.com:diplodoc-platform/cli.git"
@@ -36,11 +36,11 @@
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.6",
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",
@@ -28,7 +28,6 @@ function builder<T>(argv: Argv<T>) {
28
28
  alias: 'o',
29
29
  describe: 'output folder where translated markdown will be stored',
30
30
  type: 'string',
31
- default: process.cwd(),
32
31
  })
33
32
  .option('use-source', {
34
33
  describe: 'for debug',
@@ -29,7 +29,6 @@ function builder<T>(argv: Argv<T>) {
29
29
  alias: 'o',
30
30
  describe: 'output folder where translated markdown will be stored',
31
31
  type: 'string',
32
- default: process.cwd(),
33
32
  })
34
33
  .option('source', {
35
34
  alias: ['sll', 'source-language-locale'],
@@ -1,17 +1,12 @@
1
+ import axios from 'axios';
1
2
  import {Arguments} from 'yargs';
2
3
  import {ArgvService} from '../../services';
3
4
  import {logger} from '../../utils';
4
5
  import {ok} from 'assert';
5
- import {dirname, extname, resolve} from 'path';
6
+ import {dirname, extname, join, resolve} from 'path';
6
7
  import {mkdir} from 'fs/promises';
7
- import {AuthInfo, getYandexAuth} from './yandex/auth';
8
+ import {getYandexAuth} from './yandex/auth';
8
9
  import {asyncify, eachLimit, retry} from 'async';
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';
15
10
 
16
11
  import {
17
12
  Defer,
@@ -20,7 +15,6 @@ import {
20
15
  compose,
21
16
  dumpFile,
22
17
  extract,
23
- flat,
24
18
  loadFile,
25
19
  normalizeParams,
26
20
  } from './utils';
@@ -116,7 +110,7 @@ type TranslatorParams = {
116
110
  };
117
111
 
118
112
  type RequesterParams = {
119
- auth: AuthInfo;
113
+ auth: string;
120
114
  folderId: string | undefined;
121
115
  sourceLanguage: string;
122
116
  targetLanguage: string;
@@ -131,18 +125,22 @@ type Request = {
131
125
  };
132
126
  };
133
127
 
134
- type Split = (path: string, texts: string[]) => Promise<string[]>[];
128
+ type Split = (path: string, texts: string[]) => Promise<string>[];
135
129
 
136
130
  type Cache = Map<string, Defer>;
137
131
 
132
+ type Translations = {
133
+ translations: {
134
+ text: string;
135
+ }[];
136
+ };
137
+
138
138
  function requester(params: RequesterParams, cache: Cache) {
139
139
  const {auth, folderId, sourceLanguage, targetLanguage, dryRun} = params;
140
- const session = new Session(auth);
141
- const client = session.client(TranslationServiceClient);
142
140
  const resolve = (text: string, index: number, texts: string[]) => {
143
141
  const defer = cache.get(texts[index]);
144
142
  if (defer) {
145
- defer.resolve([text]);
143
+ defer.resolve(text);
146
144
  }
147
145
  return text;
148
146
  };
@@ -156,23 +154,30 @@ function requester(params: RequesterParams, cache: Cache) {
156
154
  return texts.map(resolve);
157
155
  }
158
156
 
159
- return client
160
- .translate(
161
- TranslateRequest.fromPartial({
162
- texts,
163
- folderId,
164
- sourceLanguageCode: sourceLanguage,
165
- targetLanguageCode: targetLanguage,
166
- // glossaryConfig: {
167
- // glossaryData: {
168
- // glossaryPairs: yandexCloudTranslateGlossaryPairs,
169
- // },
170
- // },
171
- format: Format.HTML,
172
- }),
173
- )
174
- .then((results) => {
175
- return results.translations.map(({text}, index) => {
157
+ return axios({
158
+ method: 'POST',
159
+ url: 'https://translate.api.cloud.yandex.net/translate/v2/translate',
160
+ headers: {
161
+ 'Content-Type': 'application/json',
162
+ Authorization: auth,
163
+ },
164
+ data: {
165
+ folderId,
166
+ texts,
167
+ sourceLanguageCode: sourceLanguage,
168
+ targetLanguageCode: targetLanguage,
169
+ format: 'HTML',
170
+ },
171
+ })
172
+ .then(({data, status}) => {
173
+ if (status === 200) {
174
+ return data;
175
+ } else {
176
+ throw new Error(data.message);
177
+ }
178
+ })
179
+ .then((result: Translations) => {
180
+ return result.translations.map(({text}, index) => {
176
181
  return resolve(text, index, texts);
177
182
  });
178
183
  })
@@ -193,6 +198,8 @@ function requester(params: RequesterParams, cache: Cache) {
193
198
 
194
199
  function translator(params: TranslatorParams, split: Split) {
195
200
  const {input, output, sourceLanguage, targetLanguage} = params;
201
+ const inputRoot = resolve(input);
202
+ const outputRoot = resolve(output);
196
203
 
197
204
  return async (path: string) => {
198
205
  const ext = extname(path);
@@ -200,8 +207,8 @@ function translator(params: TranslatorParams, split: Split) {
200
207
  return;
201
208
  }
202
209
 
203
- const inputPath = resolve(input, path);
204
- const outputPath = resolve(output, path);
210
+ const inputPath = join(inputRoot, path);
211
+ const outputPath = join(outputRoot, path.replace(sourceLanguage, targetLanguage));
205
212
  const content = await loadFile(inputPath);
206
213
 
207
214
  await mkdir(dirname(outputPath), {recursive: true});
@@ -227,7 +234,7 @@ function translator(params: TranslatorParams, split: Split) {
227
234
  return;
228
235
  }
229
236
 
230
- const parts = flat(await Promise.all(split(path, units)));
237
+ const parts = await Promise.all(split(path, units));
231
238
  const composed = compose(skeleton, parts, {useSource: true});
232
239
 
233
240
  await dumpFile(outputPath, composed);
@@ -236,37 +243,39 @@ function translator(params: TranslatorParams, split: Split) {
236
243
 
237
244
  function splitter(request: Request, cache: Cache): Split {
238
245
  return function (path: string, texts: string[]) {
239
- const promises: Promise<string[]>[] = [];
246
+ const promises: Promise<string>[] = [];
240
247
  let buffer: string[] = [];
241
248
  let bufferSize = 0;
242
249
 
243
250
  const release = () => {
244
- promises.push(backoff(request(buffer)));
251
+ backoff(request(buffer));
245
252
  buffer = [];
246
253
  bufferSize = 0;
247
254
  };
248
255
 
249
256
  for (const text of texts) {
250
- const defer = cache.get(text);
251
-
252
- if (defer) {
253
- promises.push(defer.promise);
254
- } else if (text.length >= BYTES_LIMIT) {
257
+ if (text.length >= BYTES_LIMIT) {
255
258
  logger.warn(path, 'Skip document part for translation. Part is too big.');
256
- promises.push(Promise.resolve([text]));
259
+ promises.push(Promise.resolve(text));
257
260
  } else {
258
- if (bufferSize + text.length > BYTES_LIMIT) {
259
- release();
261
+ const defer = cache.get(text) || new Defer();
262
+ promises.push(defer.promise);
263
+
264
+ if (!cache.get(text)) {
265
+ if (bufferSize + text.length > BYTES_LIMIT) {
266
+ release();
267
+ }
268
+
269
+ buffer.push(text);
270
+ bufferSize += text.length;
260
271
  }
261
272
 
262
- buffer.push(text);
263
- bufferSize += text.length;
264
- cache.set(text, new Defer());
273
+ cache.set(text, defer);
265
274
  }
266
275
  }
267
276
 
268
277
  if (bufferSize) {
269
- promises.push(backoff(request(buffer)));
278
+ release();
270
279
  }
271
280
 
272
281
  return promises;
@@ -141,16 +141,12 @@ export function resolveSchemas(_path: string) {
141
141
  return null;
142
142
  }
143
143
 
144
- export function flat<T>(parts: T[][]) {
145
- return ([] as T[]).concat(...parts);
146
- }
147
-
148
144
  export class Defer {
149
- resolve!: (text: string[]) => void;
145
+ resolve!: (text: string) => void;
150
146
 
151
147
  reject!: (error: any) => void;
152
148
 
153
- promise: Promise<string[]>;
149
+ promise: Promise<string>;
154
150
 
155
151
  constructor() {
156
152
  this.promise = new Promise((resolve, reject) => {
@@ -1,41 +1,30 @@
1
1
  import {readFileSync} from 'fs';
2
2
 
3
- type ServiceAccauntInfo = {
4
- id: string;
5
- service_account_id: string;
6
- public_key: string;
7
- private_key: string;
3
+ const resolveKey = (data: string) => {
4
+ switch (true) {
5
+ case data.startsWith('y0_'):
6
+ return 'Bearer ' + data;
7
+ case data.startsWith('t1.'):
8
+ return 'Bearer ' + data;
9
+ case data.startsWith('AQVN'):
10
+ return 'Api-Key ' + data;
11
+ default:
12
+ return null;
13
+ }
8
14
  };
9
15
 
10
- export type AuthInfo = ReturnType<typeof getYandexAuth>;
11
-
12
16
  export function getYandexAuth(path: string) {
13
- if (path.startsWith('y0_')) {
14
- return {
15
- oauthToken: path,
16
- };
17
- }
17
+ let auth = resolveKey(path);
18
18
 
19
- const data = readFileSync(path, 'utf8');
20
- try {
21
- const json = JSON.parse(data);
19
+ if (auth !== null) {
20
+ return auth;
21
+ }
22
22
 
23
- if (isServeseAccount(json)) {
24
- return {
25
- serviceAccountJson: {
26
- serviceAccountId: json.service_account_id,
27
- accessKeyId: json.id,
28
- privateKey: json.private_key,
29
- },
30
- };
31
- }
32
- } catch {}
23
+ auth = resolveKey(readFileSync(path, 'utf8'));
33
24
 
34
- return {
35
- oauthToken: data,
36
- };
37
- }
25
+ if (auth === null) {
26
+ throw new Error('No Auth');
27
+ }
38
28
 
39
- function isServeseAccount(json: any): json is ServiceAccauntInfo {
40
- return 'private_key' in json;
29
+ return auth;
41
30
  }