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