@messagevisor/core 0.0.1 → 0.1.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 (211) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +7 -0
  4. package/jest.config.js +8 -0
  5. package/lib/benchmark/index.d.ts +2 -0
  6. package/lib/benchmark/index.js +417 -0
  7. package/lib/benchmark/index.js.map +1 -0
  8. package/lib/builder/index.d.ts +70 -0
  9. package/lib/builder/index.js +831 -0
  10. package/lib/builder/index.js.map +1 -0
  11. package/lib/cli/index.d.ts +28 -0
  12. package/lib/cli/index.js +182 -0
  13. package/lib/cli/index.js.map +1 -0
  14. package/lib/config/index.d.ts +61 -0
  15. package/lib/config/index.js +255 -0
  16. package/lib/config/index.js.map +1 -0
  17. package/lib/create/index.d.ts +2 -0
  18. package/lib/create/index.js +405 -0
  19. package/lib/create/index.js.map +1 -0
  20. package/lib/datasource/filesystemAdapter.d.ts +44 -0
  21. package/lib/datasource/filesystemAdapter.js +424 -0
  22. package/lib/datasource/filesystemAdapter.js.map +1 -0
  23. package/lib/datasource/index.d.ts +39 -0
  24. package/lib/datasource/index.js +96 -0
  25. package/lib/datasource/index.js.map +1 -0
  26. package/lib/error.d.ts +6 -0
  27. package/lib/error.js +49 -0
  28. package/lib/error.js.map +1 -0
  29. package/lib/evaluate/cli.d.ts +8 -0
  30. package/lib/evaluate/cli.js +179 -0
  31. package/lib/evaluate/cli.js.map +1 -0
  32. package/lib/evaluate/index.d.ts +10 -0
  33. package/lib/evaluate/index.js +131 -0
  34. package/lib/evaluate/index.js.map +1 -0
  35. package/lib/examples/coerceExampleIsoDates.d.ts +12 -0
  36. package/lib/examples/coerceExampleIsoDates.js +81 -0
  37. package/lib/examples/coerceExampleIsoDates.js.map +1 -0
  38. package/lib/examples/index.d.ts +63 -0
  39. package/lib/examples/index.js +713 -0
  40. package/lib/examples/index.js.map +1 -0
  41. package/lib/exporter/index.d.ts +60 -0
  42. package/lib/exporter/index.js +610 -0
  43. package/lib/exporter/index.js.map +1 -0
  44. package/lib/find-duplicates/index.d.ts +41 -0
  45. package/lib/find-duplicates/index.js +297 -0
  46. package/lib/find-duplicates/index.js.map +1 -0
  47. package/lib/generate-code/index.d.ts +11 -0
  48. package/lib/generate-code/index.js +157 -0
  49. package/lib/generate-code/index.js.map +1 -0
  50. package/lib/generate-code/typescript.d.ts +14 -0
  51. package/lib/generate-code/typescript.js +307 -0
  52. package/lib/generate-code/typescript.js.map +1 -0
  53. package/lib/importer/index.d.ts +64 -0
  54. package/lib/importer/index.js +1092 -0
  55. package/lib/importer/index.js.map +1 -0
  56. package/lib/index.d.ts +18 -0
  57. package/lib/index.js +35 -0
  58. package/lib/index.js.map +1 -0
  59. package/lib/info/index.d.ts +17 -0
  60. package/lib/info/index.js +132 -0
  61. package/lib/info/index.js.map +1 -0
  62. package/lib/init/index.d.ts +30 -0
  63. package/lib/init/index.js +348 -0
  64. package/lib/init/index.js.map +1 -0
  65. package/lib/lint/index.d.ts +1 -0
  66. package/lib/lint/index.js +6 -0
  67. package/lib/lint/index.js.map +1 -0
  68. package/lib/linter/attributeSchema.d.ts +7 -0
  69. package/lib/linter/attributeSchema.js +36 -0
  70. package/lib/linter/attributeSchema.js.map +1 -0
  71. package/lib/linter/checkLocaleCircularDependency.d.ts +7 -0
  72. package/lib/linter/checkLocaleCircularDependency.js +42 -0
  73. package/lib/linter/checkLocaleCircularDependency.js.map +1 -0
  74. package/lib/linter/conditionSchema.d.ts +3 -0
  75. package/lib/linter/conditionSchema.js +283 -0
  76. package/lib/linter/conditionSchema.js.map +1 -0
  77. package/lib/linter/formatSchema.d.ts +325 -0
  78. package/lib/linter/formatSchema.js +165 -0
  79. package/lib/linter/formatSchema.js.map +1 -0
  80. package/lib/linter/icuStyleLint.d.ts +6 -0
  81. package/lib/linter/icuStyleLint.js +226 -0
  82. package/lib/linter/icuStyleLint.js.map +1 -0
  83. package/lib/linter/index.d.ts +34 -0
  84. package/lib/linter/index.js +557 -0
  85. package/lib/linter/index.js.map +1 -0
  86. package/lib/linter/localeSchema.d.ts +672 -0
  87. package/lib/linter/localeSchema.js +50 -0
  88. package/lib/linter/localeSchema.js.map +1 -0
  89. package/lib/linter/messageSchema.d.ts +35 -0
  90. package/lib/linter/messageSchema.js +115 -0
  91. package/lib/linter/messageSchema.js.map +1 -0
  92. package/lib/linter/printError.d.ts +8 -0
  93. package/lib/linter/printError.js +41 -0
  94. package/lib/linter/printError.js.map +1 -0
  95. package/lib/linter/schema.d.ts +33 -0
  96. package/lib/linter/schema.js +192 -0
  97. package/lib/linter/schema.js.map +1 -0
  98. package/lib/linter/segmentSchema.d.ts +8 -0
  99. package/lib/linter/segmentSchema.js +18 -0
  100. package/lib/linter/segmentSchema.js.map +1 -0
  101. package/lib/linter/targetSchema.d.ts +337 -0
  102. package/lib/linter/targetSchema.js +39 -0
  103. package/lib/linter/targetSchema.js.map +1 -0
  104. package/lib/linter/testSchema.d.ts +71 -0
  105. package/lib/linter/testSchema.js +165 -0
  106. package/lib/linter/testSchema.js.map +1 -0
  107. package/lib/linter/zodHelpers.d.ts +2 -0
  108. package/lib/linter/zodHelpers.js +15 -0
  109. package/lib/linter/zodHelpers.js.map +1 -0
  110. package/lib/list/index.d.ts +8 -0
  111. package/lib/list/index.js +524 -0
  112. package/lib/list/index.js.map +1 -0
  113. package/lib/matrix.d.ts +4 -0
  114. package/lib/matrix.js +66 -0
  115. package/lib/matrix.js.map +1 -0
  116. package/lib/promoter/index.d.ts +65 -0
  117. package/lib/promoter/index.js +1208 -0
  118. package/lib/promoter/index.js.map +1 -0
  119. package/lib/prune/index.d.ts +37 -0
  120. package/lib/prune/index.js +673 -0
  121. package/lib/prune/index.js.map +1 -0
  122. package/lib/sets.d.ts +10 -0
  123. package/lib/sets.js +120 -0
  124. package/lib/sets.js.map +1 -0
  125. package/lib/tester/cliFormat.d.ts +8 -0
  126. package/lib/tester/cliFormat.js +15 -0
  127. package/lib/tester/cliFormat.js.map +1 -0
  128. package/lib/tester/index.d.ts +35 -0
  129. package/lib/tester/index.js +713 -0
  130. package/lib/tester/index.js.map +1 -0
  131. package/lib/tester/matrix.d.ts +14 -0
  132. package/lib/tester/matrix.js +76 -0
  133. package/lib/tester/matrix.js.map +1 -0
  134. package/lib/tester/prettyDuration.d.ts +1 -0
  135. package/lib/tester/prettyDuration.js +30 -0
  136. package/lib/tester/prettyDuration.js.map +1 -0
  137. package/lib/tester/printTestResult.d.ts +2 -0
  138. package/lib/tester/printTestResult.js +32 -0
  139. package/lib/tester/printTestResult.js.map +1 -0
  140. package/lib/tester/types.d.ts +29 -0
  141. package/lib/tester/types.js +3 -0
  142. package/lib/tester/types.js.map +1 -0
  143. package/package.json +41 -13
  144. package/src/benchmark/index.spec.ts +375 -0
  145. package/src/benchmark/index.ts +433 -0
  146. package/src/builder/index.spec.ts +822 -0
  147. package/src/builder/index.ts +920 -0
  148. package/src/cli/index.spec.ts +54 -0
  149. package/src/cli/index.ts +150 -0
  150. package/src/config/index.spec.ts +70 -0
  151. package/src/config/index.ts +259 -0
  152. package/src/create/index.spec.ts +272 -0
  153. package/src/create/index.ts +295 -0
  154. package/src/datasource/filesystemAdapter.ts +313 -0
  155. package/src/datasource/index.ts +135 -0
  156. package/src/error.ts +33 -0
  157. package/src/evaluate/cli.spec.ts +368 -0
  158. package/src/evaluate/cli.ts +130 -0
  159. package/src/evaluate/index.ts +161 -0
  160. package/src/examples/coerceExampleIsoDates.spec.ts +81 -0
  161. package/src/examples/coerceExampleIsoDates.ts +98 -0
  162. package/src/examples/index.spec.ts +453 -0
  163. package/src/examples/index.ts +854 -0
  164. package/src/exporter/index.spec.ts +443 -0
  165. package/src/exporter/index.ts +643 -0
  166. package/src/find-duplicates/index.spec.ts +289 -0
  167. package/src/find-duplicates/index.ts +314 -0
  168. package/src/generate-code/index.ts +92 -0
  169. package/src/generate-code/typescript.spec.ts +241 -0
  170. package/src/generate-code/typescript.ts +284 -0
  171. package/src/importer/index.spec.ts +1101 -0
  172. package/src/importer/index.ts +1190 -0
  173. package/src/index.ts +18 -0
  174. package/src/info/index.ts +67 -0
  175. package/src/init/index.spec.ts +279 -0
  176. package/src/init/index.ts +292 -0
  177. package/src/lint/index.ts +1 -0
  178. package/src/linter/attributeSchema.ts +38 -0
  179. package/src/linter/checkLocaleCircularDependency.ts +51 -0
  180. package/src/linter/conditionSchema.ts +386 -0
  181. package/src/linter/formatSchema.ts +170 -0
  182. package/src/linter/icuStyleLint.ts +312 -0
  183. package/src/linter/index.spec.ts +824 -0
  184. package/src/linter/index.ts +460 -0
  185. package/src/linter/localeSchema.ts +70 -0
  186. package/src/linter/messageSchema.ts +152 -0
  187. package/src/linter/printError.ts +52 -0
  188. package/src/linter/schema.ts +230 -0
  189. package/src/linter/segmentSchema.ts +15 -0
  190. package/src/linter/targetSchema.ts +50 -0
  191. package/src/linter/testSchema.spec.ts +405 -0
  192. package/src/linter/testSchema.ts +239 -0
  193. package/src/linter/zodHelpers.ts +16 -0
  194. package/src/list/index.spec.ts +431 -0
  195. package/src/list/index.ts +463 -0
  196. package/src/matrix.ts +69 -0
  197. package/src/promoter/index.spec.ts +584 -0
  198. package/src/promoter/index.ts +1267 -0
  199. package/src/prune/index.spec.ts +418 -0
  200. package/src/prune/index.ts +693 -0
  201. package/src/sets.ts +74 -0
  202. package/src/tester/cliFormat.ts +11 -0
  203. package/src/tester/featurevisorIntegration.spec.ts +101 -0
  204. package/src/tester/index.spec.ts +577 -0
  205. package/src/tester/index.ts +679 -0
  206. package/src/tester/matrix.ts +106 -0
  207. package/src/tester/prettyDuration.ts +34 -0
  208. package/src/tester/printTestResult.ts +40 -0
  209. package/src/tester/types.ts +32 -0
  210. package/tsconfig.cjs.json +11 -0
  211. package/tsconfig.typecheck.json +4 -0
