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,194 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { mkdirp } from 'mkdirp';
4
+ import convertToFlatFormat from './convertToFlatFormat.js';
5
+ import { fileExtensionsMap as fileExtensionsMap$1, acceptedFileExtensions as acceptedFileExtensions$1 } from './formats.js';
6
+ import xcstrings2locize from 'locize-xcstrings/cjs/xcstrings2locize';
7
+
8
+ const fileExtensionsMap = fileExtensionsMap$1;
9
+ const acceptedFileExtensions = acceptedFileExtensions$1;
10
+
11
+ const getFiles = (srcpath) => {
12
+ return fs.readdirSync(srcpath).filter((file) => {
13
+ return !fs.statSync(path.join(srcpath, file)).isDirectory()
14
+ }).filter((file) => acceptedFileExtensions.indexOf(path.extname(file)) > -1)
15
+ };
16
+
17
+ const getDirectories = (srcpath) => {
18
+ return fs.readdirSync(srcpath).filter((file) => {
19
+ return fs.statSync(path.join(srcpath, file)).isDirectory()
20
+ })
21
+ };
22
+
23
+ const parseLocalLanguage = async (opt, lng) => {
24
+ const hasNamespaceInPath = opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) > -1;
25
+ const filledLngMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, opt.format === 'xcstrings' ? '' : lng);
26
+ let firstPartLngMask, lastPartLngMask;
27
+ if (opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`) > opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`)) {
28
+ const secondPartMask = opt.pathMask.substring(opt.pathMask.lastIndexOf(path.sep) + 1);
29
+ firstPartLngMask = secondPartMask.substring(0, secondPartMask.indexOf(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`));
30
+ lastPartLngMask = secondPartMask.substring(secondPartMask.indexOf(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`) + `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`.length);
31
+ }
32
+ let lngPath;
33
+ if (filledLngMask.lastIndexOf(path.sep) > 0) {
34
+ lngPath = filledLngMask.substring(0, filledLngMask.lastIndexOf(path.sep));
35
+ }
36
+ if (!opt.dry && lngPath && lngPath.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) < 0) mkdirp.sync(path.join(opt.path, lngPath));
37
+
38
+ let files = [];
39
+ try {
40
+ if (lngPath) {
41
+ if (lngPath.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) > -1) {
42
+ const firstPart = lngPath.substring(0, lngPath.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`));
43
+ const lastPart = lngPath.substring(lngPath.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) + `${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`.length);
44
+ let additionalSubDirsLeft = '';
45
+ let additionalSubDirs = '';
46
+ const splittedP = lngPath.split(path.sep);
47
+ const foundSplitted = splittedP.find((s) => s.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) > -1);
48
+ const foundSplittedIndex = splittedP.indexOf(foundSplitted);
49
+ if (splittedP.length > 2) {
50
+ additionalSubDirsLeft = splittedP.slice(0, foundSplittedIndex).join(path.sep);
51
+ additionalSubDirs = splittedP.slice(foundSplittedIndex + 1).join(path.sep);
52
+ }
53
+ let dirs = getDirectories(path.join(opt.path, additionalSubDirsLeft));
54
+ if (additionalSubDirs === '') {
55
+ dirs = dirs.filter((d) => d.startsWith(firstPart) && d.endsWith(lastPart));
56
+ }
57
+ dirs.forEach((d) => {
58
+ if (additionalSubDirs && fs.statSync(path.join(opt.path, additionalSubDirsLeft, d)).isDirectory()) {
59
+ let directoryExists = false;
60
+ try {
61
+ directoryExists = fs.statSync(path.join(opt.path, additionalSubDirsLeft, d, additionalSubDirs)).isDirectory();
62
+ } catch (e) {}
63
+ if (directoryExists) {
64
+ let subFls = getFiles(path.join(opt.path, additionalSubDirsLeft, d, additionalSubDirs));
65
+ if (firstPartLngMask || lastPartLngMask) subFls = subFls.filter((f) => path.basename(f, path.extname(f)) === `${firstPartLngMask}${lng}${lastPartLngMask}`);
66
+
67
+ subFls = subFls.filter((f) => {
68
+ const a = path.join(additionalSubDirsLeft, d, additionalSubDirs, path.basename(f, path.extname(f)));
69
+ const startIndexOfNs = filledLngMask.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`);
70
+ if (startIndexOfNs === -1) return true
71
+ const afterNs = filledLngMask.substring(startIndexOfNs + `${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`.length);
72
+ const nsName = a.substring(startIndexOfNs, a.indexOf(afterNs));
73
+ const b = filledLngMask.replace(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`, nsName);
74
+ return a === b
75
+ });
76
+
77
+ files = files.concat(subFls.map((f) => `${additionalSubDirsLeft ? additionalSubDirsLeft + path.sep : ''}${d}${path.sep}${additionalSubDirs}${path.sep}${f}`));
78
+ }
79
+ } else {
80
+ const fls = getFiles(path.join(opt.path, additionalSubDirsLeft, d)).filter((f) => path.basename(f, path.extname(f)) === `${firstPartLngMask}${lng}${lastPartLngMask}`);
81
+ files = files.concat(fls.map((f) => `${additionalSubDirsLeft ? additionalSubDirsLeft + path.sep : ''}${d}${path.sep}${f}`));
82
+ }
83
+ });
84
+ } else {
85
+ files = getFiles(path.join(opt.path, lngPath));
86
+ }
87
+ } else {
88
+ files = getFiles(opt.path);
89
+ // filter lng files...
90
+ const lngIndex = filledLngMask.indexOf(lng);
91
+ const lngLeftLength = filledLngMask.length - lngIndex;
92
+ files = files.filter((f) => { // {{language}} can be left or right of {{namespace}}
93
+ if (opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`) < opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`)) {
94
+ return f.indexOf(lng) === lngIndex
95
+ }
96
+ return (path.basename(f, path.extname(f)).length - f.indexOf(lng)) === lngLeftLength
97
+ });
98
+ }
99
+ } catch (err) {}
100
+
101
+ // Async map logic using Promise.all
102
+ const results = await Promise.all(files.map(async (fileOrig) => {
103
+ let file = fileOrig;
104
+ let dirPath;
105
+ if (file.lastIndexOf(path.sep) > 0) {
106
+ dirPath = file.substring(0, file.lastIndexOf(path.sep));
107
+ file = file.substring(file.lastIndexOf(path.sep) + 1);
108
+ }
109
+ const fExt = path.extname(file);
110
+ let namespace = path.basename(file, fExt);
111
+ const nsMask = `${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
112
+ const filledNsMask = lngPath && lngPath.indexOf(nsMask) > -1 ? filledLngMask : filledLngMask.substring(filledLngMask.lastIndexOf(path.sep) + 1);
113
+ const startNsIndex = filledNsMask.indexOf(nsMask);
114
+ let restNsMask = filledNsMask.substring((startNsIndex || 0) + nsMask.length);
115
+ namespace = namespace.substring(startNsIndex || 0, namespace.lastIndexOf(restNsMask));
116
+ if (lngPath && lngPath.indexOf(nsMask) > -1) {
117
+ restNsMask = restNsMask.substring(0, restNsMask.lastIndexOf(path.sep));
118
+ if (dirPath.indexOf(restNsMask) > 0) {
119
+ namespace = dirPath.substring(filledNsMask.indexOf(nsMask), dirPath.indexOf(restNsMask));
120
+ } else {
121
+ namespace = dirPath.substring(filledNsMask.indexOf(nsMask));
122
+ }
123
+ } else if (!hasNamespaceInPath && startNsIndex < 0) {
124
+ namespace = opt.namespace;
125
+ }
126
+ let fPath = path.join(opt.path, lngPath || '', file);
127
+ if (dirPath && lngPath.indexOf(nsMask) > -1) {
128
+ fPath = path.join(opt.path, dirPath.replace(nsMask, namespace), file);
129
+ }
130
+ if (!namespace) throw new Error(`namespace could not be found in ${fPath}`)
131
+ if (opt.namespaces && opt.namespaces.indexOf(namespace) < 0) return undefined
132
+ if (opt.namespace && opt.namespace !== namespace) return undefined
133
+ const data = await fs.promises.readFile(fPath);
134
+ if (fileExtensionsMap[fExt].indexOf(opt.format) < 0) {
135
+ throw new Error(`Format mismatch! Found ${fileExtensionsMap[fExt][0]} but requested ${opt.format}!`)
136
+ }
137
+ if (opt.namespace) {
138
+ let hasNamespaceInPathPask = !opt.pathMask || !opt.pathMaskInterpolationPrefix || !opt.pathMaskInterpolationSuffix;
139
+ hasNamespaceInPathPask = !hasNamespaceInPathPask && opt.pathMask.indexOf(`${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`) > -1;
140
+ if (!hasNamespaceInPathPask && namespace === lng) {
141
+ namespace = opt.namespace;
142
+ }
143
+ }
144
+ if (opt.format === 'xcstrings') {
145
+ try {
146
+ const content = xcstrings2locize(data);
147
+ const stat = await fs.promises.stat(fPath);
148
+ return Object.keys(content.resources).map((l) => ({
149
+ namespace,
150
+ path: fPath,
151
+ extension: fExt,
152
+ content: content.resources[l],
153
+ language: l,
154
+ mtime: stat.mtime
155
+ }))
156
+ } catch (err) {
157
+ err.message = 'Invalid content for "' + opt.format + '" format!\n' + (err.message || '');
158
+ err.message += '\n' + fPath;
159
+ throw err
160
+ }
161
+ } else {
162
+ let content;
163
+ try {
164
+ content = await convertToFlatFormat(opt, data, lng);
165
+ } catch (err) {
166
+ err.message = 'Invalid content for "' + opt.format + '" format!\n' + (err.message || '');
167
+ err.message += '\n' + fPath;
168
+ throw err
169
+ }
170
+ const stat = await fs.promises.stat(fPath);
171
+ return {
172
+ namespace,
173
+ path: fPath,
174
+ extension: fExt,
175
+ content,
176
+ language: lng,
177
+ mtime: stat.mtime
178
+ }
179
+ }
180
+ }));
181
+
182
+ // xcstrings, returns array in array
183
+ const r = results.filter((r) => r !== undefined).reduce((prev, cur) => {
184
+ if (Array.isArray(cur)) {
185
+ prev = prev.concat(cur);
186
+ } else {
187
+ prev.push(cur);
188
+ }
189
+ return prev
190
+ }, []);
191
+ return r
192
+ };
193
+
194
+ export { parseLocalLanguage as default };
@@ -0,0 +1,16 @@
1
+ import parseLocalLanguage from './parseLocalLanguage.js';
2
+ import filterNamespaces from './filterNamespaces.js';
3
+
4
+ const parseLocalLanguages = async (opt, lngs) => {
5
+ let res = [];
6
+ for (const lng of lngs) {
7
+ if (opt.language && (lng !== opt.language && lng !== opt.referenceLanguage)) {
8
+ continue
9
+ }
10
+ const nss = await parseLocalLanguage(opt, lng);
11
+ res = res.concat(filterNamespaces(opt, nss));
12
+ }
13
+ return res
14
+ };
15
+
16
+ export { parseLocalLanguages as default };
@@ -0,0 +1,9 @@
1
+ import parseLocalLanguage from './parseLocalLanguage.js';
2
+ import filterNamespaces from './filterNamespaces.js';
3
+
4
+ const parseLocalReference = async (opt) => {
5
+ const nss = await parseLocalLanguage(opt, opt.referenceLanguage);
6
+ return filterNamespaces(opt, nss).filter((n) => n.language === opt.referenceLanguage)
7
+ };
8
+
9
+ export { parseLocalReference as default };
@@ -0,0 +1,40 @@
1
+ import colors from 'colors';
2
+ import request from './request.js';
3
+ import getJob from './getJob.js';
4
+
5
+ const publishVersion = async (opt) => {
6
+ const { res, obj } = await request(opt.apiEndpoint + '/publish/' + opt.projectId + '/' + opt.version + (opt.tenants ? '?tenants=true' : ''), {
7
+ method: 'post',
8
+ headers: {
9
+ Authorization: opt.apiKey
10
+ }
11
+ });
12
+ if (obj && (obj.errorMessage || obj.message)) {
13
+ console.log(colors.red(`publishing failed for ${opt.version}...`));
14
+ throw new Error(obj.errorMessage || obj.message)
15
+ }
16
+ if (res.status >= 300) {
17
+ console.error(colors.red(res.statusText + ' (' + res.status + ')'));
18
+ throw new Error(res.statusText + ' (' + res.status + ')')
19
+ }
20
+ if (!obj || !obj.jobId) {
21
+ console.error(colors.red('No jobId! Something went wrong!'));
22
+ throw new Error('No jobId! Something went wrong!')
23
+ }
24
+ // Poll for job completion
25
+ while (true) {
26
+ const job = await getJob(opt, obj.jobId);
27
+ if (job && !job.timeouted) {
28
+ await new Promise(resolve => setTimeout(resolve, 2000));
29
+ continue
30
+ }
31
+ if (job && job.timeouted) {
32
+ console.error(colors.red('Job timeouted!'));
33
+ throw new Error('Job timeouted!')
34
+ }
35
+ break
36
+ }
37
+ console.log(colors.green(`publishing for ${opt.version} succesfully requested`));
38
+ };
39
+
40
+ export { publishVersion as default };
@@ -2,16 +2,16 @@
2
2
  function removeUndefinedFromArrays (obj) {
3
3
  if (!obj) return obj
4
4
 
5
- const propNames = Object.keys(obj)
5
+ const propNames = Object.keys(obj);
6
6
  propNames.forEach((propName) => {
7
7
  if (Array.isArray(obj[propName]) && obj[propName][0] === undefined) {
8
- obj[propName].shift()
8
+ obj[propName].shift();
9
9
  } else if (typeof obj[propName] === 'object') {
10
- removeUndefinedFromArrays(obj[propName])
10
+ removeUndefinedFromArrays(obj[propName]);
11
11
  }
12
- })
12
+ });
13
13
 
