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