@@ -0,0 +1,1092 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
47
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
48
+ return new (P || (P = Promise))(function (resolve, reject) {
49
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
50
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
51
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
53
+ });
54
+ };
55
+ var __generator = (this && this.__generator) || function (thisArg, body) {
56
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
57
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
58
+ function verb(n) { return function (v) { return step([n, v]); }; }
59
+ function step(op) {
60
+ if (f) throw new TypeError("Generator is already executing.");
61
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
62
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
63
+ if (y = 0, t) op = [op[0] & 2, t.value];
64
+ switch (op[0]) {
65
+ case 0: case 1: t = op; break;
66
+ case 4: _.label++; return { value: op[1], done: false };
67
+ case 5: _.label++; y = op[1]; op = [0]; continue;
68
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
69
+ default:
70
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
71
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
72
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
73
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
74
+ if (t[2]) _.ops.pop();
75
+ _.trys.pop(); continue;
76
+ }
77
+ op = body.call(thisArg, _);
78
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
79
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
80
+ }
81
+ };
82
+ var __rest = (this && this.__rest) || function (s, e) {
83
+ var t = {};
84
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
85
+ t[p] = s[p];
86
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
87
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
88
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
89
+ t[p[i]] = s[p[i]];
90
+ }
91
+ return t;
92
+ };
93
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
94
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
95
+ if (ar || !(i in from)) {
96
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
97
+ ar[i] = from[i];
98
+ }
99
+ }
100
+ return to.concat(ar || Array.prototype.slice.call(from));
101
+ };
102
+ Object.defineProperty(exports, "__esModule", { value: true });
103
+ exports.importPlugin = void 0;
104
+ exports.importProject = importProject;
105
+ exports.importProjectSets = importProjectSets;
106
+ /* eslint-disable @typescript-eslint/no-unused-vars */
107
+ var fs = __importStar(require("fs"));
108
+ var path = __importStar(require("path"));
109
+ var error_1 = require("../error");
110
+ var sets_1 = require("../sets");
111
+ var cliFormat_1 = require("../tester/cliFormat");
112
+ var prettyDuration_1 = require("../tester/prettyDuration");
113
+ function toArray(value) {
114
+ if (typeof value === "undefined")
115
+ return [];
116
+ return Array.isArray(value) ? value : [value];
117
+ }
118
+ function withoutKey(entity) {
119
+ var _key = entity.key, rest = __rest(entity, ["key"]);
120
+ return rest;
121
+ }
122
+ function cloneMessage(message) {
123
+ return JSON.parse(JSON.stringify(withoutKey(message)));
124
+ }
125
+ function parseCsv(content, delimiter) {
126
+ if (delimiter === void 0) { delimiter = ","; }
127
+ var source = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;
128
+ var rows = [];
129
+ var row = [];
130
+ var cell = "";
131
+ var inQuotes = false;
132
+ var quoteClosed = false;
133
+ for (var index = 0; index < source.length; index++) {
134
+ var char = source[index];
135
+ var next = source[index + 1];
136
+ if (inQuotes) {
137
+ if (char === '"' && next === '"') {
138
+ cell += '"';
139
+ index++;
140
+ }
141
+ else if (char === '"') {
142
+ inQuotes = false;
143
+ quoteClosed = true;
144
+ }
145
+ else if (char === "\r") {
146
+ if (next === "\n")
147
+ index++;
148
+ cell += "\n";
149
+ }
150
+ else {
151
+ cell += char;
152
+ }
153
+ continue;
154
+ }
155
+ if (quoteClosed) {
156
+ if (char === delimiter) {
157
+ row.push(cell);
158
+ cell = "";
159
+ quoteClosed = false;
160
+ }
161
+ else if (char === "\n") {
162
+ row.push(cell);
163
+ rows.push(row);
164
+ row = [];
165
+ cell = "";
166
+ quoteClosed = false;
167
+ }
168
+ else if (char === "\r") {
169
+ if (next === "\n")
170
+ index++;
171
+ row.push(cell);
172
+ rows.push(row);
173
+ row = [];
174
+ cell = "";
175
+ quoteClosed = false;
176
+ }
177
+ else {
178
+ throw new error_1.MessagevisorCLIError("Invalid CSV: unexpected character after closing quote.");
179
+ }
180
+ }
181
+ else if (char === '"') {
182
+ if (cell.length > 0) {
183
+ throw new error_1.MessagevisorCLIError("Invalid CSV: unexpected quote in unquoted field.");
184
+ }
185
+ inQuotes = true;
186
+ }
187
+ else if (char === delimiter) {
188
+ row.push(cell);
189
+ cell = "";
190
+ }
191
+ else if (char === "\n") {
192
+ row.push(cell);
193
+ rows.push(row);
194
+ row = [];
195
+ cell = "";
196
+ }
197
+ else if (char === "\r") {
198
+ if (next === "\n")
199
+ index++;
200
+ row.push(cell);
201
+ rows.push(row);
202
+ row = [];
203
+ cell = "";
204
+ }
205
+ else {
206
+ cell += char;
207
+ }
208
+ }
209
+ if (inQuotes) {
210
+ throw new error_1.MessagevisorCLIError("Invalid CSV: unterminated quoted field.");
211
+ }
212
+ if (cell.length > 0 || row.length > 0 || quoteClosed) {
213
+ row.push(cell);
214
+ rows.push(row);
215
+ }
216
+ var _a = rows[0], headers = _a === void 0 ? [] : _a, dataRows = rows.slice(1);
217
+ return {
218
+ headers: headers,
219
+ rows: dataRows
220
+ .map(function (dataRow, index) { return ({
221
+ dataRow: dataRow,
222
+ rowNumber: index + 2,
223
+ }); })
224
+ .filter(function (_a) {
225
+ var dataRow = _a.dataRow;
226
+ return dataRow.some(function (value) { return value !== ""; });
227
+ })
228
+ .map(function (_a) {
229
+ var dataRow = _a.dataRow, rowNumber = _a.rowNumber;
230
+ if (dataRow.length > headers.length) {
231
+ throw new error_1.MessagevisorCLIError("Invalid CSV: row ".concat(rowNumber, " has ").concat(dataRow.length, " cells but only ").concat(headers.length, " headers."));
232
+ }
233
+ return Object.fromEntries(headers.map(function (header, index) { return [header, dataRow[index] || ""]; }));
234
+ }),
235
+ };
236
+ }
237
+ function assertOptions(options) {
238
+ if (typeof options.delimiter !== "undefined" && options.delimiter.length !== 1) {
239
+ throw new error_1.MessagevisorCLIError("--delimiter must be a single character.");
240
+ }
241
+ if (options.fromJson && typeof options.delimiter !== "undefined") {
242
+ throw new error_1.MessagevisorCLIError("--delimiter can only be used with CSV imports.");
243
+ }
244
+ if (options.fromJson && typeof options.bom !== "undefined") {
245
+ throw new error_1.MessagevisorCLIError("--bom can only be used with CSV imports.");
246
+ }
247
+ }
248
+ function isHttpUrl(input) {
249
+ return /^https?:\/\//i.test(input);
250
+ }
251
+ function getInputFilePath(projectConfig, options, parsed) {
252
+ var _a;
253
+ var input = options.input || ((_a = parsed === null || parsed === void 0 ? void 0 : parsed._) === null || _a === void 0 ? void 0 : _a[1]);
254
+ if (!input) {
255
+ throw new error_1.MessagevisorCLIError(options.fromJson
256
+ ? "Pass a JSON file path or URL: messagevisor import <jsonFilePathOrUrl> --from-json --locale=<locale>."
257
+ : "Pass a CSV file path: messagevisor import <csvFilePath>.");
258
+ }
259
+ if (options.fromJson && isHttpUrl(input)) {
260
+ return input;
261
+ }
262
+ var projectRootDirectoryPath = path.dirname(projectConfig.exportsDirectoryPath);
263
+ return path.isAbsolute(input) ? input : path.join(projectRootDirectoryPath, input);
264
+ }
265
+ function readAll(keys, read) {
266
+ return __awaiter(this, void 0, void 0, function () {
267
+ var entries;
268
+ var _this = this;
269
+ return __generator(this, function (_a) {
270
+ switch (_a.label) {
271
+ case 0: return [4 /*yield*/, Promise.all(keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
272
+ switch (_b.label) {
273
+ case 0:
274
+ _a = [key];
275
+ return [4 /*yield*/, read(key)];
276
+ case 1: return [2 /*return*/, _a.concat([_b.sent()])];
277
+ }
278
+ }); }); }))];
279
+ case 1:
280
+ entries = _a.sent();
281
+ return [2 /*return*/, Object.fromEntries(entries)];
282
+ }
283
+ });
284
+ });
285
+ }
286
+ function resolveLocaleChain(localeKey, locales) {
287
+ var _a;
288
+ var chain = [];
289
+ var seen = new Set();
290
+ var currentKey = localeKey;
291
+ while (currentKey && !seen.has(currentKey)) {
292
+ seen.add(currentKey);
293
+ chain.unshift(currentKey);
294
+ currentKey = (_a = locales[currentKey]) === null || _a === void 0 ? void 0 : _a.inheritTranslationsFrom;
295
+ }
296
+ return chain;
297
+ }
298
+ function resolveTranslation(translations, localeKey, locales) {
299
+ if (typeof (translations === null || translations === void 0 ? void 0 : translations[localeKey]) !== "undefined") {
300
+ return translations[localeKey];
301
+ }
302
+ for (var _i = 0, _a = resolveLocaleChain(localeKey, locales).reverse(); _i < _a.length; _i++) {
303
+ var candidate = _a[_i];
304
+ if (translations && typeof translations[candidate] !== "undefined") {
305
+ return translations[candidate];
306
+ }
307
+ }
308
+ return undefined;
309
+ }
310
+ function resolveInheritedTranslationValue(translations, localeKey, locales) {
311
+ var _a, _b;
312
+ var currentKey = (_a = locales[localeKey]) === null || _a === void 0 ? void 0 : _a.inheritTranslationsFrom;
313
+ while (currentKey) {
314
+ if (translations && typeof translations[currentKey] !== "undefined") {
315
+ return translations[currentKey];
316
+ }
317
+ currentKey = (_b = locales[currentKey]) === null || _b === void 0 ? void 0 : _b.inheritTranslationsFrom;
318
+ }
319
+ }
320
+ function getLocaleInheritanceDepth(localeKey, locales) {
321
+ var _a, _b;
322
+ var depth = 0;
323
+ var seen = new Set();
324
+ var currentKey = (_a = locales[localeKey]) === null || _a === void 0 ? void 0 : _a.inheritTranslationsFrom;
325
+ while (currentKey && !seen.has(currentKey)) {
326
+ seen.add(currentKey);
327
+ depth++;
328
+ currentKey = (_b = locales[currentKey]) === null || _b === void 0 ? void 0 : _b.inheritTranslationsFrom;
329
+ }
330
+ return depth;
331
+ }
332
+ function splitMessageKey(projectConfig, key) {
333
+ var separator = projectConfig.exportOverrideKeySeparator;
334
+ var separatorIndex = key.lastIndexOf(separator);
335
+ if (separatorIndex === -1) {
336
+ return { messageKey: key };
337
+ }
338
+ return {
339
+ messageKey: key.slice(0, separatorIndex),
340
+ overrideKey: key.slice(separatorIndex + separator.length),
341
+ };
342
+ }
343
+ function getLocaleHeaders(headers, localeKeys) {
344
+ var reservedHeaders = new Set(["set", "messageKey", "messageDescription"]);
345
+ return headers.filter(function (header) {
346
+ return !reservedHeaders.has(header) && !header.endsWith("Status") && localeKeys.includes(header);
347
+ });
348
+ }
349
+ function getUnknownTranslationHeaders(headers, localeKeys) {
350
+ var reservedHeaders = new Set(["set", "messageKey", "messageDescription"]);
351
+ return headers.filter(function (header) {
352
+ return !reservedHeaders.has(header) && !header.endsWith("Status") && !localeKeys.includes(header);
353
+ });
354
+ }
355
+ function assertKnownLocales(requestedLocales, localeKeys) {
356
+ for (var _i = 0, requestedLocales_1 = requestedLocales; _i < requestedLocales_1.length; _i++) {
357
+ var locale = requestedLocales_1[_i];
358
+ if (!localeKeys.includes(locale)) {
359
+ throw new error_1.MessagevisorCLIError("Unknown locale \"".concat(locale, "\". Available locales: ").concat(localeKeys.join(", ") || "none", "."));
360
+ }
361
+ }
362
+ }
363
+ function getSelectedLocaleHeaders(headers, localeKeys, requestedLocales) {
364
+ var localeHeaders = getLocaleHeaders(headers, localeKeys);
365
+ if (requestedLocales.length === 0) {
366
+ return localeHeaders;
367
+ }
368
+ assertKnownLocales(requestedLocales, localeKeys);
369
+ return localeHeaders.filter(function (locale) { return requestedLocales.includes(locale); });
370
+ }
371
+ function toImportRows(projectConfig, csv, localeHeaders) {
372
+ if (!csv.headers.includes("messageKey")) {
373
+ throw new error_1.MessagevisorCLIError('CSV must include a "messageKey" column.');
374
+ }
375
+ return csv.rows.map(function (row, index) {
376
+ var _a = splitMessageKey(projectConfig, row.messageKey || ""), messageKey = _a.messageKey, overrideKey = _a.overrideKey;
377
+ return {
378
+ rowNumber: index + 2,
379
+ set: row.set || undefined,
380
+ messageKey: messageKey,
381
+ overrideKey: overrideKey,
382
+ values: Object.fromEntries(localeHeaders.map(function (locale) { return [locale, row[locale] || ""]; })),
383
+ };
384
+ });
385
+ }
386
+ function addWarning(warnings, message) {
387
+ warnings.push(message);
388
+ }
389
+ function getOrCreatePlan(plansByKey, set, messageKey, original) {
390
+ var planKey = "".concat(set || "", ":").concat(messageKey);
391
+ var existing = plansByKey.get(planKey);
392
+ if (existing) {
393
+ return existing;
394
+ }
395
+ var plan = {
396
+ set: set,
397
+ key: messageKey,
398
+ original: original,
399
+ updated: original ? cloneMessage(original) : { description: "", translations: {} },
400
+ createdMessage: !original,
401
+ createdOverrides: [],
402
+ changedLocales: [],
403
+ changedOverrideLocales: [],
404
+ prunedLocales: [],
405
+ prunedOverrideLocales: [],
406
+ };
407
+ plansByKey.set(planKey, plan);
408
+ return plan;
409
+ }
410
+ function shouldApplyTranslation(translations, locale, value, locales) {
411
+ if (value === "") {
412
+ return false;
413
+ }
414
+ if (translations && typeof translations[locale] !== "undefined") {
415
+ return translations[locale] !== value;
416
+ }
417
+ return resolveTranslation(translations, locale, locales) !== value;
418
+ }
419
+ function getImportValueEntries(values, locales) {
420
+ return Object.entries(values).sort(function (_a, _b) {
421
+ var leftLocale = _a[0];
422
+ var rightLocale = _b[0];
423
+ return getLocaleInheritanceDepth(leftLocale, locales) -
424
+ getLocaleInheritanceDepth(rightLocale, locales);
425
+ });
426
+ }
427
+ function getOrCreateOverride(message, overrideKey, createMissing) {
428
+ var overrides = message.overrides || [];
429
+ var existing = overrides.find(function (override) { return override.key === overrideKey; });
430
+ if (existing) {
431
+ return { override: existing, created: false };
432
+ }
433
+ if (!createMissing) {
434
+ return { created: false };
435
+ }
436
+ var created = {
437
+ key: overrideKey,
438
+ segments: "*",
439
+ translations: {},
440
+ };
441
+ message.overrides = __spreadArray(__spreadArray([], overrides, true), [created], false);
442
+ return { override: created, created: true };
443
+ }
444
+ function collectImportPlansForDatasource(datasource, rows, options, set, warnings) {
445
+ return __awaiter(this, void 0, void 0, function () {
446
+ var _a, localeKeys, messageKeys, locales, messages, plansByKey, skippedRows, skippedCells, prunedTranslations, sortedRows, _loop_1, _i, sortedRows_1, row;
447
+ var _b, _c;
448
+ return __generator(this, function (_d) {
449
+ switch (_d.label) {
450
+ case 0: return [4 /*yield*/, Promise.all([
451
+ datasource.listLocales(),
452
+ datasource.listMessages(),
453
+ ])];
454
+ case 1:
455
+ _a = _d.sent(), localeKeys = _a[0], messageKeys = _a[1];
456
+ return [4 /*yield*/, readAll(localeKeys, function (key) { return datasource.readLocale(key); })];
457
+ case 2:
458
+ locales = _d.sent();
459
+ return [4 /*yield*/, readAll(messageKeys, function (key) { return datasource.readMessage(key); })];
460
+ case 3:
461
+ messages = _d.sent();
462
+ plansByKey = new Map();
463
+ skippedRows = 0;
464
+ skippedCells = 0;
465
+ prunedTranslations = 0;
466
+ sortedRows = __spreadArray([], rows, true).sort(function (a, b) { return Number(Boolean(a.overrideKey)) - Number(Boolean(b.overrideKey)); });
467
+ _loop_1 = function (row) {
468
+ var _e, _f;
469
+ if (!row.messageKey) {
470
+ skippedRows++;
471
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": missing messageKey."));
472
+ return "continue";
473
+ }
474
+ var planKey = "".concat(set || "", ":").concat(row.messageKey);
475
+ var existingPlan = plansByKey.get(planKey);
476
+ var message = messages[row.messageKey];
477
+ if (!message && !options.createMissing) {
478
+ skippedRows++;
479
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": unknown message \"").concat(row.messageKey, "\"."));
480
+ return "continue";
481
+ }
482
+ if (row.overrideKey && !message && !existingPlan && options.createMissing) {
483
+ skippedRows++;
484
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": cannot create override \"").concat(row.overrideKey, "\" because message \"").concat(row.messageKey, "\" does not exist or is not created by another row."));
485
+ return "continue";
486
+ }
487
+ var plan = getOrCreatePlan(plansByKey, set, row.messageKey, message);
488
+ if (row.overrideKey) {
489
+ var _g = getOrCreateOverride(plan.updated, row.overrideKey, options.createMissing), override = _g.override, created = _g.created;
490
+ if (!override) {
491
+ skippedRows++;
492
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": unknown override \"").concat(row.overrideKey, "\" in message \"").concat(row.messageKey, "\"."));
493
+ return "continue";
494
+ }
495
+ var changed = false;
496
+ for (var _h = 0, _j = getImportValueEntries(row.values, locales); _h < _j.length; _h++) {
497
+ var _k = _j[_h], locale = _k[0], value = _k[1];
498
+ if (!localeKeys.includes(locale)) {
499
+ skippedCells++;
500
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": unknown locale \"").concat(locale, "\"."));
501
+ continue;
502
+ }
503
+ var inherited = options.prune
504
+ ? resolveInheritedTranslationValue(override.translations, locale, locales)
505
+ : undefined;
506
+ if (value !== "" && typeof inherited !== "undefined" && inherited === value) {
507
+ prunedTranslations++;
508
+ if (typeof ((_b = override.translations) === null || _b === void 0 ? void 0 : _b[locale]) !== "undefined") {
509
+ delete override.translations[locale];
510
+ plan.prunedOverrideLocales.push({ overrideKey: row.overrideKey, locale: locale });
511
+ changed = true;
512
+ }
513
+ continue;
514
+ }
515
+ if (!shouldApplyTranslation(override.translations, locale, value, locales)) {
516
+ skippedCells++;
517
+ continue;
518
+ }
519
+ override.translations = __assign(__assign({}, override.translations), (_e = {}, _e[locale] = value, _e));
520
+ plan.changedOverrideLocales.push({ overrideKey: row.overrideKey, locale: locale });
521
+ changed = true;
522
+ }
523
+ if (created && changed) {
524
+ plan.createdOverrides.push(row.overrideKey);
525
+ }
526
+ if (created && !changed) {
527
+ plan.updated.overrides = (plan.updated.overrides || []).filter(function (overrideEntry) { return overrideEntry.key !== row.overrideKey; });
528
+ }
529
+ return "continue";
530
+ }
531
+ for (var _l = 0, _m = getImportValueEntries(row.values, locales); _l < _m.length; _l++) {
532
+ var _o = _m[_l], locale = _o[0], value = _o[1];
533
+ if (!localeKeys.includes(locale)) {
534
+ skippedCells++;
535
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": unknown locale \"").concat(locale, "\"."));
536
+ continue;
537
+ }
538
+ var inherited = options.prune
539
+ ? resolveInheritedTranslationValue(plan.updated.translations, locale, locales)
540
+ : undefined;
541
+ if (value !== "" && typeof inherited !== "undefined" && inherited === value) {
542
+ prunedTranslations++;
543
+ if (typeof ((_c = plan.updated.translations) === null || _c === void 0 ? void 0 : _c[locale]) !== "undefined") {
544
+ delete plan.updated.translations[locale];
545
+ plan.prunedLocales.push(locale);
546
+ }
547
+ continue;
548
+ }
549
+ if (!shouldApplyTranslation(plan.updated.translations, locale, value, locales)) {
550
+ skippedCells++;
551
+ continue;
552
+ }
553
+ plan.updated.translations = __assign(__assign({}, plan.updated.translations), (_f = {}, _f[locale] = value, _f));
554
+ plan.changedLocales.push(locale);
555
+ }
556
+ };
557
+ for (_i = 0, sortedRows_1 = sortedRows; _i < sortedRows_1.length; _i++) {
558
+ row = sortedRows_1[_i];
559
+ _loop_1(row);
560
+ }
561
+ return [2 /*return*/, {
562
+ plans: Array.from(plansByKey.values()).filter(function (plan) {
563
+ return plan.changedLocales.length > 0 ||
564
+ plan.changedOverrideLocales.length > 0 ||
565
+ plan.createdOverrides.length > 0 ||
566
+ plan.prunedLocales.length > 0 ||
567
+ plan.prunedOverrideLocales.length > 0;
568
+ }),
569
+ skippedRows: skippedRows,
570
+ skippedCells: skippedCells,
571
+ prunedTranslations: prunedTranslations,
572
+ }];
573
+ }
574
+ });
575
+ });
576
+ }
577
+ function deepEqual(a, b) {
578
+ return JSON.stringify(a) === JSON.stringify(b);
579
+ }
580
+ function writePlans(datasource, plans) {
581
+ return __awaiter(this, void 0, void 0, function () {
582
+ var _i, plans_1, plan;
583
+ return __generator(this, function (_a) {
584
+ switch (_a.label) {
585
+ case 0:
586
+ _i = 0, plans_1 = plans;
587
+ _a.label = 1;
588
+ case 1:
589
+ if (!(_i < plans_1.length)) return [3 /*break*/, 4];
590
+ plan = plans_1[_i];
591
+ if (plan.original && deepEqual(withoutKey(plan.original), plan.updated)) {
592
+ return [3 /*break*/, 3];
593
+ }
594
+ return [4 /*yield*/, datasource.writeMessage(plan.key, plan.updated)];
595
+ case 2:
596
+ _a.sent();
597
+ _a.label = 3;
598
+ case 3:
599
+ _i++;
600
+ return [3 /*break*/, 1];
601
+ case 4: return [2 /*return*/];
602
+ }
603
+ });
604
+ });
605
+ }
606
+ function createResult(inputFilePath, apply, startTime, rows, plans, skippedRows, skippedCells, prunedTranslations, warnings) {
607
+ var changedOverrideKeys = new Set(plans.flatMap(function (plan) {
608
+ return __spreadArray(__spreadArray([], plan.changedOverrideLocales, true), plan.prunedOverrideLocales, true).map(function (entry) { return "".concat(plan.set || "", ":").concat(plan.key, ":").concat(entry.overrideKey); });
609
+ }));
610
+ var changedMessagePlans = plans.filter(function (plan) { return plan.changedLocales.length > 0 || plan.prunedLocales.length > 0; });
611
+ return {
612
+ inputFilePath: inputFilePath,
613
+ apply: apply,
614
+ duration: Date.now() - startTime,
615
+ plans: plans,
616
+ warnings: warnings,
617
+ summary: {
618
+ rows: rows,
619
+ changedMessages: changedMessagePlans.length,
620
+ changedOverrides: changedOverrideKeys.size,
621
+ createdMessages: plans.filter(function (plan) { return plan.createdMessage; }).length,
622
+ createdOverrides: plans.reduce(function (sum, plan) { return sum + plan.createdOverrides.length; }, 0),
623
+ changedTranslations: plans.reduce(function (sum, plan) { return sum + plan.changedLocales.length; }, 0) +
624
+ plans.reduce(function (sum, plan) { return sum + plan.changedOverrideLocales.length; }, 0),
625
+ prunedTranslations: prunedTranslations,
626
+ skippedRows: skippedRows,
627
+ skippedCells: skippedCells,
628
+ warnings: warnings.length,
629
+ sets: Array.from(new Set(plans.map(function (plan) { return plan.set; }).filter(function (entry) { return Boolean(entry); }))),
630
+ },
631
+ };
632
+ }
633
+ function readCsv(inputFilePath, options) {
634
+ return __awaiter(this, void 0, void 0, function () {
635
+ var _a;
636
+ return __generator(this, function (_b) {
637
+ switch (_b.label) {
638
+ case 0:
639
+ if (!fs.existsSync(inputFilePath)) {
640
+ throw new error_1.MessagevisorCLIError("CSV file does not exist: ".concat(inputFilePath));
641
+ }
642
+ _a = parseCsv;
643
+ return [4 /*yield*/, fs.promises.readFile(inputFilePath, "utf8")];
644
+ case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent(), options.delimiter || ","])];
645
+ }
646
+ });
647
+ });
648
+ }
649
+ function readJsonText(inputFilePath) {
650
+ return __awaiter(this, void 0, void 0, function () {
651
+ var response, error_2;
652
+ return __generator(this, function (_a) {
653
+ switch (_a.label) {
654
+ case 0:
655
+ if (!isHttpUrl(inputFilePath)) return [3 /*break*/, 5];
656
+ response = void 0;
657
+ _a.label = 1;
658
+ case 1:
659
+ _a.trys.push([1, 3, , 4]);
660
+ return [4 /*yield*/, fetch(inputFilePath)];
661
+ case 2:
662
+ response = _a.sent();
663
+ return [3 /*break*/, 4];
664
+ case 3:
665
+ error_2 = _a.sent();
666
+ throw new error_1.MessagevisorCLIError("Unable to fetch JSON from ".concat(inputFilePath, "."));
667
+ case 4:
668
+ if (!response.ok) {
669
+ throw new error_1.MessagevisorCLIError("Unable to fetch JSON from ".concat(inputFilePath, ": ").concat(response.status, " ").concat(response.statusText).trim());
670
+ }
671
+ return [2 /*return*/, response.text()];
672
+ case 5:
673
+ if (!fs.existsSync(inputFilePath)) {
674
+ throw new error_1.MessagevisorCLIError("JSON file does not exist: ".concat(inputFilePath));
675
+ }
676
+ return [2 /*return*/, fs.promises.readFile(inputFilePath, "utf8")];
677
+ }
678
+ });
679
+ });
680
+ }
681
+ function parseJson(content) {
682
+ try {
683
+ return JSON.parse(content);
684
+ }
685
+ catch (error) {
686
+ throw new error_1.MessagevisorCLIError("Invalid JSON: unable to parse input.");
687
+ }
688
+ }
689
+ function isPlainObject(value) {
690
+ return typeof value === "object" && value !== null && !Array.isArray(value);
691
+ }
692
+ function selectJsonPath(content, jsonPath) {
693
+ if (typeof jsonPath === "undefined") {
694
+ return content;
695
+ }
696
+ if (jsonPath.trim() === "") {
697
+ throw new error_1.MessagevisorCLIError("--json-path cannot be empty.");
698
+ }
699
+ var current = content;
700
+ for (var _i = 0, _a = jsonPath.split("."); _i < _a.length; _i++) {
701
+ var segment = _a[_i];
702
+ if (!segment) {
703
+ throw new error_1.MessagevisorCLIError("Invalid JSON path \"".concat(jsonPath, "\"."));
704
+ }
705
+ if (!isPlainObject(current) || !(segment in current)) {
706
+ throw new error_1.MessagevisorCLIError("JSON path \"".concat(jsonPath, "\" was not found."));
707
+ }
708
+ current = current[segment];
709
+ }
710
+ return current;
711
+ }
712
+ function jsonToImportRows(projectConfig, content, locale, jsonPath) {
713
+ var selected = selectJsonPath(content, jsonPath);
714
+ if (!isPlainObject(selected)) {
715
+ throw new error_1.MessagevisorCLIError(jsonPath
716
+ ? "JSON path \"".concat(jsonPath, "\" must resolve to a flat object.")
717
+ : "JSON import input must be a flat object.");
718
+ }
719
+ return Object.entries(selected).map(function (_a, index) {
720
+ var _b;
721
+ var key = _a[0], value = _a[1];
722
+ if (typeof value !== "string") {
723
+ throw new error_1.MessagevisorCLIError("JSON translation value for \"".concat(key, "\" must be a string."));
724
+ }
725
+ var _c = splitMessageKey(projectConfig, key), messageKey = _c.messageKey, overrideKey = _c.overrideKey;
726
+ return {
727
+ rowNumber: index + 1,
728
+ messageKey: messageKey,
729
+ overrideKey: overrideKey,
730
+ values: (_b = {},
731
+ _b[locale] = value,
732
+ _b),
733
+ };
734
+ });
735
+ }
736
+ function getJsonImportLocale(options) {
737
+ var requestedLocales = toArray(options.locale);
738
+ if (requestedLocales.length !== 1) {
739
+ throw new error_1.MessagevisorCLIError("--from-json requires exactly one --locale=<locale>.");
740
+ }
741
+ return requestedLocales[0];
742
+ }
743
+ function readJsonImportInput(projectConfig, inputFilePath, locale, options) {
744
+ return __awaiter(this, void 0, void 0, function () {
745
+ var content, _a, rows;
746
+ return __generator(this, function (_b) {
747
+ switch (_b.label) {
748
+ case 0:
749
+ _a = parseJson;
750
+ return [4 /*yield*/, readJsonText(inputFilePath)];
751
+ case 1:
752
+ content = _a.apply(void 0, [_b.sent()]);
753
+ rows = jsonToImportRows(projectConfig, content, locale, options.jsonPath);
754
+ return [2 /*return*/, {
755
+ inputFilePath: inputFilePath,
756
+ rows: rows,
757
+ warnings: [],
758
+ rowCount: rows.length,
759
+ }];
760
+ }
761
+ });
762
+ });
763
+ }
764
+ function readCsvImportInput(projectConfig, datasource, inputFilePath, options) {
765
+ return __awaiter(this, void 0, void 0, function () {
766
+ var csv, localeKeys, requestedLocales, localeHeaders, unknownHeaders, warnings, rows;
767
+ return __generator(this, function (_a) {
768
+ switch (_a.label) {
769
+ case 0: return [4 /*yield*/, readCsv(inputFilePath, options)];
770
+ case 1:
771
+ csv = _a.sent();
772
+ if (csv.headers.includes("set") && hasNonEmptySetValues(csv)) {
773
+ throw new error_1.MessagevisorCLIError('CSV "set" column can only contain values when `sets: true` is configured.');
774
+ }
775
+ return [4 /*yield*/, datasource.listLocales()];
776
+ case 2:
777
+ localeKeys = _a.sent();
778
+ requestedLocales = toArray(options.locale);
779
+ localeHeaders = getSelectedLocaleHeaders(csv.headers, localeKeys, requestedLocales);
780
+ unknownHeaders = getUnknownTranslationHeaders(csv.headers, localeKeys);
781
+ warnings = unknownHeaders.map(function (header) { return "Ignoring unknown CSV column \"".concat(header, "\"."); });
782
+ rows = toImportRows(projectConfig, csv, localeHeaders);
783
+ return [2 /*return*/, {
784
+ inputFilePath: inputFilePath,
785
+ rows: rows,
786
+ warnings: warnings,
787
+ rowCount: rows.length,
788
+ }];
789
+ }
790
+ });
791
+ });
792
+ }
793
+ function getAllLocaleKeysBySet(executions) {
794
+ var _this = this;
795
+ return Promise.all(executions.map(function (execution) { return __awaiter(_this, void 0, void 0, function () {
796
+ var _a;
797
+ return __generator(this, function (_b) {
798
+ switch (_b.label) {
799
+ case 0:
800
+ _a = {
801
+ set: execution.set
802
+ };
803
+ return [4 /*yield*/, execution.datasource.listLocales()];
804
+ case 1: return [2 /*return*/, (_a.locales = _b.sent(),
805
+ _a)];
806
+ }
807
+ });
808
+ }); }));
809
+ }
810
+ function hasNonEmptySetValues(csv) {
811
+ return csv.rows.some(function (row) { return row.set && row.set.trim() !== ""; });
812
+ }
813
+ function importProject(projectConfig_1, datasource_1) {
814
+ return __awaiter(this, arguments, void 0, function (projectConfig, datasource, options, parsed) {
815
+ var startTime, inputFilePath, input, _a, collected;
816
+ var _this = this;
817
+ if (options === void 0) { options = {}; }
818
+ return __generator(this, function (_b) {
819
+ switch (_b.label) {
820
+ case 0:
821
+ startTime = Date.now();
822
+ assertOptions(options);
823
+ if (projectConfig.sets) {
824
+ return [2 /*return*/, importProjectSets(projectConfig, datasource, options, parsed)];
825
+ }
826
+ if (toArray(options.set).length > 0) {
827
+ throw new error_1.MessagevisorCLIError("--set can only be used when `sets: true` is configured.");
828
+ }
829
+ inputFilePath = getInputFilePath(projectConfig, options, parsed);
830
+ if (!options.fromJson) return [3 /*break*/, 2];
831
+ return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
832
+ var locale, localeKeys;
833
+ return __generator(this, function (_a) {
834
+ switch (_a.label) {
835
+ case 0:
836
+ locale = getJsonImportLocale(options);
837
+ return [4 /*yield*/, datasource.listLocales()];
838
+ case 1:
839
+ localeKeys = _a.sent();
840
+ assertKnownLocales([locale], localeKeys);
841
+ return [2 /*return*/, readJsonImportInput(projectConfig, inputFilePath, locale, options)];
842
+ }
843
+ });
844
+ }); })()];
845
+ case 1:
846
+ _a = _b.sent();
847
+ return [3 /*break*/, 4];
848
+ case 2: return [4 /*yield*/, readCsvImportInput(projectConfig, datasource, inputFilePath, options)];
849
+ case 3:
850
+ _a = _b.sent();
851
+ _b.label = 4;
852
+ case 4:
853
+ input = _a;
854
+ return [4 /*yield*/, collectImportPlansForDatasource(datasource, input.rows, {
855
+ createMissing: options.createMissing === true,
856
+ prune: options.prune === true,
857
+ }, undefined, input.warnings)];
858
+ case 5:
859
+ collected = _b.sent();
860
+ if (!(options.apply === true)) return [3 /*break*/, 7];
861
+ return [4 /*yield*/, writePlans(datasource, collected.plans)];
862
+ case 6:
863
+ _b.sent();
864
+ _b.label = 7;
865
+ case 7: return [2 /*return*/, createResult(inputFilePath, options.apply === true, startTime, input.rowCount, collected.plans, collected.skippedRows, collected.skippedCells, collected.prunedTranslations, input.warnings)];
866
+ }
867
+ });
868
+ });
869
+ }
870
+ function importProjectSets(projectConfig_1, datasource_1) {
871
+ return __awaiter(this, arguments, void 0, function (projectConfig, datasource, options, parsed) {
872
+ var startTime, requestedSets, executions, executionSets, unknownRequestedSets, inputFilePath, locale, execution_1, localeKeys, input, warnings_1, collected, csv, selectedExecutions, hasSetColumn, localeKeysBySet, allLocaleKeys, requestedLocales, localeHeaders, unknownHeaders, warnings, rows, rowsBySet, skippedRows, skippedCells, _i, rows_1, row, rowSet, plans, prunedTranslations, _a, selectedExecutions_1, execution, setRows, collected;
873
+ if (options === void 0) { options = {}; }
874
+ return __generator(this, function (_b) {
875
+ switch (_b.label) {
876
+ case 0:
877
+ startTime = Date.now();
878
+ assertOptions(options);
879
+ if (!projectConfig.sets) {
880
+ return [2 /*return*/, importProject(projectConfig, datasource, options, parsed)];
881
+ }
882
+ requestedSets = toArray(options.set);
883
+ return [4 /*yield*/, (0, sets_1.getProjectSetExecutions)(projectConfig, datasource, undefined)];
884
+ case 1:
885
+ executions = _b.sent();
886
+ executionSets = executions.map(function (execution) { return execution.set; });
887
+ unknownRequestedSets = requestedSets.filter(function (set) { return !executionSets.includes(set); });
888
+ inputFilePath = getInputFilePath(projectConfig, options, parsed);
889
+ if (unknownRequestedSets.length > 0) {
890
+ throw new error_1.MessagevisorCLIError("Unknown set \"".concat(unknownRequestedSets[0], "\". Available sets: ").concat(executionSets.join(", ") || "none", "."));
891
+ }
892
+ if (!options.fromJson) return [3 /*break*/, 7];
893
+ if (requestedSets.length !== 1) {
894
+ throw new error_1.MessagevisorCLIError("--from-json requires exactly one --set=<set> when `sets: true` is configured.");
895
+ }
896
+ locale = getJsonImportLocale(options);
897
+ execution_1 = executions.find(function (currentExecution) { return currentExecution.set === requestedSets[0]; });
898
+ return [4 /*yield*/, execution_1.datasource.listLocales()];
899
+ case 2:
900
+ localeKeys = _b.sent();
901
+ assertKnownLocales([locale], localeKeys);
902
+ return [4 /*yield*/, readJsonImportInput(projectConfig, inputFilePath, locale, options)];
903
+ case 3:
904
+ input = _b.sent();
905
+ warnings_1 = __spreadArray([], input.warnings, true);
906
+ return [4 /*yield*/, collectImportPlansForDatasource(execution_1.datasource, input.rows.map(function (row) { return (__assign(__assign({}, row), { set: execution_1.set })); }), {
907
+ createMissing: options.createMissing === true,
908
+ prune: options.prune === true,
909
+ }, execution_1.set, warnings_1)];
910
+ case 4:
911
+ collected = _b.sent();
912
+ if (!(options.apply === true)) return [3 /*break*/, 6];
913
+ return [4 /*yield*/, writePlans(execution_1.datasource, collected.plans)];
914
+ case 5:
915
+ _b.sent();
916
+ _b.label = 6;
917
+ case 6: return [2 /*return*/, createResult(inputFilePath, options.apply === true, startTime, input.rowCount, collected.plans, collected.skippedRows, collected.skippedCells, collected.prunedTranslations, warnings_1)];
918
+ case 7: return [4 /*yield*/, readCsv(inputFilePath, options)];
919
+ case 8:
920
+ csv = _b.sent();
921
+ selectedExecutions = requestedSets.length > 0
922
+ ? executions.filter(function (execution) { return requestedSets.includes(execution.set); })
923
+ : executions;
924
+ hasSetColumn = csv.headers.includes("set");
925
+ if (!hasSetColumn && requestedSets.length !== 1) {
926
+ throw new error_1.MessagevisorCLIError('CSV without a "set" column requires exactly one --set=<set>.');
927
+ }
928
+ return [4 /*yield*/, getAllLocaleKeysBySet(selectedExecutions)];
929
+ case 9:
930
+ localeKeysBySet = _b.sent();
931
+ allLocaleKeys = Array.from(new Set(localeKeysBySet.flatMap(function (entry) { return entry.locales; })));
932
+ requestedLocales = toArray(options.locale);
933
+ localeHeaders = getSelectedLocaleHeaders(csv.headers, allLocaleKeys, requestedLocales);
934
+ unknownHeaders = getUnknownTranslationHeaders(csv.headers, allLocaleKeys);
935
+ warnings = unknownHeaders.map(function (header) { return "Ignoring unknown CSV column \"".concat(header, "\"."); });
936
+ rows = toImportRows(projectConfig, csv, localeHeaders);
937
+ rowsBySet = new Map();
938
+ skippedRows = 0;
939
+ skippedCells = 0;
940
+ for (_i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
941
+ row = rows_1[_i];
942
+ rowSet = hasSetColumn ? row.set : requestedSets[0];
943
+ if (!rowSet) {
944
+ skippedRows++;
945
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": missing set."));
946
+ continue;
947
+ }
948
+ if (!executionSets.includes(rowSet)) {
949
+ skippedRows++;
950
+ addWarning(warnings, "Row ".concat(row.rowNumber, ": unknown set \"").concat(rowSet, "\"."));
951
+ continue;
952
+ }
953
+ if (requestedSets.length > 0 && !requestedSets.includes(rowSet)) {
954
+ skippedRows++;
955
+ continue;
956
+ }
957
+ rowsBySet.set(rowSet, __spreadArray(__spreadArray([], (rowsBySet.get(rowSet) || []), true), [__assign(__assign({}, row), { set: rowSet })], false));
958
+ }
959
+ plans = [];
960
+ prunedTranslations = 0;
961
+ _a = 0, selectedExecutions_1 = selectedExecutions;
962
+ _b.label = 10;
963
+ case 10:
964
+ if (!(_a < selectedExecutions_1.length)) return [3 /*break*/, 14];
965
+ execution = selectedExecutions_1[_a];
966
+ setRows = rowsBySet.get(execution.set) || [];
967
+ if (setRows.length === 0) {
968
+ return [3 /*break*/, 13];
969
+ }
970
+ return [4 /*yield*/, collectImportPlansForDatasource(execution.datasource, setRows, {
971
+ createMissing: options.createMissing === true,
972
+ prune: options.prune === true,
973
+ }, execution.set, warnings)];
974
+ case 11:
975
+ collected = _b.sent();
976
+ plans.push.apply(plans, collected.plans);
977
+ skippedRows += collected.skippedRows;
978
+ skippedCells += collected.skippedCells;
979
+ prunedTranslations += collected.prunedTranslations;
980
+ if (!(options.apply === true)) return [3 /*break*/, 13];
981
+ return [4 /*yield*/, writePlans(execution.datasource, collected.plans)];
982
+ case 12:
983
+ _b.sent();
984
+ _b.label = 13;
985
+ case 13:
986
+ _a++;
987
+ return [3 /*break*/, 10];
988
+ case 14: return [2 /*return*/, createResult(inputFilePath, options.apply === true, startTime, rows.length, plans, skippedRows, skippedCells, prunedTranslations, warnings)];
989
+ }
990
+ });
991
+ });
992
+ }
993
+ function printImportResult(result) {
994
+ console.log("");
995
+ console.log(cliFormat_1.CLI_FORMAT_BOLD, "Importing Messagevisor translations");
996
+ var inputLabel = isHttpUrl(result.inputFilePath)
997
+ ? result.inputFilePath
998
+ : path.relative(process.cwd(), result.inputFilePath);
999
+ console.log(" Input: ".concat((0, cliFormat_1.colorize)(inputLabel, 36)));
1000
+ console.log(" Mode: ".concat(result.apply ? "apply" : "preview"));
1001
+ if (result.summary.sets.length > 0) {
1002
+ console.log(" Sets: ".concat(result.summary.sets.join(", ")));
1003
+ }
1004
+ console.log("");
1005
+ console.log(" Rows: ".concat(result.summary.rows));
1006
+ console.log(" Changed messages: ".concat(result.summary.changedMessages));
1007
+ console.log(" Changed overrides: ".concat(result.summary.changedOverrides));
1008
+ console.log(" Created messages: ".concat(result.summary.createdMessages));
1009
+ console.log(" Created overrides: ".concat(result.summary.createdOverrides));
1010
+ console.log(" Changed translations: ".concat(result.summary.changedTranslations));
1011
+ console.log(" Pruned translations: ".concat(result.summary.prunedTranslations));
1012
+ console.log(" Skipped rows: ".concat(result.summary.skippedRows));
1013
+ console.log(" Skipped cells: ".concat(result.summary.skippedCells));
1014
+ console.log(" Warnings: ".concat(result.summary.warnings));
1015
+ console.log("");
1016
+ if (result.warnings.length > 0) {
1017
+ console.log(cliFormat_1.CLI_FORMAT_BOLD, "Warnings");
1018
+ for (var _i = 0, _a = result.warnings.slice(0, 12); _i < _a.length; _i++) {
1019
+ var warning = _a[_i];
1020
+ console.log(cliFormat_1.CLI_FORMAT_YELLOW, " ".concat(warning));
1021
+ }
1022
+ if (result.warnings.length > 12) {
1023
+ console.log(" ".concat((0, cliFormat_1.colorize)("...and ".concat(result.warnings.length - 12, " more"), 2)));
1024
+ }
1025
+ console.log("");
1026
+ }
1027
+ console.log(cliFormat_1.CLI_FORMAT_GREEN, result.apply ? "Import applied" : "Import preview complete");
1028
+ console.log(cliFormat_1.CLI_FORMAT_BOLD, "Time: ".concat((0, prettyDuration_1.prettyDuration)(result.duration)));
1029
+ }
1030
+ exports.importPlugin = {
1031
+ command: "import [input]",
1032
+ handler: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
1033
+ var result, error_3;
1034
+ var projectConfig = _b.projectConfig, datasource = _b.datasource, parsed = _b.parsed;
1035
+ return __generator(this, function (_c) {
1036
+ switch (_c.label) {
1037
+ case 0:
1038
+ _c.trys.push([0, 2, , 3]);
1039
+ return [4 /*yield*/, importProjectSets(projectConfig, datasource, {
1040
+ input: parsed.input || parsed.csvFilePath,
1041
+ set: parsed.set,
1042
+ locale: parsed.locale,
1043
+ createMissing: parsed.createMissing,
1044
+ apply: parsed.apply === true || parsed.apply === "true",
1045
+ prune: parsed.prune === true || parsed.prune === "true",
1046
+ fromJson: parsed.fromJson === true || parsed.fromJson === "true",
1047
+ jsonPath: parsed.jsonPath,
1048
+ delimiter: parsed.delimiter,
1049
+ bom: parsed.bom,
1050
+ }, parsed)];
1051
+ case 1:
1052
+ result = _c.sent();
1053
+ printImportResult(result);
1054
+ return [3 /*break*/, 3];
1055
+ case 2:
1056
+ error_3 = _c.sent();
1057
+ if ((0, error_1.printMessagevisorCLIError)(error_3)) {
1058
+ return [2 /*return*/, false];
1059
+ }
1060
+ throw error_3;
1061
+ case 3: return [2 /*return*/];
1062
+ }
1063
+ });
1064
+ }); },
1065
+ examples: [
1066
+ {
1067
+ command: "import exports/messagevisor-export-20260419T123456.csv",
1068
+ description: "preview translations from a CSV file",
1069
+ },
1070
+ {
1071
+ command: "import --input=translator/nl.csv --apply",
1072
+ description: "apply an import and write message files",
1073
+ },
1074
+ {
1075
+ command: "import --input=translator/translations.csv --locale=nl --apply",
1076
+ description: "apply only one locale column from a CSV",
1077
+ },
1078
+ {
1079
+ command: "import --input=translator/translations.csv --locale=en-US --prune --apply",
1080
+ description: "apply an import while pruning translations duplicated by inheritance",
1081
+ },
1082
+ {
1083
+ command: "import translations.csv --set=staging",
1084
+ description: "preview a CSV without a set column for one set",
1085
+ },
1086
+ {
1087
+ command: "import translations.json --from-json --locale=nl-NL --apply",
1088
+ description: "apply translations from a flat JSON object",
1089
+ },
1090
+ ],
1091
+ };
1092
+ //# sourceMappingURL=index.js.map