@enplug/scripts 1.11.4-dev6 → 1.11.4-dev61

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.
@@ -1,6 +1,7 @@
1
1
  const axios = require('axios');
2
2
  const chalk = require('chalk');
3
3
  const fs = require('fs');
4
+ const path = require('path');
4
5
  const FormData = require('form-data');
5
6
  const inquirer = require('inquirer');
6
7
  const loadDevPrivateFile = require('../loadDevPrivateFile');
@@ -13,9 +14,7 @@ const { catchError, switchMap, tap, filter } = require('rxjs/operators');
13
14
  const HTTP_UNAUTHORIZED_STATUS_CODE = 401;
14
15
  const HTTP_NOT_FOUND_STATUS_CODE = 404;
15
16
 
16
- // const CROWDIN_PROJECT_ID = 'enplug';
17
17
  const CROWDIN_PROJECT_ID = '401630';
18
- // const CROWDIN_PROJECT_URL = `https://api.crowdin.com/api/project/${CROWDIN_PROJECT_ID}`;
19
18
  const CROWDIN_PROJECT_URL = `https://api.crowdin.com/api/v2/projects/${CROWDIN_PROJECT_ID}`;
20
19
  const CROWDIN_STORAGE_URL = `https://api.crowdin.com/api/v2/storages`;
21
20
  const CROWDIN_DIRECTORY_NOT_FOUND_ERROR_CODE = 17;
@@ -108,115 +107,72 @@ function getCrowdinConfig() {
108
107
  return pkg.config.crowdin;
109
108
  }
110
109
 
