@enplug/scripts
Version:
Enplug scripts
213 lines (189 loc) • 8.31 kB
JavaScript
const axios = require('axios');
const chalk = require('chalk');
const fs = require('fs');
const inquirer = require('inquirer');
const loadDevPrivateFile = require('../loadDevPrivateFile');
const rootPath = __dirname.split('node_modules')[0];
const getPackageJson = require('../getPackageJson');
const { from, throwError } = require('rxjs');
const { catchError, switchMap, tap, filter } = require('rxjs/operators');
const HTTP_UNAUTHORIZED_STATUS_CODE = 401;
const HTTP_NOT_FOUND_STATUS_CODE = 404;
const CROWDIN_PROJECT_ID = '401630';
const CROWDIN_PROJECT_URL = `https://api.crowdin.com/api/v2/projects/${CROWDIN_PROJECT_ID}`;
const CROWDIN_STORAGE_URL = `https://api.crowdin.com/api/v2/storages`;
function getCrowdinCredentials() {
try {
let devPrivateFile;
try { devPrivateFile = loadDevPrivateFile(rootPath); }
catch {
try { devPrivateFile = loadDevPrivateFile('../'); }
catch { devPrivateFile = loadDevPrivateFile('../../'); }
}
if (!devPrivateFile.crowdinCredentials) {
throw new Error('Crowdin credentials missing');
}
return devPrivateFile.crowdinCredentials;
} catch {
console.error(chalk.bold.red('Could not fetch Crowdin credentials'));
console.log(`Make sure that the ${chalk.bold.yellow('dev.private.json')} file contains ${chalk.bold.yellow('{ crowdinCredentials: { login, accountKey } }')}.`);
throw new Error('Could not get Crowdin credentials');
}
}
function getCrowdinConfig() {
const pkg = getPackageJson();
if (!pkg) {
console.error(chalk.bold.red('Could not find package.json file'));
throw new Error('Could not find package.json file');
}
if (!pkg.config || !pkg.config.crowdin || !pkg.config.crowdin.crowdinPath || !pkg.config.crowdin.localPath) {
console.error(chalk.bold.red('Could not find Crowdin config'));
console.log(`Make sure that the ${chalk.bold.yellow('package.json')} file contains ${chalk.bold.yellow('{ config: { crowdin: crowdinPath, localPath } }')}.`);
throw new Error('Could not get Crowdin config');
}
return pkg.config.crowdin;
}
async function findCrowdinAppDirectoryId(credentials, crowdinPath, appName) {
try {
if(crowdinPath.startsWith('apps') || appName !== 'en.json') { // path is apps/{app-name}/... or dashboard/{data-connector or regions-map or uploader}/en.json
const url = `${CROWDIN_PROJECT_URL}/directories?filter=${appName}`;
const AuthStr = 'Bearer '.concat(credentials.token);
const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
const directory = resp.data.data.find(d => d.data.name === appName );
return directory ? directory.data.id : undefined;
} 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
const url = `${CROWDIN_PROJECT_URL}/directories?filter=dashboard`;
const AuthStr = 'Bearer '.concat(credentials.token);
const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
const directory = resp.data.data.find(d => d.data.name === 'dashboard' && d.data.title === 'Dashboard' && d.data.path === '/dashboard');
return directory ? directory.data.id : undefined;
}
} catch (err) {
if (err.response.status === HTTP_UNAUTHORIZED_STATUS_CODE) {
console.error(`\n${chalk.red.bold('Provided Crowdin token is invalid')}`);
console.log(`Check the ${chalk.default.yellow('dev.private.json')} file.`);
return throwError(err);
}
}
}
async function findCrowdinAppSubFolderId(credentials, directoryId, subfolderName) {
const url = `${CROWDIN_PROJECT_URL}/directories?directoryId=${directoryId}`;
const AuthStr = 'Bearer '.concat(credentials.token);
const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
const subdirectory = resp.data.data.find(d => d.data.name === subfolderName);
return subdirectory ? subdirectory.data.id : undefined;
}
async function getFileIdIfExists(credentials, directoryId, fileName) {
const url = `${CROWDIN_PROJECT_URL}/files?directoryId=${directoryId}`;
const AuthStr = 'Bearer '.concat(credentials.token);
const resp = await axios.get(url, { headers: { Authorization: AuthStr } });
const file = resp.data.data.find(d => d.data.name === fileName);
return file ? file.data.id : undefined;
}
function postFileToCrowdin(credentials, localPath) {
const AuthStr = 'Bearer '.concat(credentials.token);
const file = fs.readFileSync(localPath);
const url = `${CROWDIN_STORAGE_URL}`;
return from(axios.post(url, file, { headers: {
"Authorization": AuthStr,
"Content-Type": 'application/json',
"Crowdin-API-FileName": 'en.json'
} }));
}
async function uploadFileToCrowdinStorage(credentials, localPath) {
if (!fs.existsSync(localPath)) {
console.error(`${chalk.red.bold('Local file does not exists')} ${chalk.yellow.bold(`[${localPath}]`)}`);
throw new Error('Local file does not exist');
}
return postFileToCrowdin(credentials, localPath).pipe(
catchError(error => {
console('ERROR could not upload file to crowdin storage')
return throwError(error);
}),
).toPromise();
}
async function updateCrowdinFile(credentials, crowdinPath, storageId, fileId) {
const url = `${CROWDIN_PROJECT_URL}/files/${fileId}`;
const AuthStr = 'Bearer '.concat(credentials.token);
const body = {
"storageId": storageId,
"updateOption": "keep_translations_and_approvals",
"importOptions": {
"contentSegmentation": false,
"customSegmentation": false
},
"exportOptions": {
"exportPattern": "%locale%.json"
},
"replaceModifiedContext": false
}
return from(axios.put(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({
next: response => {
if (response.data) {
console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
} else {
console.error('Unexpected result');
console.log(response);
}
},
error: error => {
console.error('\nUnexpected error:');
console.error(error);
}
})).toPromise();
}
async function addCrowdinFile(credentials, crowdinPath, storageId, folderId) {
const url = `${CROWDIN_PROJECT_URL}/files`;
const AuthStr = 'Bearer '.concat(credentials.token);
const body = {
"storageId": storageId,
"name": "en.json",
"directoryId": folderId,
"context": null,
"type": "json",
"parserVersion": 1,
"importOptions": {
"contentSegmentation": false,
"customSegmentation": false
},
"exportOptions": {
"exportPattern": "%locale%.json"
},
"excludedTargetLanguages": null
}
return from(axios.post(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({
next: response => {
if (response.data) {
console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`);
} else {
console.error('Unexpected result');
console.log(response);
}
},
error: error => {
console.error('\nUnexpected error:');
console.error(error);
}
})).toPromise();
}
function fetchFileFromCrowdin(credentials, language, fileId) {
const url = `${CROWDIN_PROJECT_URL}/translations/exports`;
const AuthStr = 'Bearer '.concat(credentials.token);
const body = {
"targetLanguageId": language,
"fileIds": [fileId]
};
return axios.post(url, body, { headers: { Authorization: AuthStr } });
}
function readFakeTranslationsFile(url) {
return axios.get(url);
}
function promptAddFile(crowdinPath) {
const prompt = inquirer.createPromptModule();
return from(prompt({
type: 'confirm',
name: 'addFileConfirm',
message: `${chalk.reset('File')} ${chalk.yellow.bold(`[${crowdinPath}]`)} ${chalk.reset('does not exist in Crowdin repository.')}\nDo you want to add this file?`,
}));
}
module.exports = { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, addCrowdinFile, fetchFileFromCrowdin, readFakeTranslationsFile };