locize-cli 11.0.0 → 12.0.0
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/CHANGELOG.md +12 -0
- package/LICENSE +1 -1
- package/README.md +1 -0
- package/dist/cjs/add.js +90 -0
- package/{bin/locize → dist/cjs/cli.js} +390 -670
- package/dist/cjs/combineSubkeyPreprocessor.js +155 -0
- package/dist/cjs/convertToDesiredFormat.js +205 -0
- package/dist/cjs/convertToFlatFormat.js +231 -0
- package/dist/cjs/copyVersion.js +60 -0
- package/dist/cjs/createBranch.js +59 -0
- package/dist/cjs/deleteBranch.js +89 -0
- package/dist/cjs/deleteNamespace.js +37 -0
- package/dist/cjs/download.js +376 -0
- package/dist/cjs/filterNamespaces.js +13 -0
- package/dist/cjs/format.js +156 -0
- package/dist/cjs/formats.js +33 -0
- package/dist/cjs/get.js +66 -0
- package/dist/cjs/getBranches.js +37 -0
- package/dist/cjs/getJob.js +37 -0
- package/dist/cjs/getProjectStats.js +37 -0
- package/dist/cjs/getRemoteLanguages.js +38 -0
- package/dist/cjs/getRemoteNamespace.js +125 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/isValidUuid.js +6 -0
- package/dist/cjs/lngs.js +215 -0
- package/dist/cjs/mapLimit.js +22 -0
- package/dist/cjs/mergeBranch.js +80 -0
- package/dist/cjs/migrate.js +239 -0
- package/dist/cjs/missing.js +162 -0
- package/dist/cjs/package.json +5 -0
- package/{parseLocalLanguage.js → dist/cjs/parseLocalLanguage.js} +135 -142
- package/dist/cjs/parseLocalLanguages.js +18 -0
- package/dist/cjs/parseLocalReference.js +11 -0
- package/dist/cjs/publishVersion.js +42 -0
- package/dist/cjs/removeUndefinedFromArrays.js +19 -0
- package/dist/cjs/removeVersion.js +42 -0
- package/dist/cjs/request.js +66 -0
- package/dist/cjs/shouldUnflatten.js +21 -0
- package/dist/cjs/sortFlatResources.js +13 -0
- package/dist/cjs/sync.js +772 -0
- package/dist/cjs/unflatten.js +81 -0
- package/dist/esm/add.js +88 -0
- package/dist/esm/cli.js +1020 -0
- package/{combineSubkeyPreprocessor.js → dist/esm/combineSubkeyPreprocessor.js} +70 -73
- package/dist/esm/convertToDesiredFormat.js +203 -0
- package/dist/esm/convertToFlatFormat.js +229 -0
- package/dist/esm/copyVersion.js +58 -0
- package/dist/esm/createBranch.js +57 -0
- package/dist/esm/deleteBranch.js +87 -0
- package/dist/esm/deleteNamespace.js +35 -0
- package/dist/esm/download.js +374 -0
- package/{filterNamespaces.js → dist/esm/filterNamespaces.js} +4 -4
- package/dist/esm/format.js +154 -0
- package/{formats.js → dist/esm/formats.js} +7 -11
- package/dist/esm/get.js +64 -0
- package/dist/esm/getBranches.js +35 -0
- package/dist/esm/getJob.js +35 -0
- package/dist/esm/getProjectStats.js +35 -0
- package/dist/esm/getRemoteLanguages.js +36 -0
- package/dist/esm/getRemoteNamespace.js +123 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/isValidUuid.js +4 -0
- package/dist/esm/lngs.js +213 -0
- package/dist/esm/mapLimit.js +20 -0
- package/dist/esm/mergeBranch.js +78 -0
- package/dist/esm/migrate.js +237 -0
- package/dist/esm/missing.js +160 -0
- package/dist/esm/parseLocalLanguage.js +194 -0
- package/dist/esm/parseLocalLanguages.js +16 -0
- package/dist/esm/parseLocalReference.js +9 -0
- package/dist/esm/publishVersion.js +40 -0
- package/{removeUndefinedFromArrays.js → dist/esm/removeUndefinedFromArrays.js} +5 -5
- package/dist/esm/removeVersion.js +40 -0
- package/dist/esm/request.js +64 -0
- package/{shouldUnflatten.js → dist/esm/shouldUnflatten.js} +7 -7
- package/dist/esm/sortFlatResources.js +11 -0
- package/dist/esm/sync.js +770 -0
- package/{unflatten.js → dist/esm/unflatten.js} +36 -34
- package/package.json +39 -18
- package/rollup.config.js +57 -0
- package/add.js +0 -105
- package/convertToDesiredFormat.js +0 -268
- package/convertToFlatFormat.js +0 -322
- package/copyVersion.js +0 -69
- package/createBranch.js +0 -61
- package/deleteBranch.js +0 -97
- package/deleteNamespace.js +0 -39
- package/download.js +0 -516
- package/format.js +0 -206
- package/get.js +0 -81
- package/getBranches.js +0 -40
- package/getJob.js +0 -40
- package/getProjectStats.js +0 -40
- package/getRemoteLanguages.js +0 -40
- package/getRemoteNamespace.js +0 -122
- package/index.js +0 -9
- package/isValidUuid.js +0 -2
- package/lngs.json +0 -211
- package/mergeBranch.js +0 -102
- package/migrate.js +0 -314
- package/missing.js +0 -169
- package/parseLocalLanguages.js +0 -22
- package/parseLocalReference.js +0 -10
- package/publishVersion.js +0 -64
- package/removeVersion.js +0 -64
- package/request.js +0 -64
- package/sortFlatResources.js +0 -9
- package/sync.js +0 -786
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { diffLines } from 'diff';
|
|
5
|
+
import convertToFlatFormat from './convertToFlatFormat.js';
|
|
6
|
+
import convertToDesiredFormat from './convertToDesiredFormat.js';
|
|
7
|
+
import sortFlatResources from './sortFlatResources.js';
|
|
8
|
+
import { reversedFileExtensionsMap as reversedFileExtensionsMap$1, acceptedFileExtensions as acceptedFileExtensions$1, fileExtensionsMap as fileExtensionsMap$1 } from './formats.js';
|
|
9
|
+
|
|
10
|
+
const fileExtensionsMap = fileExtensionsMap$1;
|
|
11
|
+
const acceptedFileExtensions = acceptedFileExtensions$1;
|
|
12
|
+
const reversedFileExtensionsMap = reversedFileExtensionsMap$1;
|
|
13
|
+
|
|
14
|
+
const getFiles = (srcpath) => {
|
|
15
|
+
let files = [];
|
|
16
|
+
fs.readdirSync(srcpath).forEach((file) => {
|
|
17
|
+
if (fs.statSync(path.join(srcpath, file)).isDirectory()) {
|
|
18
|
+
files = files.concat(getFiles(path.join(srcpath, file)));
|
|
19
|
+
} else if (acceptedFileExtensions.indexOf(path.extname(file)) > -1) {
|
|
20
|
+
files.push(path.join(srcpath, file));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return files
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
async function readLocalFile (opt, fPath) {
|
|
27
|
+
const fExt = path.extname(fPath);
|
|
28
|
+
const namespace = path.basename(fPath, fExt);
|
|
29
|
+
const splitted = fPath.split(path.sep);
|
|
30
|
+
const lng = splitted[splitted.length - 2];
|
|
31
|
+
const data = await fs.promises.readFile(fPath);
|
|
32
|
+
const stat = await fs.promises.stat(fPath);
|
|
33
|
+
return {
|
|
34
|
+
namespace,
|
|
35
|
+
path: fPath,
|
|
36
|
+
extension: fExt,
|
|
37
|
+
original: data.toString(),
|
|
38
|
+
language: lng,
|
|
39
|
+
mtime: stat.mtime
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function readLocalFiles (opt, filePaths) {
|
|
44
|
+
return await Promise.all(filePaths.map(f => readLocalFile(opt, f)))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function convertAllFilesToFlatFormat (opt, files) {
|
|
48
|
+
return await Promise.all(files.map(async file => {
|
|
49
|
+
if (fileExtensionsMap[file.extension].indexOf(opt.format) < 0) {
|
|
50
|
+
throw new Error(`Format mismatch! Found ${fileExtensionsMap[file.extension][0]} but requested ${opt.format}!`)
|
|
51
|
+
}
|
|
52
|
+
let content;
|
|
53
|
+
try {
|
|
54
|
+
content = await convertToFlatFormat(opt, file.original);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
err.message = 'Invalid content for "' + opt.format + '" format!\n' + (err.message || '') + '\n' + file.path;
|
|
57
|
+
throw err
|
|
58
|
+
}
|
|
59
|
+
file.content = sortFlatResources(content);
|
|
60
|
+
return file
|
|
61
|
+
}))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function convertAllFilesToDesiredFormat (opt, files) {
|
|
65
|
+
return await Promise.all(files.map(async file => {
|
|
66
|
+
let res;
|
|
67
|
+
try {
|
|
68
|
+
res = await convertToDesiredFormat(opt, file.namespace, file.language, file.content, file.mtime);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
err.message = 'Invalid content for "' + opt.format + '" format!\n' + (err.message || '');
|
|
71
|
+
throw err
|
|
72
|
+
}
|
|
73
|
+
res = (opt.format !== 'xlsx' && !res.endsWith('\n')) ? (res + '\n') : res;
|
|
74
|
+
file.converted = res;
|
|
75
|
+
return file
|
|
76
|
+
}))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function writeLocalFile (opt, file) {
|
|
80
|
+
if (file.converted === file.original) {
|
|
81
|
+
console.log(colors.grey(`${file.path} unchanged`));
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
const d = diffLines(file.original, file.converted);
|
|
85
|
+
d.forEach((part) => {
|
|
86
|
+
const color = part.added ? 'green' : part.removed ? 'red' : 'grey';
|
|
87
|
+
console.log(part.value[color]);
|
|
88
|
+
});
|
|
89
|
+
console.log(colors.yellow(`reformatting ${file.path}...`));
|
|
90
|
+
if (opt.dry) {
|
|
91
|
+
console.log(colors.yellow(`would have reformatted ${file.path}...`));
|
|
92
|
+
return true
|
|
93
|
+
}
|
|
94
|
+
const fileContent = (opt.format !== 'xlsx' && !file.converted.endsWith('\n')) ? (file.converted + '\n') : file.converted;
|
|
95
|
+
await fs.promises.writeFile(file.path, fileContent);
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function writeLocalFiles (opt, files) {
|
|
100
|
+
return await Promise.all(files.map(f => writeLocalFile(opt, f)))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function processFiles (opt, filePaths) {
|
|
104
|
+
const orgFiles = await readLocalFiles(opt, filePaths);
|
|
105
|
+
if (!opt.format) {
|
|
106
|
+
if (orgFiles.length === 0) {
|
|
107
|
+
throw new Error('Please provide a format!')
|
|
108
|
+
}
|
|
109
|
+
opt.format = fileExtensionsMap[orgFiles[0].extension][0];
|
|
110
|
+
console.log(colors.bgYellow(`No format argument was passed, so guessing "${opt.format}" format.`));
|
|
111
|
+
}
|
|
112
|
+
const files = await convertAllFilesToFlatFormat(opt, orgFiles);
|
|
113
|
+
opt.getNamespace = async (o, lng, ns) => {
|
|
114
|
+
const foundOrgFile = orgFiles.find((f) => f.namespace === ns && f.language === lng);
|
|
115
|
+
if (!foundOrgFile) {
|
|
116
|
+
throw new Error(`No file found for language "${lng}" and namespace "${ns}" locally!`)
|
|
117
|
+
}
|
|
118
|
+
return { content: foundOrgFile.content, mtime: foundOrgFile.mtime }
|
|
119
|
+
};
|
|
120
|
+
files.forEach((f) => {
|
|
121
|
+
if (f.content) {
|
|
122
|
+
Object.keys(f.content).forEach((k) => {
|
|
123
|
+
if (f.content[k] && typeof f.content[k] === 'object' && f.content[k].value !== undefined) {
|
|
124
|
+
f.content[k] = f.content[k].value;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
const convertedFiles = await convertAllFilesToDesiredFormat(opt, files);
|
|
130
|
+
return await writeLocalFiles(opt, convertedFiles)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function format (opt) {
|
|
134
|
+
if (opt.format && !reversedFileExtensionsMap[opt.format]) {
|
|
135
|
+
throw new Error(`${opt.format} is not a valid format!`)
|
|
136
|
+
}
|
|
137
|
+
const stat = await fs.promises.lstat(opt.fileOrDirectory);
|
|
138
|
+
const isDirectory = stat.isDirectory();
|
|
139
|
+
let filePaths = [];
|
|
140
|
+
if (isDirectory) {
|
|
141
|
+
try {
|
|
142
|
+
filePaths = getFiles(opt.fileOrDirectory);
|
|
143
|
+
} catch (err) {}
|
|
144
|
+
} else {
|
|
145
|
+
filePaths = [opt.fileOrDirectory];
|
|
146
|
+
}
|
|
147
|
+
const writeResults = await processFiles(opt, filePaths);
|
|
148
|
+
console.log(colors.green('FINISHED'));
|
|
149
|
+
if (opt.dry && writeResults.find((wr) => !!wr)) {
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { format as default };
|
|
@@ -15,19 +15,15 @@ const fileExtensionsMap = {
|
|
|
15
15
|
'.php': ['laravel'],
|
|
16
16
|
'.properties': ['properties'],
|
|
17
17
|
'.xcstrings': ['xcstrings']
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
|
|
20
|
-
const acceptedFileExtensions = Object.keys(fileExtensionsMap)
|
|
20
|
+
const acceptedFileExtensions = Object.keys(fileExtensionsMap);
|
|
21
21
|
|
|
22
|
-
const reversedFileExtensionsMap = {}
|
|
22
|
+
const reversedFileExtensionsMap = {};
|
|
23
23
|
acceptedFileExtensions.forEach((ext) => {
|
|
24
24
|
fileExtensionsMap[ext].forEach((format) => {
|
|
25
|
-
reversedFileExtensionsMap[format] = ext
|
|
26
|
-
})
|
|
27
|
-
})
|
|
25
|
+
reversedFileExtensionsMap[format] = ext;
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
fileExtensionsMap,
|
|
31
|
-
acceptedFileExtensions,
|
|
32
|
-
reversedFileExtensionsMap
|
|
33
|
-
}
|
|
29
|
+
export { acceptedFileExtensions, fileExtensionsMap, reversedFileExtensionsMap };
|
package/dist/esm/get.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import request from './request.js';
|
|
3
|
+
import flatten from 'flat';
|
|
4
|
+
|
|
5
|
+
const get = async (opt) => {
|
|
6
|
+
const url = `${opt.apiEndpoint}/{{projectId}}/{{version}}/{{lng}}/{{ns}}`
|
|
7
|
+
.replace('{{projectId}}', opt.projectId)
|
|
8
|
+
.replace('{{ver}}', opt.version)
|
|
9
|
+
.replace('{{version}}', opt.version)
|
|
10
|
+
.replace('{{language}}', opt.language)
|
|
11
|
+
.replace('{{lng}}', opt.language)
|
|
12
|
+
.replace('{{ns}}', opt.namespace)
|
|
13
|
+
.replace('{{namespace}}', opt.namespace);
|
|
14
|
+
|
|
15
|
+
if (opt.key && opt.key.indexOf(',') > 0 && opt.key.indexOf(' ') < 0) {
|
|
16
|
+
opt.keys = opt.key.split(',');
|
|
17
|
+
delete opt.key;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const { res, obj, err } = await request(`${url}${opt.cdnType === 'standard' ? '?cache=no' : ''}`, {
|
|
21
|
+
method: 'get'
|
|
22
|
+
});
|
|
23
|
+
if (err) {
|
|
24
|
+
console.log(colors.red(`get failed for ${opt.key || (opt.keys && opt.keys.join(', '))} from ${opt.version}/${opt.language}/${opt.namespace}...`));
|
|
25
|
+
throw err
|
|
26
|
+
}
|
|
27
|
+
const ignore404 = res.status === 404 && opt.cdnType === 'standard';
|
|
28
|
+
if (res.status >= 300 && !ignore404) {
|
|
29
|
+
console.error(colors.red(res.statusText + ' (' + res.status + ')'));
|
|
30
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
31
|
+
}
|
|
32
|
+
const flatObj = flatten(ignore404 ? {} : obj);
|
|
33
|
+
if (opt.key) {
|
|
34
|
+
if (!flatObj[opt.key]) {
|
|
35
|
+
console.error(colors.red(`${opt.key} not found in ${opt.version}/${opt.language}/${opt.namespace} => ${JSON.stringify(obj, null, 2)}`));
|
|
36
|
+
throw new Error(`${opt.key} not found in ${opt.version}/${opt.language}/${opt.namespace} => ${JSON.stringify(obj, null, 2)}`)
|
|
37
|
+
}
|
|
38
|
+
console.log(flatObj[opt.key]);
|
|
39
|
+
}
|
|
40
|
+
if (opt.keys) {
|
|
41
|
+
const ret = {};
|
|
42
|
+
const retWitAllKeys = {};
|
|
43
|
+
opt.keys.forEach((k) => {
|
|
44
|
+
if (flatObj[k] !== undefined) {
|
|
45
|
+
ret[k] = flatObj[k];
|
|
46
|
+
}
|
|
47
|
+
retWitAllKeys[k] = flatObj[k];
|
|
48
|
+
});
|
|
49
|
+
const retKeys = Object.keys(ret);
|
|
50
|
+
if (retKeys.length === 0) {
|
|
51
|
+
console.error(colors.red(`${opt.keys.join(', ')} not found in ${opt.version}/${opt.language}/${opt.namespace} => ${JSON.stringify(obj, null, 2)}`));
|
|
52
|
+
throw new Error(`${opt.keys.join(', ')} not found in ${opt.version}/${opt.language}/${opt.namespace} => ${JSON.stringify(obj, null, 2)}`)
|
|
53
|
+
}
|
|
54
|
+
if (console.table) {
|
|
55
|
+
console.table(retWitAllKeys);
|
|
56
|
+
} else {
|
|
57
|
+
opt.keys.forEach((k) => {
|
|
58
|
+
console.log(`${k}\t=>\t${ret[k] || ''}`);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { get as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import request from './request.js';
|
|
3
|
+
|
|
4
|
+
const getBranches = async (opt) => {
|
|
5
|
+
const { res, obj, err } = await request(opt.apiEndpoint + '/branches/' + opt.projectId, {
|
|
6
|
+
method: 'get',
|
|
7
|
+
headers: {
|
|
8
|
+
Authorization: opt.apiKey
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
13
|
+
console.log(colors.red('getting branches failed...'));
|
|
14
|
+
if (err) {
|
|
15
|
+
console.error(colors.red(err.message));
|
|
16
|
+
throw err
|
|
17
|
+
}
|
|
18
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
19
|
+
console.error(colors.red((obj.errorMessage || obj.message)));
|
|
20
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (res.status === 404) {
|
|
24
|
+
console.error(colors.yellow(res.statusText + ' (' + res.status + ')'));
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
if (res.status >= 300) {
|
|
28
|
+
console.error(colors.red(res.statusText + ' (' + res.status + ')'));
|
|
29
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
30
|
+
}
|
|
31
|
+
console.log(colors.green('getting branches successful'));
|
|
32
|
+
return obj
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { getBranches as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import request from './request.js';
|
|
3
|
+
|
|
4
|
+
const getJob = async (opt, jobId) => {
|
|
5
|
+
const { res, obj, err } = await request(opt.apiEndpoint + '/jobs/' + opt.projectId + '/' + jobId, {
|
|
6
|
+
method: 'get',
|
|
7
|
+
headers: {
|
|
8
|
+
Authorization: opt.apiKey
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
13
|
+
console.log(colors.red('getting job failed...'));
|
|
14
|
+
if (err) {
|
|
15
|
+
console.error(colors.red(err.message));
|
|
16
|
+
throw err
|
|
17
|
+
}
|
|
18
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
19
|
+
console.error(colors.red((obj.errorMessage || obj.message)));
|
|
20
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (res.status === 404) {
|
|
24
|
+
console.error(colors.yellow(res.statusText + ' (' + res.status + ')'));
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
if (res.status >= 300) {
|
|
28
|
+
console.error(colors.red(res.statusText + ' (' + res.status + ')'));
|
|
29
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
30
|
+
}
|
|
31
|
+
console.log(colors.green('getting job successful'));
|
|
32
|
+
return obj
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { getJob as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import request from './request.js';
|
|
3
|
+
|
|
4
|
+
const getProjectStats = async (opt) => {
|
|
5
|
+
const { res, obj, err } = await request(opt.apiEndpoint + '/stats/project/' + opt.projectId, {
|
|
6
|
+
method: 'get',
|
|
7
|
+
headers: {
|
|
8
|
+
Authorization: opt.apiKey
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
13
|
+
console.log(colors.red('getting job failed...'));
|
|
14
|
+
if (err) {
|
|
15
|
+
console.error(colors.red(err.message));
|
|
16
|
+
throw err
|
|
17
|
+
}
|
|
18
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
19
|
+
console.error(colors.red((obj.errorMessage || obj.message)));
|
|
20
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (res.status === 404) {
|
|
24
|
+
console.error(colors.yellow(res.statusText + ' (' + res.status + ')'));
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
if (res.status >= 300) {
|
|
28
|
+
console.error(colors.red(res.statusText + ' (' + res.status + ')'));
|
|
29
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
30
|
+
}
|
|
31
|
+
console.log(colors.green('getting project stats successful'));
|
|
32
|
+
return obj
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { getProjectStats as default };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import request from './request.js';
|
|
2
|
+
|
|
3
|
+
const getRemoteLanguages = async (opt) => {
|
|
4
|
+
const { res, obj } = await request(opt.apiEndpoint + '/languages/' + opt.projectId + '?ts=' + Date.now() + (opt.cdnType === 'standard' ? '&cache=no' : ''), {
|
|
5
|
+
method: 'get'
|
|
6
|
+
});
|
|
7
|
+
if ((obj && (obj.errorMessage || obj.message))) {
|
|
8
|
+
if (res && res.statusText && res.status) {
|
|
9
|
+
throw new Error(res.statusText + ' (' + res.status + ') | ' + (obj.errorMessage || obj.message))
|
|
10
|
+
}
|
|
11
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
12
|
+
}
|
|
13
|
+
if (res.status >= 300) throw new Error(res.statusText + ' (' + res.status + ')')
|
|
14
|
+
|
|
15
|
+
if (Object.keys(obj).length === 0) {
|
|
16
|
+
throw new Error('Project with id "' + opt.projectId + '" not found!')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const lngs = Object.keys(obj);
|
|
20
|
+
let foundRefLng = null;
|
|
21
|
+
lngs.forEach((l) => {
|
|
22
|
+
if (obj[l].isReferenceLanguage) foundRefLng = l;
|
|
23
|
+
});
|
|
24
|
+
if (!foundRefLng) {
|
|
25
|
+
throw new Error('Reference language for project with id "' + opt.projectId + '" not found!')
|
|
26
|
+
}
|
|
27
|
+
opt.referenceLanguage = foundRefLng;
|
|
28
|
+
|
|
29
|
+
// reflng first
|
|
30
|
+
lngs.splice(lngs.indexOf(opt.referenceLanguage), 1);
|
|
31
|
+
lngs.unshift(opt.referenceLanguage);
|
|
32
|
+
|
|
33
|
+
return lngs
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { getRemoteLanguages as default };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import request from './request.js';
|
|
2
|
+
import flatten from 'flat';
|
|
3
|
+
import sortFlatResources from './sortFlatResources.js';
|
|
4
|
+
|
|
5
|
+
const getRandomDelay = (delayFrom, delayTo) => Math.floor(Math.random() * delayTo) + delayFrom;
|
|
6
|
+
|
|
7
|
+
function onlyKeysFlat (resources, prefix, ret) {
|
|
8
|
+
ret = ret || {};
|
|
9
|
+
if (!resources) return ret
|
|
10
|
+
Object.keys(resources).forEach((k) => {
|
|
11
|
+
if (typeof resources[k] === 'string' || !resources[k] || typeof resources[k].value === 'string') {
|
|
12
|
+
if (prefix) {
|
|
13
|
+
ret[prefix + '.' + k] = resources[k];
|
|
14
|
+
} else {
|
|
15
|
+
ret[k] = resources[k];
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
onlyKeysFlat(resources[k], prefix ? prefix + '.' + k : k, ret);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return ret
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
25
|
+
|
|
26
|
+
const pullNamespacePaged = async (opt, lng, ns, next = '', retry = 0) => {
|
|
27
|
+
const { res, obj, err } = await request(opt.apiEndpoint + '/pull/' + opt.projectId + '/' + opt.version + '/' + lng + '/' + ns + '?' + 'next=' + next + ((opt.raw || opt.overriddenOnly) ? '&raw=true' : '') + '&ts=' + Date.now(), {
|
|
28
|
+
method: 'get',
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: opt.apiKey
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
if (err) throw err
|
|
34
|
+
if (res.status >= 300) {
|
|
35
|
+
if (retry < 3 && res.status !== 401) {
|
|
36
|
+
await sleep(getRandomDelay(3000, 10000));
|
|
37
|
+
return await pullNamespacePaged(opt, lng, ns, next, retry + 1)
|
|
38
|
+
}
|
|
39
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
40
|
+
if (res.statusText && res.status) {
|
|
41
|
+
throw new Error(res.statusText + ' (' + res.status + ') | ' + (obj.errorMessage || obj.message))
|
|
42
|
+
}
|
|
43
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
44
|
+
}
|
|
45
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let resultObj = obj;
|
|
49
|
+
if (opt.overriddenOnly && obj) {
|
|
50
|
+
const newObj = {};
|
|
51
|
+
Object.keys(obj).forEach((k) => {
|
|
52
|
+
if (obj[k].overrides !== undefined) {
|
|
53
|
+
if (opt.raw) {
|
|
54
|
+
newObj[k] = obj[k];
|
|
55
|
+
} else {
|
|
56
|
+
newObj[k] = obj[k].value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
resultObj = newObj;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
result: opt.raw ? sortFlatResources(onlyKeysFlat(resultObj)) : sortFlatResources(flatten(resultObj)),
|
|
65
|
+
next: res.headers.get('x-next-page'),
|
|
66
|
+
lastModified: res.headers.get('last-modified') ? new Date(res.headers.get('last-modified')) : undefined
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const pullNamespace = async (opt, lng, ns) => {
|
|
71
|
+
const ret = {};
|
|
72
|
+
let lastModified = new Date(2000, 0, 1);
|
|
73
|
+
let next = '';
|
|
74
|
+
while (true) {
|
|
75
|
+
const info = await pullNamespacePaged(opt, lng, ns, next);
|
|
76
|
+
Object.keys(info.result).forEach((k) => {
|
|
77
|
+
ret[k] = info.result[k];
|
|
78
|
+
});
|
|
79
|
+
if (info.lastModified && info.lastModified.getTime() > (lastModified ? lastModified.getTime() : 0)) {
|
|
80
|
+
lastModified = info.lastModified;
|
|
81
|
+
}
|
|
82
|
+
if (info.next) {
|
|
83
|
+
next = info.next;
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
return { result: ret, lastModified }
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getRemoteNamespace = async (opt, lng, ns) => {
|
|
92
|
+
if (opt.unpublished) {
|
|
93
|
+
const { result, lastModified } = await pullNamespace(opt, lng, ns);
|
|
94
|
+
return { result, lastModified }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { res, obj, err } = await request(opt.apiEndpoint + (opt.isPrivate ? '/private' : '') + '/' + opt.projectId + '/' + opt.version + '/' + lng + '/' + ns + '?ts=' + Date.now() + (opt.cdnType === 'standard' ? '&cache=no' : ''), {
|
|
98
|
+
method: 'get',
|
|
99
|
+
headers: opt.isPrivate
|
|
100
|
+
? {
|
|
101
|
+
Authorization: opt.apiKey
|
|
102
|
+
}
|
|
103
|
+
: undefined
|
|
104
|
+
});
|
|
105
|
+
if (err) throw err
|
|
106
|
+
const ignore404 = res.status === 404 && opt.cdnType === 'standard';
|
|
107
|
+
if (ignore404) return { result: {}, lastModified: undefined }
|
|
108
|
+
if (res.status >= 300) {
|
|
109
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
110
|
+
if (res.statusText && res.status) {
|
|
111
|
+
throw new Error(res.statusText + ' (' + res.status + ') | ' + (obj.errorMessage || obj.message))
|
|
112
|
+
}
|
|
113
|
+
throw new Error((obj.errorMessage || obj.message))
|
|
114
|
+
}
|
|
115
|
+
throw new Error(res.statusText + ' (' + res.status + ')')
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
result: sortFlatResources(flatten(obj)),
|
|
119
|
+
lastModified: res.headers.get('last-modified') ? new Date(res.headers.get('last-modified')) : undefined
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export { getRemoteNamespace as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as add } from './add.js';
|
|
2
|
+
export { default as get } from './get.js';
|
|
3
|
+
export { default as download } from './download.js';
|
|
4
|
+
export { default as migrate } from './migrate.js';
|
|
5
|
+
export { default as sync } from './sync.js';
|
|
6
|
+
export { default as publishVersion } from './publishVersion.js';
|
|
7
|
+
export { default as copyVersion } from './copyVersion.js';
|
|
8
|
+
export { default as createBranch } from './createBranch.js';
|
|
9
|
+
export { default as deleteBranch } from './deleteBranch.js';
|
|
10
|
+
export { default as deleteNamespace } from './deleteNamespace.js';
|
|
11
|
+
export { default as format } from './format.js';
|
|
12
|
+
export { default as getBranches } from './getBranches.js';
|
|
13
|
+
export { default as getJob } from './getJob.js';
|
|
14
|
+
export { default as mergeBranch } from './mergeBranch.js';
|
|
15
|
+
export { default as missing } from './missing.js';
|
|
16
|
+
export { default as removeVersion } from './removeVersion.js';
|