crowdin-api
Advanced tools
Comparing version 1.1.2 to 2.0.0
328
index.js
'use strict'; | ||
var fs = require('fs'); | ||
var request = require('request-promise'); | ||
const fs = require('fs'); | ||
const request = require('request'); | ||
const requestPromise = require('request-promise'); | ||
const temp = require('temp'); | ||
const Bluebird = require('bluebird'); | ||
const _ = require('lodash'); | ||
var apiKey; | ||
var baseUrl = 'https://api.crowdin.com'; | ||
temp.track(); | ||
function validateKey() { | ||
if (apiKey === undefined) { | ||
throw new Error('Please specify CrowdIn API key.'); | ||
} | ||
function resultToError(result) { | ||
return new Error('Error code ' + result.error.code + ': ' + result.error.message); | ||
} | ||
function throwError(result) { | ||
throw new Error('Error code ' + result.error.code + ': ' + result.error.message); | ||
function parseError(err) { | ||
if (err.response && err.response.body) { | ||
try { | ||
const parsed = JSON.parse(err.response.body); | ||
return resultToError(parsed); | ||
} catch (parseErr) { | ||
// Return original error instead | ||
return err; | ||
} | ||
} | ||
return err; | ||
} | ||
function handleRequest(request) { | ||
return request | ||
.then(function (body) { | ||
const result = JSON.parse(body); | ||
if (result.success === false) { | ||
throwError(result); | ||
} | ||
async function handlePromise(request) { | ||
let body; | ||
try { | ||
body = await request; | ||
} catch (err) { | ||
throw parseError(err); | ||
} | ||
return result; | ||
}) | ||
.catch(function (err) { | ||
if (err.response && err.response.body) { | ||
try { | ||
var parsed = JSON.parse(err.response.body); | ||
throwError(parsed); | ||
} catch (parseErr) { | ||
throw err; | ||
} | ||
} | ||
const result = JSON.parse(body); | ||
if (result.success === false) { | ||
throw resultToError(result); | ||
} | ||
throw err; | ||
}); | ||
return result; | ||
} | ||
function getApiCall(apiUrl) { | ||
validateKey(); | ||
async function handleStream(request) { | ||
const {path, fd} = await Bluebird.fromCallback(cb => { | ||
temp.open('crowdin', cb); | ||
}); | ||
var url = baseUrl + '/api/' + apiUrl; | ||
var params = { | ||
json: true, | ||
key: apiKey | ||
}; | ||
return new Bluebird((resolve, reject) => { | ||
let statusCode; | ||
return handleRequest(request.get({ | ||
url: url, | ||
qs: params | ||
})); | ||
request | ||
.on('error', err => { | ||
reject(parseError(err)); | ||
}) | ||
.on('response', response => { | ||
statusCode = response.statusCode; | ||
}) | ||
.on('close', async () => { | ||
if (statusCode < 400) { | ||
resolve(path); | ||
} else { | ||
try { | ||
const result = await Bluebird.fromCallback(cb => fs.readFile(path, 'utf8')); | ||
reject(resultToError(result)); | ||
} catch (err) { | ||
reject(`Error streaming from Crowdin: ${statusCode}`); | ||
} | ||
} | ||
}) | ||
.pipe(fs.createWriteStream(null, { | ||
fd | ||
})); | ||
}); | ||
} | ||
function postApiCall(apiUrl, getOptions, postOptions) { | ||
validateKey(); | ||
class CrowdinApi { | ||
constructor({baseUrl = 'https://api.crowdin.com', apiKey}) { | ||
this.baseUrl = baseUrl; | ||
this.apiKey = apiKey; | ||
var url = baseUrl + '/api/' + apiUrl; | ||
var params = Object.assign(getOptions || {}, { | ||
json: true, | ||
key: apiKey | ||
}); | ||
console.log(baseUrl, apiKey); | ||
return handleRequest(request.post({ | ||
url: url, | ||
qs: params, | ||
formData: postOptions | ||
})); | ||
} | ||
if (!apiKey) { | ||
throw new Error('Please specify CrowdIn API key.'); | ||
} | ||
} | ||
function getApiRequest(apiUrl) { | ||
validateKey(); | ||
uri(path) { | ||
return `${this.baseUrl}/api/${path}`; | ||
} | ||
var url = baseUrl + '/api/' + apiUrl + '?key=' + apiKey + '&json'; | ||
getPromise(path) { | ||
return handlePromise(requestPromise.get({ | ||
uri: this.uri(path), | ||
qs: { | ||
json: true, | ||
key: this.apiKey | ||
} | ||
})); | ||
} | ||
return request(url); | ||
} | ||
postPromise(path, qs = {}, data) { | ||
Object.assign(qs, { | ||
json: true, | ||
key: this.apiKey | ||
}); | ||
module.exports = { | ||
setBasePath: function (newBasePath) { | ||
baseUrl = newBasePath; | ||
}, | ||
return handlePromise(requestPromise.post({ | ||
uri: this.uri(path), | ||
qs, | ||
formData: data | ||
})); | ||
} | ||
setKey: function (newKey) { | ||
apiKey = newKey; | ||
}, | ||
getStream(path) { | ||
return handleStream(request.get({ | ||
uri: this.uri(path), | ||
qs: { | ||
json: true, | ||
key: this.apiKey | ||
} | ||
})); | ||
} | ||
/** | ||
@@ -98,12 +137,10 @@ * Add new file to Crowdin project | ||
*/ | ||
addFile: function (projectName, files, params) { | ||
var filesInformation = {}; | ||
files.forEach(function (fileName) { | ||
var index = 'files[' + fileName + ']'; | ||
filesInformation[index] = fs.createReadStream(fileName); | ||
addFile(projectName, files, params) { | ||
const filesInformation = _.fromPairs(files, fileName => { | ||
return [`files[${fileName}]`, fs.createReadStream(fileName)]; | ||
}); | ||
return postApiCall('project/' + projectName + '/add-file', undefined, Object.assign(filesInformation, params)); | ||
}, | ||
return this.postPromise(`project/${projectName}/add-file`, undefined, Object.assign(filesInformation, params)); | ||
} | ||
/** | ||
@@ -116,12 +153,10 @@ * Upload latest version of your localization file to Crowdin. | ||
*/ | ||
updateFile: function (projectName, files, params) { | ||
var filesInformation = {}; | ||
files.forEach(function (fileName) { | ||
var index = 'files[' + fileName + ']'; | ||
filesInformation[index] = fs.createReadStream(fileName); | ||
updateFile(projectName, files, params) { | ||
const filesInformation = _.fromPairs(files, fileName => { | ||
return [`files[${fileName}]`, fs.createReadStream(fileName)]; | ||
}); | ||
return postApiCall('project/' + projectName + '/update-file', undefined, Object.assign(filesInformation, params)); | ||
}, | ||
return this.postPromise(`project/${projectName}/update-file`, undefined, Object.assign(filesInformation, params)); | ||
} | ||
/** | ||
@@ -132,7 +167,8 @@ * Delete file from Crowdin project. All the translations will be lost without ability to restore them. | ||
*/ | ||
deleteFile: function (projectName, fileName) { | ||
return postApiCall('project/' + projectName + '/delete-file', undefined, { | ||
deleteFile(projectName, fileName) { | ||
return this.postPromise(`project/${projectName}/delete-file`, undefined, { | ||
file: fileName | ||
}); | ||
}, | ||
} | ||
/** | ||
@@ -146,20 +182,17 @@ * Upload existing translations to your Crowdin project | ||
*/ | ||
updateTranslations: function (projectName, files, language, params) { | ||
var filesInformation = { | ||
language: language | ||
}; | ||
files.forEach(function (fileName) { | ||
var index = 'files[' + fileName + ']'; | ||
filesInformation[index] = fs.createReadStream(fileName); | ||
updateTranslations(projectName, files, language, params) { | ||
const filesInformation = _.fromPairs(files, fileName => { | ||
return [`files[${fileName}]`, fs.createReadStream(fileName)]; | ||
}); | ||
return postApiCall('project/' + projectName + '/upload-translation', undefined, Object.assign(filesInformation, params)); | ||
}, | ||
return this.postPromise(`project/${projectName}/upload-translation`, undefined, Object.assign(filesInformation, params)); | ||
} | ||
/** | ||
* Track your Crowdin project translation progress by language. | ||
* @param projectName {String} Should contain the project identifier. */ | ||
translationStatus: function (projectName) { | ||
return postApiCall('project/' + projectName + '/status'); | ||
}, | ||
translationStatus(projectName) { | ||
return this.postPromise(`project/${projectName}/status`); | ||
} | ||
/** | ||
@@ -169,17 +202,20 @@ * Get Crowdin Project details. | ||
*/ | ||
projectInfo: function (projectName) { | ||
return postApiCall('project/' + projectName + '/info'); | ||
}, | ||
projectInfo(projectName) { | ||
return this.postPromise(`project/${projectName}/info`); | ||
} | ||
/** | ||
* Download ZIP file with translations. You can choose the language of translation you need. | ||
*/ | ||
downloadTranslations: function (projectName, languageCode) { | ||
return getApiRequest('project/' + projectName + '/download/' + languageCode + '.zip'); | ||
}, | ||
downloadTranslations(projectName, languageCode) { | ||
return this.getStream(`project/${projectName}/download/${languageCode}.zip`); | ||
} | ||
/** | ||
* Download ZIP file with all translations. | ||
*/ | ||
downloadAllTranslations: function (projectName) { | ||
return getApiRequest('project/' + projectName + '/download/all.zip'); | ||
}, | ||
downloadAllTranslations(projectName) { | ||
return this.getStream(`project/${projectName}/download/all.zip`); | ||
} | ||
/** | ||
@@ -190,5 +226,6 @@ * Build ZIP archive with the latest translations. Please note that this method can be invoked only once per 30 minutes (there is no such | ||
*/ | ||
exportTranslations: function (projectName) { | ||
return getApiCall('project/' + projectName + '/export'); | ||
}, | ||
exportTranslations(projectName) { | ||
return this.getPromise(`project/${projectName}/export`); | ||
} | ||
/** | ||
@@ -199,5 +236,6 @@ * Edit Crowdin project | ||
*/ | ||
editProject: function (projectName, params) { | ||
return postApiCall('project/' + projectName + '/edit-project', undefined, params); | ||
}, | ||
editProject(projectName, params) { | ||
return this.postPromise(`project/${projectName}/edit-project`, undefined, params); | ||
} | ||
/** | ||
@@ -207,5 +245,6 @@ * Delete Crowdin project with all translations. | ||
*/ | ||
deleteProject: function (projectName) { | ||
return postApiCall('project/' + projectName + '/delete-project'); | ||
}, | ||
deleteProject(projectName) { | ||
return this.postPromise(`project/${projectName}/delete-project`); | ||
} | ||
/** | ||
@@ -216,7 +255,8 @@ * Add directory to Crowdin project. | ||
*/ | ||
createDirectory: function (projectName, directory) { | ||
return postApiCall('project/' + projectName + '/add-directory', undefined, { | ||
createDirectory(projectName, directory) { | ||
return this.postPromise(`project/${projectName}/add-directory`, undefined, { | ||
name: directory | ||
}); | ||
}, | ||
} | ||
/** | ||
@@ -228,7 +268,8 @@ * Rename directory or modify its attributes. When renaming directory the path can not be changed (it means new_name parameter can not contain path, name only). | ||
*/ | ||
changeDirectory: function (projectName, directory, params) { | ||
return postApiCall('project/' + projectName + '/change-directory', undefined, { | ||
changeDirectory(projectName, directory, params) { | ||
return this.postPromise(`project/${projectName}/change-directory`, undefined, { | ||
name: directory | ||
}, params); | ||
}, | ||
} | ||
/** | ||
@@ -239,13 +280,15 @@ * Delete Crowdin project directory. All nested files and directories will be deleted too. | ||
*/ | ||
deleteDirectory: function (projectName, directory) { | ||
return postApiCall('project/' + projectName + '/delete-directory', undefined, { | ||
deleteDirectory(projectName, directory) { | ||
return this.postPromise(`project/${projectName}/delete-directory`, undefined, { | ||
name: directory | ||
}); | ||
}, | ||
} | ||
/** | ||
* Download Crowdin project glossaries as TBX file. | ||
*/ | ||
downloadGlossary: function (projectName) { | ||
return getApiRequest('project/' + projectName + '/download-glossary'); | ||
}, | ||
downloadGlossary(projectName) { | ||
return this.getStream(`project/${projectName}/download-glossary`); | ||
} | ||
/** | ||
@@ -256,3 +299,3 @@ * Upload your glossaries for Crowdin Project in TBX file format. | ||
*/ | ||
uploadGlossary: function (projectName, fileNameOrStream) { | ||
uploadGlossary(projectName, fileNameOrStream) { | ||
if (typeof fileNameOrStream === 'string') { | ||
@@ -262,12 +305,14 @@ fileNameOrStream = fs.createReadStream(fileNameOrStream); | ||
return postApiCall('project/' + projectName + '/upload-glossary', undefined, { | ||
return this.postPromise(`project/${projectName}/upload-glossary`, undefined, { | ||
file: fileNameOrStream | ||
}); | ||
}, | ||
} | ||
/** | ||
* Download Crowdin project Translation Memory as TMX file. | ||
*/ | ||
downloadTranslationMemory: function (projectName) { | ||
return postApiCall('project/' + projectName + '/download-tm'); | ||
}, | ||
downloadTranslationMemory(projectName) { | ||
return this.postPromise(`project/${projectName}/download-tm`); | ||
} | ||
/** | ||
@@ -278,3 +323,3 @@ * Upload your Translation Memory for Crowdin Project in TMX file format. | ||
*/ | ||
uploadTranslationMemory: function (projectName, fileNameOrStream) { | ||
uploadTranslationMemory(projectName, fileNameOrStream) { | ||
if (typeof fileNameOrStream === 'string') { | ||
@@ -284,12 +329,15 @@ fileNameOrStream = fs.createReadStream(fileNameOrStream); | ||
return postApiCall('project/' + projectName + '/upload-tm', undefined, { | ||
return this.postPromise(`project/${projectName}/upload-tm`, undefined, { | ||
file: fileNameOrStream | ||
}); | ||
}, | ||
} | ||
/** | ||
* Get supported languages list with Crowdin codes mapped to locale name and standardized codes. | ||
*/ | ||
supportedLanguages: function () { | ||
return getApiCall('supported-languages'); | ||
supportedLanguages() { | ||
return this.getPromise('supported-languages'); | ||
} | ||
}; | ||
} | ||
module.exports = CrowdinApi; |
{ | ||
"name": "crowdin-api", | ||
"version": "1.1.2", | ||
"version": "2.0.0", | ||
"description": "API client for Crowdin", | ||
@@ -16,9 +16,12 @@ "repository": { | ||
"dependencies": { | ||
"request": "^2.81.0", | ||
"request-promise": "^4.2.1" | ||
"bluebird": "^3.5.0", | ||
"lodash": "^4.17.4", | ||
"request": "^2.82.0", | ||
"request-promise": "^4.2.2", | ||
"temp": "^0.8.3" | ||
}, | ||
"devDependencies": { | ||
"eslint-config-standard": "^10.2.1", | ||
"eslint-plugin-import": "^2.6.1", | ||
"eslint-plugin-node": "^5.1.0", | ||
"eslint-plugin-import": "^2.7.0", | ||
"eslint-plugin-node": "^5.1.1", | ||
"eslint-plugin-promise": "^3.5.0", | ||
@@ -29,3 +32,3 @@ "eslint-plugin-standard": "^3.0.1", | ||
"grunt-contrib-jshint": "^1.1.0", | ||
"grunt-eslint": "^20.0.0", | ||
"grunt-eslint": "^20.1.0", | ||
"grunt-jscs": "^3.0.1", | ||
@@ -32,0 +35,0 @@ "grunt-release": "^0.14.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12571
283
5
1
+ Addedbluebird@^3.5.0
+ Addedlodash@^4.17.4
+ Addedtemp@^0.8.3
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedrimraf@2.6.3(transitive)
+ Addedtemp@0.8.4(transitive)
+ Addedwrappy@1.0.2(transitive)
Updatedrequest@^2.82.0
Updatedrequest-promise@^4.2.2