14
14
  return obj
15
15
  }
16
16
 
17
- module.exports = removeUndefinedFromArrays
17
+ export { removeUndefinedFromArrays as default };
@@ -0,0 +1,40 @@
1
+ import colors from 'colors';
2
+ import request from './request.js';
3
+ import getJob from './getJob.js';
4
+
5
+ const removeVersion = async (opt) => {
6
+ const { res, obj } = await request(opt.apiEndpoint + '/version/' + opt.projectId + '/' + opt.version, {
7
+ method: 'delete',
8
+ headers: {
9
+ Authorization: opt.apiKey
10
+ }
11
+ });
12
+ if (obj && (obj.errorMessage || obj.message)) {
13
+ console.log(colors.red(`remove failed for version ${opt.version}...`));
14
+ throw new Error(obj.errorMessage || obj.message)
15
+ }
16
+ if (res.status >= 300) {
17
+ console.error(colors.red(res.statusText + ' (' + res.status + ')'));
18
+ throw new Error(res.statusText + ' (' + res.status + ')')
19
+ }
20
+ if (!obj || !obj.jobId) {
21
+ console.error(colors.red('No jobId! Something went wrong!'));
22
+ throw new Error('No jobId! Something went wrong!')
23
+ }
24
+ // Poll for job completion
25
+ while (true) {
26
+ const job = await getJob(opt, obj.jobId);
27
+ if (job && !job.timeouted) {
28
+ await new Promise(resolve => setTimeout(resolve, 2000));
29
+ continue
30
+ }
31
+ if (job && job.timeouted) {
32
+ console.error(colors.red('Job timeouted!'));
33
+ throw new Error('Job timeouted!')
34
+ }
35
+ break
36
+ }
37
+ console.log(colors.green(`remove version ${opt.version} succesfully requested`));
38
+ };
39
+
40
+ export { removeVersion as default };
@@ -0,0 +1,64 @@
1
+ import { HttpsProxyAgent } from 'https-proxy-agent';
2
+ import https from 'https';
3
+ import CacheableLookup from 'cacheable-lookup';
4
+
5
+ const cacheable = new CacheableLookup();
6
+ cacheable.install(https.globalAgent);
7
+
8
+ const httpProxy = process.env.http_proxy || process.env.HTTP_PROXY || process.env.https_proxy || process.env.HTTPS_PROXY;
9
+ const isRetriableError = (err) => {
10
+ return err && err.message && (
11
+ err.message.indexOf('ETIMEDOUT') > -1 || // on timeout retry
12
+ err.message.indexOf('FetchError') > -1 ||
13
+ err.code === 'ETIMEDOUT' ||
14
+ // on dns errors
15
+ err.message.indexOf('ENOTFOUND') > -1 ||
16
+ err.message.indexOf('ENODATA') > -1 ||
17
+ err.message.indexOf('ENOENT') > -1 // Windows: name exists, but not this record type
18
+ )
19
+ };
20
+
21
+ const isJSONResponse = (res) => res.headers.get('content-type') && res.headers.get('content-type').indexOf('json') > 0;
22
+
23
+ const handleResponse = (res) => {
24
+ if (isJSONResponse(res)) {
25
+ return new Promise((resolve, reject) => res.json().then((obj) => resolve({ res, obj })).catch(reject))
26
+ } else {
27
+ return { res }
28
+ }
29
+ };
30
+
31
+ async function request (url, options) {
32
+ if (httpProxy) {
33
+ const httpsProxyAgent = new HttpsProxyAgent(httpProxy);
34
+ cacheable.install(httpsProxyAgent);
35
+ options.agent = httpsProxyAgent;
36
+ }
37
+
38
+ options.headers = options.headers || {};
39
+ options.headers['User-Agent'] = `__packageName__/v__packageVersion__ (node/${process.version}; ${process.platform} ${process.arch})`; // This string is replaced with the actual version at build time by rollup
40
+ options.headers['X-User-Agent'] = options.headers['User-Agent'];
41
+ if (options.body || options.method !== 'get') options.headers['Content-Type'] = 'application/json';
42
+ if (options.body) {
43
+ if (typeof options.body !== 'string') {
44
+ options.body = JSON.stringify(options.body);
45
+ }
46
+ }
47
+ if (options.headers['Authorization'] === undefined) delete options.headers['Authorization'];
48
+
49
+ async function retriableFetch (maxRetries) {
50
+ try {
51
+ const response = await fetch(url, options);
52
+ const result = await handleResponse(response);
53
+ return result
54
+ } catch (err) {
55
+ if (maxRetries < 1) throw err
56
+ if (!isRetriableError(err)) throw err
57
+ await new Promise(resolve => setTimeout(resolve, 5000));
58
+ return retriableFetch(--maxRetries)
59
+ }
60
+ }
61
+ return retriableFetch(3)
62
+ }
63
+
64
+ export { request as default };
@@ -1,19 +1,19 @@
1
1
  const shouldUnflatten = (json) => {
2
- const keys = Object.keys(json)
3
- let shouldUnflatten = true
2
+ const keys = Object.keys(json);
3
+ let shouldUnflatten = true;
4
4
  for (let i = 0, len = keys.length; i < len; i++) {
5
- const key = keys[i]
5
+ const key = keys[i];
6
6
 
7
7
  if (shouldUnflatten && /( |,|\?)/.test(key)) {
8
- shouldUnflatten = false
8
+ shouldUnflatten = false;
9
9
  return shouldUnflatten
10
10
  } else if (shouldUnflatten && key.indexOf('.') > -1 && keys.indexOf(key.substring(0, key.lastIndexOf('.'))) > -1) {
11
- shouldUnflatten = false
11
+ shouldUnflatten = false;
12
12
  return shouldUnflatten
13
13
  }
14
14
  }
15
15
 
16
16
  return shouldUnflatten
17
- }
17
+ };
18
18
 
19
- module.exports = shouldUnflatten
19
+ export { shouldUnflatten as default };
@@ -0,0 +1,11 @@
1
+ const sortFlatResources = (resources) => {
2
+ const keys = Object.keys(resources).sort();
3
+ const cleaned = {};
4
+ for (let i = 0, len = keys.length; i < len; i++) {
5
+ const key = keys[i];
6
+ cleaned[key] = resources[key];
7
+ }
8
+ return cleaned
9
+ };
10
+
11
+ export { sortFlatResources as default };