111
- function generateFormData(crowdinPath, localPath) {
112
- const formData = new FormData();
113
-
114
- // formData.append('update_option', 'update_without_changes'); // Previous translations should remain valid
115
- formData.append('json', '');
116
- formData.append(`files[${crowdinPath}]`, fs.createReadStream(localPath));
117
- formData.append(`export_patterns[${crowdinPath}]`, '%locale%.json');
118
- return formData;
119
- }
120
-
121
- function postFileToCrowdin(operation, credentials, crowdinPath, localPath) {
122
- const AuthStr = 'Bearer '.concat(credentials.token);
123
- const formData = generateFormData(crowdinPath, localPath);
124
-
125
- const url = `${CROWDIN_STORAGE_URL}`;
126
-
127
- return from(axios.post(url, formData, { headers: {
128
- "Authorization": AuthStr,
129
- "Content-Type": "application/json",
130
- "Crowdin-API-FileName": "en.json"
131
- } }));
132
- }
133
-
134
- async function findCrowdinAppDirectoryId(credentials, crowdinPath) {
135
- path = crowdinPath.startsWith('/') ? crowdinPath.substr(1) : crowdinPath;
136
- if(path.startsWith('apps')){
137
- const appName = path.split('/')[1];
138
- const url = `${CROWDIN_PROJECT_URL}/directories?filter=${appName}`;
139
- const AuthStr = 'Bearer '.concat(credentials.token);
140
- const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
141
- console.log('resp', resp.data.data);
142
- console.log('appName', appName);
143
- const directories = resp.data.data;
144
- const appdata = directories.find(d => {
145
- return d.data.name === appName
146
- });
147
- console.log('appdata', appdata);
148
- return appdata.id
149
- } else if(path.startsWith('dashboard')) {
150
- const url = `${CROWDIN_PROJECT_URL}/directories?filter=dashboard`;
151
- const AuthStr = 'Bearer '.concat(credentials.token);
152
- const directories = axios.get(url, { headers: { Authorization: AuthStr } });
153
- console.log('directories', directories.data.data)
154
-
155
- return directories.data.data.find(d => d.data.name === 'dashboard' && d.data.title === 'Dashboard' && d.data.path === '/dashboard').id;
110
+ async function findCrowdinAppDirectoryId(credentials, crowdinPath, appName) {
111
+ try {
112
+ if(crowdinPath.startsWith('apps') || appName !== 'en.json') { // path is apps/{app-name}/... or dashboard/{data-connector or regions-map or uploader}/en.json
113
+ const url = `${CROWDIN_PROJECT_URL}/directories?filter=${appName}`;
114
+ const AuthStr = 'Bearer '.concat(credentials.token);
115
+ const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
116
+ const directory = resp.data.data.find(d => d.data.name === appName );
117
+ return directory ? directory.data.id : undefined;
118
+ } else if((crowdinPath.startsWith('dashboard') || crowdinPath.startsWith('player-web') || crowdinPath.startsWith('components')) && appName === 'en.json') { //path is dashboard/en.json or player-web/en.json or components/en.json
119
+ const url = `${CROWDIN_PROJECT_URL}/directories?filter=dashboard`;
120
+ const AuthStr = 'Bearer '.concat(credentials.token);
121
+ const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
122
+ const directory = resp.data.data.find(d => d.data.name === 'dashboard' && d.data.title === 'Dashboard' && d.data.path === '/dashboard');
123
+ return directory ? directory.data.id : undefined;
124
+ }
125
+ } catch (err) {
126
+ if (err.response.status === HTTP_UNAUTHORIZED_STATUS_CODE) {
127
+ console.error(`\n${chalk.red.bold('Provided Crowdin token is invalid')}`);
128
+ console.log(`Check the ${chalk.default.yellow('dev.private.json')} file.`);
129
+ return throwError(err);
130
+ }
156
131
  }
157
132
  }
158
133
 
159
134
  async function findCrowdinAppSubFolderId(credentials, directoryId, subfolderName) {
160
135
  const url = `${CROWDIN_PROJECT_URL}/directories?directoryId=${directoryId}`;
161
136
  const AuthStr = 'Bearer '.concat(credentials.token);
162
- const directories = await axios.get(url, { headers: { Authorization: AuthStr } });
163
- console.log('subdirectories', directories.data.data)
164
-
165
- return directories.data.data.find(d => d.data.name === subfolderName).id;
137
+ const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
138
+ const subdirectory = resp.data.data.find(d => d.data.name === subfolderName);
139
+ return subdirectory ? subdirectory.data.id : undefined;
166
140
  }
167
141
 
168
142
  async function getFileIdIfExists(credentials, directoryId, fileName) {
169
143
  const url = `${CROWDIN_PROJECT_URL}/files?directoryId=${directoryId}`;
170
144
  const AuthStr = 'Bearer '.concat(credentials.token);
171
- const files = await axios.get(url, { headers: { Authorization: AuthStr } });
172
- return files.data.find(d => d.data.name === fileName).id;
145
+ const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
146
+ const file = resp.data.data.find(d => d.data.name === fileName);
147
+ return file ? file.data.id : undefined;
148
+ }
149
+
150
+ function postFileToCrowdin(credentials, localPath) {
151
+ const AuthStr = 'Bearer '.concat(credentials.token);
152
+ const file = fs.readFileSync(localPath);
153
+ const url = `${CROWDIN_STORAGE_URL}`;
154
+
155
+ return from(axios.post(url, file, { headers: {
156
+ "Authorization": AuthStr,
157
+ "Content-Type": 'application/json',
158
+ "Crowdin-API-FileName": 'en.json'
159
+ } }));
173
160
  }
174
161
 
175
- async function uploadFileToCrowdinStorage(credentials, crowdinPath, localPath) {
162
+ async function uploadFileToCrowdinStorage(credentials, localPath) {
176
163
  if (!fs.existsSync(localPath)) {
177
164
  console.error(`${chalk.red.bold('Local file does not exists')} ${chalk.yellow.bold(`[${localPath}]`)}`);
178
165
  throw new Error('Local file does not exist');
179
166
  }
180
-
181
- return postFileToCrowdin('update', credentials, crowdinPath, localPath).pipe(
167
+ return postFileToCrowdin(credentials, localPath).pipe(
182
168
  catchError(error => {
183
- if (error.response.status === HTTP_NOT_FOUND_STATUS_CODE) {
184
- return promptAddFile(crowdinPath).pipe(
185
- filter(({addFileConfirm}) => addFileConfirm === true),
186
- switchMap(() => postFileToCrowdin('add', credentials, crowdinPath, localPath))
187
- );
188
- }
189
-
169
+ console('ERROR could not upload file to crowdin storage')
190
170
  return throwError(error);
191
171
  }),
192
- tap({
193
- next: response => {
194
- if (response.data) {
195
- console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
196
- } else {
197
- console.error('Unexpected result');
198
- console.log(response);
199
- }
200
- },
201
- error: error => {
202
- const crowdinError = error.response && error.response.data && error.response.data.error;
203
-
204
- if (crowdinError && crowdinError.code === CROWDIN_DIRECTORY_NOT_FOUND_ERROR_CODE) {
205
- console.error(`\n${chalk.red.bold('Directory does not exist')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
206
- console.log('Create the directory in the Crowdin panel first.');
207
- } else if (error.response.status === HTTP_UNAUTHORIZED_STATUS_CODE) {
208
- console.error(`\n${chalk.red.bold('Provided Crowdin credentials are incorrect')}`);
209
- console.log(`Check the ${chalk.default.yellow('dev.private.json')} file.`);
210
- } else {
211
- console.error('\nUnexpected error:');
212
- console.error(error);
213
- }
214
- }
215
- })
216
172
  ).toPromise();
217
173
  }
218
174
 
219
- function updateCrowdinFile(credentials, storageId, fileId) {
175
+ async function updateCrowdinFile(credentials, crowdinPath, storageId, fileId) {
220
176
  const url = `${CROWDIN_PROJECT_URL}/files/${fileId}`;
221
177
  const AuthStr = 'Bearer '.concat(credentials.token);
222
178
  const body = {
@@ -231,19 +187,66 @@ function updateCrowdinFile(credentials, storageId, fileId) {
231
187
  },
232
188
  "replaceModifiedContext": false
233
189
  }
234
- return axios.put(url, body, { headers: { Authorization: AuthStr } });
190
+ return from(axios.put(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({
191
+ next: response => {
192
+ if (response.data) {
193
+ console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
194
+ } else {
195
+ console.error('Unexpected result');
196
+ console.log(response);
197
+ }
198
+ },
199
+ error: error => {
200
+ console.error('\nUnexpected error:');
201
+ console.error(error);
202
+ }
203
+ })).toPromise();
235
204
  }
236
205
 
237
- function fetchFileFromCrowdin(credentials, crowdinPath, language) {
238
- const url = `${CROWDIN_PROJECT_URL}/export-file`;
239
- const params = {
240
- 'login': credentials.login,
241
- 'account-key': credentials.accountKey,
242
- 'file': crowdinPath,
243
- 'language': language
206
+ async function addCrowdinFile(credentials, crowdinPath, storageId, folderId) {
207
+ const url = `${CROWDIN_PROJECT_URL}/files`;
208
+ const AuthStr = 'Bearer '.concat(credentials.token);
209
+ const body = {
210
+ "storageId": storageId,
211
+ "name": "en.json",
212
+ "directoryId": folderId,
213
+ "context": null,
214
+ "type": "json",
215
+ "parserVersion": 1,
216
+ "importOptions": {
217
+ "contentSegmentation": false,
218
+ "customSegmentation": false
219
+ },
220
+ "exportOptions": {
221
+ "exportPattern": "%locale%.json"
222
+ },
223
+ "excludedTargetLanguages": null
224
+ }
225
+ return from(axios.post(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({
226
+ next: response => {
227
+ if (response.data) {
228
+ console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
229
+ } else {
230
+ console.error('Unexpected result');
231
+ console.log(response);
232
+ }
233
+ },
234
+ error: error => {
235
+ console.error('\nUnexpected error:');
236
+ console.error(error);
237
+ }
238
+ })).toPromise();
239
+ }
240
+
241
+ function fetchFileFromCrowdin(credentials, language, fileId) {
242
+ const url = `${CROWDIN_PROJECT_URL}/translations/exports`;
243
+ const AuthStr = 'Bearer '.concat(credentials.token);
244
+ const body = {
245
+ "targetLanguageId": language,
246
+ "fileIds": [fileId]
244
247
  };
245
248
 
246
- return axios.get(url, { params });
249
+ return axios.post(url, body, { headers: { Authorization: AuthStr } });
247
250
  }
248
251
 
249
252
  function promptAddFile(crowdinPath) {
@@ -256,4 +259,4 @@ function promptAddFile(crowdinPath) {
256
259
  }));
257
260
  }
258
261
 
259
- module.exports = { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, uploadFileToCrowdin, fetchFileFromCrowdin };
262
+ module.exports = { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, addCrowdinFile, uploadFileToCrowdin, fetchFileFromCrowdin };
@@ -5,7 +5,7 @@ const inquirer = require('inquirer');
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
7
 
8
- const { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, uploadFileToCrowdin, fetchFileFromCrowdin } = require('./crowdin');
8
+ const { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, addCrowdinFile, uploadFileToCrowdin, fetchFileFromCrowdin } = require('./crowdin');
9
9
  const { checkKeys, validateTranslationFile } = require('./transloco');
10
10
  const { uploadTranslationToS3 } = require('./translation-s3');
11
11
  const getPackageJson = require('../getPackageJson');
@@ -61,34 +61,80 @@ async function syncTranslations(s3Client, bucket) {
61
61
  await uploadTranslationToS3(s3Client, bucket, s3EnPath, enTranslation);
62
62
 
63
63
  if (isProduction) {
64
- const appDirectoryId = await findCrowdinAppDirectoryId(credentials, config.crowdinPath);
65
- console.log('found directoryId', appDirectoryId);
66
- if(config.crowdinPath.includes('apps')) {
67
- const path = crowdinPath.startsWith('/') ? crowdinPath.substr(1) : crowdinPath;
68
- const subfolderName = path.split('/')[2];
64
+ const crowdinPath = config.crowdinPath.startsWith('/') ? config.crowdinPath.substr(1) : config.crowdinPath;
65
+ const crowdinPathSections = crowdinPath.split('/');
66
+ const appName = crowdinPathSections[1];
67
+ const appDirectoryId = await findCrowdinAppDirectoryId(credentials, crowdinPath, appName);
68
+ if(appDirectoryId === undefined) {
69
+ console.error(`\n${chalk.red.bold('Directory does not exist')} ${chalk.yellow.bold(`${appName}`)}`);
70
+ console.log('Create the directory in the Crowdin panel first.');
71
+ return;
72
+ }
73
+ if(crowdinPathSections[0] === 'apps' && appDirectoryId) {
74
+ if(crowdinPathSections.length !== 4 && crowdinPathSections[3] !== 'en.json') {
75
+ console.error(`\n${chalk.red.bold('Crowdin path provided does not match defined format, make sure the path is as follows /apps/{app-id}/dashboard/en.json or /apps/{app-id}/app/en.json')}`);
76
+ return;
77
+ }
78
+ const subfolderName = crowdinPathSections[2]; //dashboard or app folder
69
79
  const folderId = await findCrowdinAppSubFolderId(credentials, appDirectoryId, subfolderName);
70
- console.log('found folderId', folderId);
71
- const fileId = await getFileIdIfExists(credentials, appDirectoryId, path.split('/')[3]);
72
- console.log('found fileId', fileId);
73
- const storageId = await uploadFileToCrowdinStorage(credentials, config.crowdinPath, config.localPath)
80
+ if(folderId === undefined) {
81
+ console.error(`Could not find ${chalk.yellow.bold(`[${subfolderName}]`)} folder`);
82
+ }
83
+ const fileId = await getFileIdIfExists(credentials, folderId, crowdinPathSections[3]); // en.json file id to update
74
84
  if(fileId) {
75
- await updateCrowdinFile(credentials, storageId, fileId);
85
+ const storageId = await uploadFileToCrowdinStorage(credentials, config.localPath);
86
+ if(fileId && storageId) {
87
+ await updateCrowdinFile(credentials, crowdinPath, storageId.data.data.id, fileId);
88
+ await updateFrakeTranslations(credentials, fileId);
89
+ }
90
+ } else {
91
+ const storageId = await uploadFileToCrowdinStorage(credentials, config.localPath);
92
+ if(storageId) {
93
+ const result = await addCrowdinFile(credentials, crowdinPath, storageId.data.data.id, folderId);
94
+ console.log('add result', result.data);
95
+ // await updateFrakeTranslations(credentials, fileId);
96
+ }
97
+ }
98
+ } else if((crowdinPathSections[0] === 'dashboard' || crowdinPathSections[0] === 'player-web' || crowdinPathSections[0] === 'components') && appDirectoryId) {
99
+ if(crowdinPathSections[1] === 'en.json') {
100
+ const fileId = await getFileIdIfExists(credentials, appDirectoryId, crowdinPathSections[1]); // en.json file id to update
101
+ if(fileId) {
102
+ const storageId = await uploadFileToCrowdinStorage(credentials, config.localPath);
103
+ if(fileId && storageId) {
104
+ await updateCrowdinFile(credentials, crowdinPath, storageId.data.data.id, fileId);
105
+ await updateFrakeTranslations(credentials, fileId);
106
+ }
107
+ } else {
108
+ console.error(`Could not upload ${chalk.yellow.bold(`${rowdinPathSections[1]}`)}. Only en.json supported.`);
109
+ }
110
+ } else { // data-connector, regions-map and uploader in dashboard folder
111
+ const folderId = await findCrowdinAppDirectoryId(credentials, crowdinPath, crowdinPathSections[1]);
112
+ if(folderId === undefined) {
113
+ console.error(`Could not find ${chalk.yellow.bold(`${folderId}`)} folder`);
114
+ }
115
+ const fileId = await getFileIdIfExists(credentials, folderId, crowdinPathSections[2]); // en.json file id to update
116
+ const storageId = await uploadFileToCrowdinStorage(credentials, config.localPath);
117
+ if(fileId && storageId) {
118
+ await updateCrowdinFile(credentials, crowdinPath, storageId.data.data.id, fileId);
119
+ await updateFrakeTranslations(credentials, fileId);
120
+ }
76
121
  }
77
- } else {
78
- // TODO Update dashboard transtlations file
79
122
  }
80
- // await uploadFileToCrowdin(credentials, config.crowdinPath, config.localPath);
81
- // const { data: fakeTranslation } = await fetchFileFromCrowdin(credentials, config.crowdinPath, FAKE_IN_CONTEXT_LANGUAGE);
82
-
83
- // const s3TranslationsPath = path.parse(s3EnPath).dir;
84
- // const s3FakeTranslationPath = path.join(s3TranslationsPath, FAKE_IN_CONTEXT_LANGUAGE_FILE);
85
-
86
- // await uploadTranslationToS3(s3Client, bucket, s3FakeTranslationPath, JSON.stringify(fakeTranslation));
87
123
  }
88
124
  }
89
125
  }
90
126
  }
91
127
 
128
+ async function updateFrakeTranslations(credentials, fileId) {
129
+ const { data: fakeTranslation } = await fetchFileFromCrowdin(credentials, FAKE_IN_CONTEXT_LANGUAGE, fileId);
130
+ console.log('eo data', fakeTranslation);
131
+ const s3TranslationsPath = path.parse(s3EnPath).dir;
132
+ console.log('s3TranslationsPath', s3TranslationsPath);
133
+ const s3FakeTranslationPath = path.join(s3TranslationsPath, FAKE_IN_CONTEXT_LANGUAGE_FILE);
134
+ console.log('s3FakeTranslationPath', s3FakeTranslationPath);
135
+ // await uploadTranslationToS3(s3Client, bucket, s3FakeTranslationPath, JSON.stringify(fakeTranslation));
136
+ }
137
+
92
138
  async function promptForceContinue() {
93
139
  return inquirer.prompt({
94
140
  type: 'confirm',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enplug/scripts",
3
- "version": "1.11.4-dev6",
3
+ "version": "1.11.4-dev61",
4
4
  "description": "Enplug scripts",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",