@intlayer/cli 5.4.2 → 5.5.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 (61) hide show
  1. package/dist/cjs/build.cjs +1 -1
  2. package/dist/cjs/build.cjs.map +1 -1
  3. package/dist/cjs/cli.cjs +242 -20
  4. package/dist/cjs/cli.cjs.map +1 -1
  5. package/dist/cjs/config.cjs +3 -6
  6. package/dist/cjs/config.cjs.map +1 -1
  7. package/dist/cjs/fill.cjs +362 -0
  8. package/dist/cjs/fill.cjs.map +1 -0
  9. package/dist/cjs/index.cjs +6 -6
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/listContentDeclaration.cjs +5 -7
  12. package/dist/cjs/listContentDeclaration.cjs.map +1 -1
  13. package/dist/cjs/pull.cjs +11 -23
  14. package/dist/cjs/pull.cjs.map +1 -1
  15. package/dist/cjs/push.cjs +29 -59
  16. package/dist/cjs/push.cjs.map +1 -1
  17. package/dist/cjs/pushConfig.cjs +5 -4
  18. package/dist/cjs/pushConfig.cjs.map +1 -1
  19. package/dist/esm/build.mjs +1 -1
  20. package/dist/esm/build.mjs.map +1 -1
  21. package/dist/esm/cli.mjs +230 -19
  22. package/dist/esm/cli.mjs.map +1 -1
  23. package/dist/esm/config.mjs +5 -8
  24. package/dist/esm/config.mjs.map +1 -1
  25. package/dist/esm/fill.mjs +340 -0
  26. package/dist/esm/fill.mjs.map +1 -0
  27. package/dist/esm/index.mjs +3 -3
  28. package/dist/esm/index.mjs.map +1 -1
  29. package/dist/esm/listContentDeclaration.mjs +7 -9
  30. package/dist/esm/listContentDeclaration.mjs.map +1 -1
  31. package/dist/esm/pull.mjs +14 -26
  32. package/dist/esm/pull.mjs.map +1 -1
  33. package/dist/esm/push.mjs +31 -61
  34. package/dist/esm/push.mjs.map +1 -1
  35. package/dist/esm/pushConfig.mjs +7 -6
  36. package/dist/esm/pushConfig.mjs.map +1 -1
  37. package/dist/types/build.d.ts +2 -1
  38. package/dist/types/build.d.ts.map +1 -1
  39. package/dist/types/cli.d.ts +10 -0
  40. package/dist/types/cli.d.ts.map +1 -1
  41. package/dist/types/config.d.ts +2 -2
  42. package/dist/types/config.d.ts.map +1 -1
  43. package/dist/types/fill.d.ts +27 -0
  44. package/dist/types/fill.d.ts.map +1 -0
  45. package/dist/types/index.d.ts +3 -3
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/listContentDeclaration.d.ts +4 -3
  48. package/dist/types/listContentDeclaration.d.ts.map +1 -1
  49. package/dist/types/pull.d.ts +2 -2
  50. package/dist/types/pull.d.ts.map +1 -1
  51. package/dist/types/push.d.ts +4 -2
  52. package/dist/types/push.d.ts.map +1 -1
  53. package/dist/types/pushConfig.d.ts +2 -1
  54. package/dist/types/pushConfig.d.ts.map +1 -1
  55. package/package.json +13 -12
  56. package/dist/cjs/audit.cjs +0 -126
  57. package/dist/cjs/audit.cjs.map +0 -1
  58. package/dist/esm/audit.mjs +0 -94
  59. package/dist/esm/audit.mjs.map +0 -1
  60. package/dist/types/audit.d.ts +0 -38
  61. package/dist/types/audit.d.ts.map +0 -1
package/dist/cjs/push.cjs CHANGED
@@ -31,13 +31,14 @@ __export(push_exports, {
31
31
  push: () => push
32
32
  });
33
33
  module.exports = __toCommonJS(push_exports);
34
- var fsPromises = __toESM(require("fs/promises"));
35
- var import_path = require("path");
36
- var readline = __toESM(require("readline"));
37
34
  var import_api = require("@intlayer/api");
35
+ var import_chokidar = require("@intlayer/chokidar");
38
36
  var import_config = require("@intlayer/config");
39
37
  var import_dictionaries_entry = __toESM(require("@intlayer/dictionaries-entry"));
38
+ var fsPromises = __toESM(require("fs/promises"));
40
39
  var import_p_limit = __toESM(require("p-limit"));
40
+ var import_path = require("path");
41
+ var readline = __toESM(require("readline"));
41
42
  const spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
42
43
  const RESET = "\x1B[0m";
43
44
  const GREEN = "\x1B[32m";
@@ -46,9 +47,10 @@ const BLUE = "\x1B[34m";
46
47
  const GREY = "\x1B[90m";
47
48
  const GREY_DARK = "\x1B[90m";
48
49
  const push = async (options) => {
50
+ const config = (0, import_config.getConfiguration)(options?.configOptions);
51
+ const appLogger = (0, import_config.getAppLogger)(config);
52
+ const { clientId, clientSecret } = config.editor;
49
53
  try {
50
- const config = (0, import_config.getConfiguration)(options);
51
- const { clientId, clientSecret } = config.editor;
52
54
  if (!clientId || !clientSecret) {
53
55
  throw new Error(
54
56
  "Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project."
@@ -64,15 +66,12 @@ const push = async (options) => {
64
66
  (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)
65
67
  );
66
68
  if (noneExistingDictionariesOption.length > 0) {
67
- (0, import_config.logger)(
69
+ appLogger(
68
70
  `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(
69
71
  ", "
70
72
  )} and have been ignored.`,
71
73
  {
72
- level: "error",
73
- config: {
74
- prefix: options?.logPrefix
75
- }
74
+ level: "error"
76
75
  }
77
76
  );
78
77
  }
@@ -80,20 +79,16 @@ const push = async (options) => {
80
79
  (dictionary) => options.dictionaries.includes(dictionary.key)
81
80
  );
82
81
  }
82
+ if (options?.gitOptions) {
83
+ const gitFiles = await (0, import_chokidar.listGitFiles)(options.gitOptions);
84
+ }
83
85
  if (dictionaries.length === 0) {
84
- (0, import_config.logger)("No local dictionaries found", {
85
- level: "error",
86
- config: {
87
- prefix: options?.logPrefix
88
- }
86
+ appLogger("No local dictionaries found", {
87
+ level: "error"
89
88
  });
90
89
  return;
91
90
  }
92
- (0, import_config.logger)("Pushing dictionaries:", {
93
- config: {
94
- prefix: options?.logPrefix
95
- }
96
- });
91
+ appLogger("Pushing dictionaries:", {});
97
92
  const dictionariesStatuses = dictionaries.map(
98
93
  (dictionary, index) => ({
99
94
  dictionary,
@@ -147,11 +142,8 @@ const push = async (options) => {
147
142
  updateAllStatusLines(dictionariesStatuses);
148
143
  for (const statusObj of dictionariesStatuses) {
149
144
  if (statusObj.errorMessage) {
150
- (0, import_config.logger)(statusObj.errorMessage, {
151
- level: "error",
152
- config: {
153
- prefix: options?.logPrefix
154
- }
145
+ appLogger(statusObj.errorMessage, {
146
+ level: "error"
155
147
  });
156
148
  }
157
149
  }
@@ -174,11 +166,8 @@ const push = async (options) => {
174
166
  }
175
167
  }
176
168
  } catch (error) {
177
- (0, import_config.logger)(error, {
178
- level: "error",
179
- config: {
180
- prefix: options?.logPrefix
181
- }
169
+ appLogger(error, {
170
+ level: "error"
182
171
  });
183
172
  }
184
173
  };
@@ -195,16 +184,15 @@ const askUser = (question) => {
195
184
  });
196
185
  };
197
186
  const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
198
- const { baseDir } = (0, import_config.getConfiguration)().content;
187
+ const config = (0, import_config.getConfiguration)(options?.configOptions);
188
+ const appLogger = (0, import_config.getAppLogger)(config);
189
+ const { baseDir } = config.content;
199
190
  const filePathsSet = /* @__PURE__ */ new Set();
200
191
  for (const dictionary of dictionariesToDelete) {
201
192
  const { filePath } = dictionary;
202
193
  if (!filePath) {
203
- (0, import_config.logger)(`Dictionary ${dictionary.key} does not have a file path`, {
204
- level: "error",
205
- config: {
206
- prefix: options?.logPrefix
207
- }
194
+ appLogger(`Dictionary ${dictionary.key} does not have a file path`, {
195
+ level: "error"
208
196
  });
209
197
  continue;
210
198
  }
@@ -216,30 +204,15 @@ const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
216
204
  const stats = await fsPromises.lstat(filePath);
217
205
  if (stats.isFile()) {
218
206
  await fsPromises.unlink(filePath);
219
- (0, import_config.logger)(`Deleted file ${relativePath}`, {
220
- config: {
221
- prefix: options?.logPrefix
222
- }
223
- });
207
+ appLogger(`Deleted file ${relativePath}`, {});
224
208
  } else if (stats.isDirectory()) {
225
- (0, import_config.logger)(`Path is a directory ${relativePath}, skipping.`, {
226
- config: {
227
- prefix: options?.logPrefix
228
- }
229
- });
209
+ appLogger(`Path is a directory ${relativePath}, skipping.`, {});
230
210
  } else {
231
- (0, import_config.logger)(`Unknown file type for ${relativePath}, skipping.`, {
232
- config: {
233
- prefix: options?.logPrefix
234
- }
235
- });
211
+ appLogger(`Unknown file type for ${relativePath}, skipping.`, {});
236
212
  }
237
213
  } catch (err) {
238
- (0, import_config.logger)(`Error deleting ${relativePath}: ${err}`, {
239
- level: "error",
240
- config: {
241
- prefix: options?.logPrefix
242
- }
214
+ appLogger(`Error deleting ${relativePath}: ${err}`, {
215
+ level: "error"
243
216
  });
244
217
  }
245
218
  }
@@ -256,9 +229,6 @@ const getStatusIcon = (status) => {
256
229
  return statusIcons[status] || "";
257
230
  };
258
231
  const getStatusLine = (statusObj) => {
259
- const {
260
- log: { prefix }
261
- } = (0, import_config.getConfiguration)();
262
232
  let icon = getStatusIcon(statusObj.status);
263
233
  let colorStart = "";
264
234
  let colorEnd = "";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import * as fsPromises from 'fs/promises';\nimport { relative } from 'path';\nimport * as readline from 'readline';\nimport { getIntlayerAPI } from '@intlayer/api';\nimport {\n getConfiguration,\n GetConfigurationOptions,\n logger,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport pLimit from 'p-limit';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n logPrefix?: string;\n} & GetConfigurationOptions;\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n icon: string;\n index: number;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\n/**\n * Get all locale dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n try {\n const config = getConfiguration(options);\n const { clientId, clientSecret } = config.editor;\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAPI = getIntlayerAPI(undefined, config);\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n logger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n logger('No local dictionaries found', {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n });\n return;\n }\n\n logger('Pushing dictionaries:', {\n config: {\n prefix: options?.logPrefix,\n },\n });\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary, index) => ({\n dictionary,\n icon: getStatusIcon('pending'),\n status: 'pending',\n index,\n spinnerFrameIndex: 0,\n })\n );\n\n // Output initial statuses\n for (const statusObj of dictionariesStatuses) {\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n // Start spinner timer\n const spinnerTimer = setInterval(() => {\n updateAllStatusLines(dictionariesStatuses);\n }, 100); // Update every 100ms\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries(\n [statusObj.dictionary],\n {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }\n );\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Limit the number of concurrent requests\n const pushPromises = dictionariesStatuses.map((statusObj) =>\n limit(() => processDictionary(statusObj))\n );\n await Promise.all(pushPromises);\n\n // Stop the spinner timer\n clearInterval(spinnerTimer);\n\n // Update statuses one last time\n updateAllStatusLines(dictionariesStatuses);\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n logger(statusObj.errorMessage, {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n logger(error, {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const { baseDir } = getConfiguration().content;\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n logger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n const relativePath = relative(baseDir, filePath);\n\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n logger(`Deleted file ${relativePath}`, {\n config: {\n prefix: options?.logPrefix,\n },\n });\n } else if (stats.isDirectory()) {\n logger(`Path is a directory ${relativePath}, skipping.`, {\n config: {\n prefix: options?.logPrefix,\n },\n });\n } else {\n logger(`Unknown file type for ${relativePath}, skipping.`, {\n config: {\n prefix: options?.logPrefix,\n },\n });\n }\n } catch (err) {\n logger(`Error deleting ${relativePath}: ${err}`, {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n });\n }\n }\n};\n\nconst getStatusIcon = (status: string): string => {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n pushing: '', // Spinner handled separately\n modified: '✔',\n pushed: '✔',\n error: '✖',\n };\n return statusIcons[status] || '';\n};\n\nconst getStatusLine = (statusObj: DictionariesStatus): string => {\n const {\n log: { prefix },\n } = getConfiguration();\n\n let icon = getStatusIcon(statusObj.status);\n let colorStart = '';\n let colorEnd = '';\n\n if (statusObj.status === 'pushing') {\n // Use spinner frame\n icon = spinnerFrames[statusObj.spinnerFrameIndex! % spinnerFrames.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (statusObj.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (statusObj.status === 'pushed' || statusObj.status === 'modified') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n return `- ${statusObj.dictionary.key} ${GREY_DARK}[${colorStart}${icon}${statusObj.status}${GREY_DARK}]${colorEnd}`;\n};\n\nconst updateAllStatusLines = (dictionariesStatuses: DictionariesStatus[]) => {\n // Move cursor up to the first status line\n readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);\n for (const statusObj of dictionariesStatuses) {\n // Clear the line\n readline.clearLine(process.stdout, 0);\n\n if (statusObj.status === 'pushing') {\n // Update spinner frame\n statusObj.spinnerFrameIndex =\n (statusObj.spinnerFrameIndex! + 1) % spinnerFrames.length;\n }\n\n // Write the status line\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n};\n"],"mappings":"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","names":["dictionariesRecord","pLimit"]}
1
+ {"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import { getIntlayerAPI } from '@intlayer/api';\nimport { listGitFiles, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport * as fsPromises from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { relative } from 'path';\nimport * as readline from 'readline';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n icon: string;\n index: number;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\n/**\n * Get all locale dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { clientId, clientSecret } = config.editor;\n try {\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAPI = getIntlayerAPI(undefined, config);\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:', {});\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary, index) => ({\n dictionary,\n icon: getStatusIcon('pending'),\n status: 'pending',\n index,\n spinnerFrameIndex: 0,\n })\n );\n\n // Output initial statuses\n for (const statusObj of dictionariesStatuses) {\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n // Start spinner timer\n const spinnerTimer = setInterval(() => {\n updateAllStatusLines(dictionariesStatuses);\n }, 100); // Update every 100ms\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries(\n [statusObj.dictionary],\n {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }\n );\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Limit the number of concurrent requests\n const pushPromises = dictionariesStatuses.map((statusObj) =>\n limit(() => processDictionary(statusObj))\n );\n await Promise.all(pushPromises);\n\n // Stop the spinner timer\n clearInterval(spinnerTimer);\n\n // Update statuses one last time\n updateAllStatusLines(dictionariesStatuses);\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { baseDir } = config.content;\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n const relativePath = relative(baseDir, filePath);\n\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${relativePath}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${relativePath}, skipping.`, {});\n } else {\n appLogger(`Unknown file type for ${relativePath}, skipping.`, {});\n }\n } catch (err) {\n appLogger(`Error deleting ${relativePath}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n\nconst getStatusIcon = (status: string): string => {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n pushing: '', // Spinner handled separately\n modified: '✔',\n pushed: '✔',\n error: '✖',\n };\n return statusIcons[status] || '';\n};\n\nconst getStatusLine = (statusObj: DictionariesStatus): string => {\n let icon = getStatusIcon(statusObj.status);\n let colorStart = '';\n let colorEnd = '';\n\n if (statusObj.status === 'pushing') {\n // Use spinner frame\n icon = spinnerFrames[statusObj.spinnerFrameIndex! % spinnerFrames.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (statusObj.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (statusObj.status === 'pushed' || statusObj.status === 'modified') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n return `- ${statusObj.dictionary.key} ${GREY_DARK}[${colorStart}${icon}${statusObj.status}${GREY_DARK}]${colorEnd}`;\n};\n\nconst updateAllStatusLines = (dictionariesStatuses: DictionariesStatus[]) => {\n // Move cursor up to the first status line\n readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);\n for (const statusObj of dictionariesStatuses) {\n // Clear the line\n readline.clearLine(process.stdout, 0);\n\n if (statusObj.status === 'pushing') {\n // Update spinner frame\n statusObj.spinnerFrameIndex =\n (statusObj.spinnerFrameIndex! + 1) % spinnerFrames.length;\n }\n\n // Write the status line\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n};\n"],"mappings":"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","names":["dictionariesRecord","pLimit"]}
@@ -24,10 +24,11 @@ module.exports = __toCommonJS(pushConfig_exports);
24
24
  var import_api = require("@intlayer/api");
25
25
  var import_config = require("@intlayer/config");
26
26
  const pushConfig = async (options) => {
27
- const config = (0, import_config.getConfiguration)(options);
27
+ const config = (0, import_config.getConfiguration)(options?.configOptions);
28
+ const appLogger = (0, import_config.getAppLogger)(config);
28
29
  const { clientId, clientSecret } = config.editor;
29
30
  if (!clientId || !clientSecret) {
30
- (0, import_config.logger)(
31
+ appLogger(
31
32
  "Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.",
32
33
  {
33
34
  level: "error",
@@ -47,12 +48,12 @@ const pushConfig = async (options) => {
47
48
  if (!getDictionariesKeysResult.data) {
48
49
  throw new Error("Error pushing project configuration");
49
50
  }
50
- (0, import_config.logger)("Project configuration pushed successfully", {
51
+ appLogger("Project configuration pushed successfully", {
51
52
  config: {
52
53
  prefix: options?.logPrefix
53
54
  }
54
55
  });
55
- (0, import_config.logger)(JSON.stringify(getDictionariesKeysResult.data, null, 2), {
56
+ appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2), {
56
57
  config: {
57
58
  prefix: options?.logPrefix
58
59
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPI } from '@intlayer/api';\nimport {\n getConfiguration,\n logger,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype PushOptions = {\n logPrefix?: string;\n} & GetConfigurationOptions;\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options);\n\n const { clientId, clientSecret } = config.editor;\n\n if (!clientId || !clientSecret) {\n logger(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.',\n {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n }\n );\n return;\n }\n\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config, {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n });\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n logger('Project configuration pushed successfully', {\n config: {\n prefix: options?.logPrefix,\n },\n });\n\n logger(JSON.stringify(getDictionariesKeysResult.data, null, 2), {\n config: {\n prefix: options?.logPrefix,\n },\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA+B;AAC/B,oBAIO;AAMA,MAAM,aAAa,OAAO,YAA0B;AACzD,QAAM,aAAS,gCAAiB,OAAO;AAEvC,QAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAE1C,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,QAAQ;AAAA,UACN,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,kBAAc,2BAAe,QAAW,MAAM;AAEpD,QAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,QAAM,oBAAoB,kBAAkB,MAAM;AAGlD,QAAM,4BACJ,MAAM,YAAY,QAAQ,yBAAyB,QAAQ;AAAA,IACzD,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,EAC1D,CAAC;AAEH,MAAI,CAAC,0BAA0B,MAAM;AACnC,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAEA,4BAAO,6CAA6C;AAAA,IAClD,QAAQ;AAAA,MACN,QAAQ,SAAS;AAAA,IACnB;AAAA,EACF,CAAC;AAED,4BAAO,KAAK,UAAU,0BAA0B,MAAM,MAAM,CAAC,GAAG;AAAA,IAC9D,QAAQ;AAAA,MACN,QAAQ,SAAS;AAAA,IACnB;AAAA,EACF,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPI } from '@intlayer/api';\nimport {\n getAppLogger,\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype PushOptions = {\n logPrefix?: string;\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const { clientId, clientSecret } = config.editor;\n\n if (!clientId || !clientSecret) {\n appLogger(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.',\n {\n level: 'error',\n config: {\n prefix: options?.logPrefix,\n },\n }\n );\n return;\n }\n\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config, {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n });\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully', {\n config: {\n prefix: options?.logPrefix,\n },\n });\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2), {\n config: {\n prefix: options?.logPrefix,\n },\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA+B;AAC/B,oBAIO;AAOA,MAAM,aAAa,OAAO,YAA0B;AACzD,QAAM,aAAS,gCAAiB,SAAS,aAAa;AACtD,QAAM,gBAAY,4BAAa,MAAM;AAErC,QAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAE1C,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,QAAQ;AAAA,UACN,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,kBAAc,2BAAe,QAAW,MAAM;AAEpD,QAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,QAAM,oBAAoB,kBAAkB,MAAM;AAGlD,QAAM,4BACJ,MAAM,YAAY,QAAQ,yBAAyB,QAAQ;AAAA,IACzD,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,EAC1D,CAAC;AAEH,MAAI,CAAC,0BAA0B,MAAM;AACnC,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAEA,YAAU,6CAA6C;AAAA,IACrD,QAAQ;AAAA,MACN,QAAQ,SAAS;AAAA,IACnB;AAAA,EACF,CAAC;AAED,YAAU,KAAK,UAAU,0BAA0B,MAAM,MAAM,CAAC,GAAG;AAAA,IACjE,QAAQ;AAAA,MACN,QAAQ,SAAS;AAAA,IACnB;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  getConfiguration
4
4
  } from "@intlayer/config";
5
5
  const build = async (options) => {
6
- const config = getConfiguration(options);
6
+ const config = getConfiguration(options?.configOptions);
7
7
  await buildAndWatchIntlayer({
8
8
  persistent: options?.watch ?? false,
9
9
  configuration: config
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/build.ts"],"sourcesContent":["import { buildAndWatchIntlayer } from '@intlayer/chokidar';\nimport {\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype BuildOptions = { watch?: boolean } & GetConfigurationOptions;\n\n/**\n * Get locales dictionaries .content.{json|ts|tsx|js|jsx|mjs|cjs} and build the JSON dictionaries in the .intlayer directory.\n * Watch mode available to get the change in the .content.{json|ts|tsx|js|jsx|mjs|cjs}\n */\nexport const build = async (options?: BuildOptions) => {\n const config = getConfiguration(options);\n\n await buildAndWatchIntlayer({\n persistent: options?.watch ?? false,\n configuration: config,\n });\n};\n"],"mappings":"AAAA,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,OAEK;AAQA,MAAM,QAAQ,OAAO,YAA2B;AACrD,QAAM,SAAS,iBAAiB,OAAO;AAEvC,QAAM,sBAAsB;AAAA,IAC1B,YAAY,SAAS,SAAS;AAAA,IAC9B,eAAe;AAAA,EACjB,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../src/build.ts"],"sourcesContent":["import { buildAndWatchIntlayer } from '@intlayer/chokidar';\nimport {\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype BuildOptions = {\n watch?: boolean;\n configOptions?: GetConfigurationOptions;\n};\n\n/**\n * Get locales dictionaries .content.{json|ts|tsx|js|jsx|mjs|cjs} and build the JSON dictionaries in the .intlayer directory.\n * Watch mode available to get the change in the .content.{json|ts|tsx|js|jsx|mjs|cjs}\n */\nexport const build = async (options?: BuildOptions) => {\n const config = getConfiguration(options?.configOptions);\n\n await buildAndWatchIntlayer({\n persistent: options?.watch ?? false,\n configuration: config,\n });\n};\n"],"mappings":"AAAA,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,OAEK;AAWA,MAAM,QAAQ,OAAO,YAA2B;AACrD,QAAM,SAAS,iBAAiB,SAAS,aAAa;AAEtD,QAAM,sBAAsB;AAAA,IAC1B,YAAY,SAAS,SAAS;AAAA,IAC9B,eAAe;AAAA,EACjB,CAAC;AACH;","names":[]}
package/dist/esm/cli.mjs CHANGED
@@ -1,34 +1,245 @@
1
+ import configuration from "@intlayer/config/built";
1
2
  import { Command } from "commander";
2
- import { audit } from "./audit.mjs";
3
+ import { readFileSync } from "fs";
4
+ import { dirname, resolve } from "path";
5
+ import { fileURLToPath } from "url";
3
6
  import { build } from "./build.mjs";
4
7
  import { getConfig } from "./config.mjs";
8
+ import { fill } from "./fill.mjs";
5
9
  import { listContentDeclaration } from "./listContentDeclaration.mjs";
6
10
  import { pull } from "./pull.mjs";
7
11
  import { push } from "./push.mjs";
8
12
  import { pushConfig } from "./pushConfig.mjs";
13
+ const CJS_ESM_Dirname = __dirname ?? dirname(fileURLToPath(import.meta.url));
14
+ const packageJson = JSON.parse(
15
+ readFileSync(resolve(CJS_ESM_Dirname, "../../package.json"), "utf8")
16
+ );
17
+ const logOptions = [
18
+ ["--verbose", "Verbose"],
19
+ ["--prefix [prefix]", "Prefix"]
20
+ ];
21
+ const configurationOptions = [
22
+ ["--env-file [envFile]", "Environment file"],
23
+ ["-e, --env [env]", "Environment"],
24
+ ["--base-dir [baseDir]", "Base directory"],
25
+ ...logOptions
26
+ ];
27
+ const aiOptions = [
28
+ ["--provider [provider]", "Provider"],
29
+ ["--temperature [temperature]", "Temperature"],
30
+ ["--model [model]", "Model"],
31
+ ["--api-key [apiKey]", "Provider API key"],
32
+ ["--custom-prompt [prompt]", "Custom prompt"],
33
+ ["--application-context [applicationContext]", "Application context"]
34
+ ];
35
+ const gitOptions = [
36
+ ["--git-diff [gitDiff]", "Git diff mode - Check git diff between two refs"],
37
+ ["--git-diff-base [gitDiffBase]", "Git diff base ref"],
38
+ ["--git-diff-current [gitDiffCurrent]", "Git diff current ref"],
39
+ ["--uncommitted [uncommitted]", "Uncommitted"],
40
+ ["--unpushed [unpushed]", "Unpushed"],
41
+ ["--untracked [untracked]", "Untracked"]
42
+ ];
43
+ const applyOptions = (command, options) => {
44
+ options.forEach(([flag, description]) => command.option(flag, description));
45
+ return command;
46
+ };
47
+ const removeUndefined = (obj) => Object.fromEntries(
48
+ Object.entries(obj).filter(([_, value]) => value !== void 0)
49
+ );
50
+ const applyConfigOptions = (command) => applyOptions(command, configurationOptions);
51
+ const applyAIOptions = (command) => applyOptions(command, aiOptions);
52
+ const applyGitOptions = (command) => applyOptions(command, gitOptions);
53
+ const extractAiOptions = (options) => {
54
+ const isOptionEmpty = !Object.values(options).some(Boolean);
55
+ if (isOptionEmpty) {
56
+ return void 0;
57
+ }
58
+ const { apiKey, provider, model, temperature, applicationContext } = options;
59
+ return removeUndefined({
60
+ apiKey: apiKey ?? configuration.ai?.apiKey,
61
+ provider: provider ?? configuration.ai?.provider,
62
+ model: model ?? configuration.ai?.model,
63
+ temperature: temperature ?? configuration.ai?.temperature,
64
+ applicationContext: applicationContext ?? configuration.ai?.applicationContext
65
+ });
66
+ };
67
+ const extractGitOptions = (options) => {
68
+ const isOptionEmpty = !Object.values(options).some(Boolean);
69
+ if (isOptionEmpty) {
70
+ return void 0;
71
+ }
72
+ const {
73
+ gitDiff,
74
+ gitDiffBase,
75
+ gitDiffCurrent,
76
+ uncommitted,
77
+ unpushed,
78
+ untracked
79
+ } = options;
80
+ const mode = [
81
+ gitDiff && "gitDiff",
82
+ uncommitted && "uncommitted",
83
+ unpushed && "unpushed",
84
+ untracked && "untracked"
85
+ ].filter(Boolean);
86
+ return removeUndefined({
87
+ mode,
88
+ baseRef: gitDiffBase,
89
+ currentRef: gitDiffCurrent,
90
+ absolute: true
91
+ });
92
+ };
93
+ const extractConfigOptions = (options) => {
94
+ const { baseDir, env, envFile, verbose, prefix } = options;
95
+ const log = {
96
+ prefix: prefix ?? "",
97
+ // Should not consider the prefix set in the intlayer configuration file
98
+ verbose
99
+ };
100
+ const override = {
101
+ log
102
+ };
103
+ return removeUndefined({
104
+ baseDir,
105
+ env,
106
+ envFile,
107
+ override
108
+ });
109
+ };
9
110
  const setAPI = () => {
10
111
  const program = new Command();
11
- program.version("1.0.0").description("Intlayer CLI");
112
+ program.version(packageJson.version).description("Intlayer CLI");
12
113
  const dictionariesProgram = program.command("dictionary").alias("dictionaries").alias("dic").description("Dictionaries operations");
13
- dictionariesProgram.command("build").description("Build the dictionaries").option("-w, --watch", "Watch for changes").option("-e, --env [env]", "Environment").action(build);
14
- dictionariesProgram.command("pull").option("-d, --dictionaries [ids...]", "List of dictionary IDs to pull").option("--newDictionariesPath [path]", "Path to save the new dictionaries").option("-e, --env [env]", "Environment").action(pull);
15
- dictionariesProgram.command("push").description(
16
- "Push all dictionaries. Create or update the pushed dictionaries"
17
- ).option("-d, --dictionaries [ids...]", "List of dictionary IDs to push").option(
18
- "-r, --deleteLocaleDictionary",
19
- "Delete the local dictionaries after pushing"
20
- ).option(
21
- "-k, --keepLocaleDictionary",
22
- "Keep the local dictionaries after pushing"
23
- ).option("-e, --env [env]", "Environment").action(push);
114
+ const buildOptions = {
115
+ description: "Build the dictionaries",
116
+ options: [["-w, --watch", "Watch for changes"]]
117
+ };
118
+ const dictionariesBuildCmd = dictionariesProgram.command("build").description(buildOptions.description);
119
+ applyOptions(dictionariesBuildCmd, buildOptions.options);
120
+ applyConfigOptions(dictionariesBuildCmd);
121
+ dictionariesBuildCmd.action((options) => {
122
+ build({
123
+ ...options,
124
+ configOptions: extractConfigOptions(options)
125
+ });
126
+ });
127
+ const rootBuildCmd = program.command("build").description(buildOptions.description);
128
+ applyOptions(rootBuildCmd, buildOptions.options);
129
+ applyConfigOptions(rootBuildCmd);
130
+ rootBuildCmd.action((options) => {
131
+ build({
132
+ ...options,
133
+ configOptions: extractConfigOptions(options)
134
+ });
135
+ });
136
+ const pullOptions = {
137
+ description: "Pull dictionaries from the server",
138
+ options: [
139
+ ["-d, --dictionaries [ids...]", "List of dictionary IDs to pull"],
140
+ ["--newDictionariesPath [path]", "Path to save the new dictionaries"]
141
+ ]
142
+ };
143
+ const dictionariesPullCmd = dictionariesProgram.command("pull").description(pullOptions.description);
144
+ applyOptions(dictionariesPullCmd, pullOptions.options);
145
+ applyConfigOptions(dictionariesPullCmd);
146
+ dictionariesPullCmd.action((options) => {
147
+ pull({
148
+ ...options,
149
+ configOptions: {
150
+ ...options.configOptions,
151
+ baseDir: options.baseDir
152
+ }
153
+ });
154
+ });
155
+ const rootPullCmd = program.command("pull").description(pullOptions.description);
156
+ applyOptions(rootPullCmd, pullOptions.options);
157
+ applyConfigOptions(rootPullCmd);
158
+ rootPullCmd.action((options) => {
159
+ pull({
160
+ ...options,
161
+ configOptions: extractConfigOptions(options)
162
+ });
163
+ });
164
+ const pushOptions = {
165
+ description: "Push all dictionaries. Create or update the pushed dictionaries",
166
+ options: [
167
+ ["-d, --dictionaries [ids...]", "List of dictionary IDs to push"],
168
+ [
169
+ "-r, --deleteLocaleDictionary",
170
+ "Delete the local dictionaries after pushing"
171
+ ],
172
+ [
173
+ "-k, --keepLocaleDictionary",
174
+ "Keep the local dictionaries after pushing"
175
+ ]
176
+ ]
177
+ };
178
+ const dictionariesPushCmd = dictionariesProgram.command("push").description(pushOptions.description);
179
+ applyOptions(dictionariesPushCmd, pushOptions.options);
180
+ applyConfigOptions(dictionariesPushCmd);
181
+ applyGitOptions(dictionariesPushCmd);
182
+ dictionariesPushCmd.action(
183
+ (options) => push({
184
+ ...options,
185
+ gitOptions: extractGitOptions(options),
186
+ configOptions: extractConfigOptions(options)
187
+ })
188
+ );
189
+ const rootPushCmd = program.command("push").description(pushOptions.description);
190
+ applyOptions(rootPushCmd, pushOptions.options);
191
+ applyConfigOptions(rootPushCmd);
192
+ applyGitOptions(rootPushCmd);
193
+ rootPushCmd.action(
194
+ (options) => push({
195
+ ...options,
196
+ gitOptions: extractGitOptions(options),
197
+ configOptions: extractConfigOptions(options)
198
+ })
199
+ );
24
200
  const configurationProgram = program.command("configuration").alias("config").alias("conf").description("Configuration operations");
25
- configurationProgram.command("get").description("Get the configuration").option("--env-file [envFile]", "Environment file").option("--verbose", "Verbose").option("-e, --env [env]", "Environment").action(getConfig);
26
- configurationProgram.command("push").description("Push the configuration").option("--env-file [envFile]", "Environment file").option("--verbose", "Verbose").option("-e, --env [env]", "Environment").action(pushConfig);
201
+ const configGetCmd = configurationProgram.command("get").description("Get the configuration");
202
+ applyConfigOptions(configGetCmd);
203
+ configGetCmd.action((options) => {
204
+ getConfig({
205
+ ...options,
206
+ configOptions: extractConfigOptions(options)
207
+ });
208
+ });
209
+ const configPushCmd = configurationProgram.command("push").description("Push the configuration");
210
+ applyConfigOptions(configPushCmd);
211
+ configPushCmd.action((options) => {
212
+ pushConfig({
213
+ ...options,
214
+ configOptions: extractConfigOptions(options)
215
+ });
216
+ });
27
217
  program.command("content list").description("List the content declaration files").action(listContentDeclaration);
28
- program.command("audit").description("Audit the dictionaries").option("-f, --files [files...]", "List of Dictionary files to audit").option(
29
- "--exclude [excludedGlobs...]",
30
- "Globs pattern to exclude from the audit"
31
- ).option("-m, --model [model]", "Model").option("-p, --custom-prompt [prompt]", "Custom prompt").option("-l, --async-limit [asyncLimit]", "Async limit").option("-k, --open-ai-api-key [openAiApiKey]", "OpenAI API key").option("-e, --env [env]", "Environment").action(audit);
218
+ const fillProgram = program.command("fill").description("Fill the dictionaries").option("-f, --file [files...]", "List of Dictionary files to fill").option("--source-locale [sourceLocale]", "Source locale to translate from").option(
219
+ "--output-locales [outputLocales...]",
220
+ "Target locales to translate to"
221
+ ).option(
222
+ "--mode [mode]",
223
+ "Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys",
224
+ "review"
225
+ ).option("--keys [keys...]", "Filter dictionaries based on keys").option(
226
+ "--excluded-keys [excludedKeys...]",
227
+ "Filter out dictionaries based on keys"
228
+ ).option(
229
+ "--path-filter [pathFilters...]",
230
+ "Filter dictionaries based on glob pattern"
231
+ );
232
+ applyConfigOptions(fillProgram);
233
+ applyAIOptions(fillProgram);
234
+ applyGitOptions(fillProgram);
235
+ fillProgram.action(
236
+ (options) => fill({
237
+ ...options,
238
+ aiOptions: extractAiOptions(options),
239
+ gitOptions: extractGitOptions(options),
240
+ configOptions: extractConfigOptions(options)
241
+ })
242
+ );
32
243
  program.parse(process.argv);
33
244
  return program;
34
245
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { audit } from './audit';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version('1.0.0').description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n dictionariesProgram\n .command('build')\n .description('Build the dictionaries')\n .option('-w, --watch', 'Watch for changes')\n .option('-e, --env [env]', 'Environment')\n .action(build);\n\n dictionariesProgram\n .command('pull')\n .option('-d, --dictionaries [ids...]', 'List of dictionary IDs to pull')\n .option('--newDictionariesPath [path]', 'Path to save the new dictionaries')\n .option('-e, --env [env]', 'Environment')\n .action(pull);\n\n // Define the main `push` command\n dictionariesProgram\n .command('push')\n .description(\n 'Push all dictionaries. Create or update the pushed dictionaries'\n )\n .option('-d, --dictionaries [ids...]', 'List of dictionary IDs to push')\n .option(\n '-r, --deleteLocaleDictionary',\n 'Delete the local dictionaries after pushing'\n )\n .option(\n '-k, --keepLocaleDictionary',\n 'Keep the local dictionaries after pushing'\n )\n .option('-e, --env [env]', 'Environment')\n .action(push);\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n configurationProgram\n .command('get')\n .description('Get the configuration')\n .option('--env-file [envFile]', 'Environment file')\n .option('--verbose', 'Verbose')\n .option('-e, --env [env]', 'Environment')\n .action(getConfig);\n\n // Define the `push config` subcommand and add it to the `push` command\n configurationProgram\n .command('push')\n .description('Push the configuration')\n .option('--env-file [envFile]', 'Environment file')\n .option('--verbose', 'Verbose')\n .option('-e, --env [env]', 'Environment')\n .action(pushConfig);\n\n /**\n * CONTENT DECLARATION\n */\n\n program\n .command('content list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n program\n .command('audit')\n .description('Audit the dictionaries')\n .option('-f, --files [files...]', 'List of Dictionary files to audit')\n .option(\n '--exclude [excludedGlobs...]',\n 'Globs pattern to exclude from the audit'\n )\n .option('-m, --model [model]', 'Model')\n .option('-p, --custom-prompt [prompt]', 'Custom prompt')\n .option('-l, --async-limit [asyncLimit]', 'Async limit')\n .option('-k, --open-ai-api-key [openAiApiKey]', 'OpenAI API key')\n .option('-e, --env [env]', 'Environment')\n .action(audit);\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,SAAS,8BAA8B;AACvC,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAUpB,MAAM,SAAS,MAAe;AACnC,QAAM,UAAU,IAAI,QAAQ;AAE5B,UAAQ,QAAQ,OAAO,EAAE,YAAY,cAAc;AAMnD,QAAM,sBAAsB,QACzB,QAAQ,YAAY,EACpB,MAAM,cAAc,EACpB,MAAM,KAAK,EACX,YAAY,yBAAyB;AAExC,sBACG,QAAQ,OAAO,EACf,YAAY,wBAAwB,EACpC,OAAO,eAAe,mBAAmB,EACzC,OAAO,mBAAmB,aAAa,EACvC,OAAO,KAAK;AAEf,sBACG,QAAQ,MAAM,EACd,OAAO,+BAA+B,gCAAgC,EACtE,OAAO,gCAAgC,mCAAmC,EAC1E,OAAO,mBAAmB,aAAa,EACvC,OAAO,IAAI;AAGd,sBACG,QAAQ,MAAM,EACd;AAAA,IACC;AAAA,EACF,EACC,OAAO,+BAA+B,gCAAgC,EACtE;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,mBAAmB,aAAa,EACvC,OAAO,IAAI;AAOd,QAAM,uBAAuB,QAC1B,QAAQ,eAAe,EACvB,MAAM,QAAQ,EACd,MAAM,MAAM,EACZ,YAAY,0BAA0B;AAEzC,uBACG,QAAQ,KAAK,EACb,YAAY,uBAAuB,EACnC,OAAO,wBAAwB,kBAAkB,EACjD,OAAO,aAAa,SAAS,EAC7B,OAAO,mBAAmB,aAAa,EACvC,OAAO,SAAS;AAGnB,uBACG,QAAQ,MAAM,EACd,YAAY,wBAAwB,EACpC,OAAO,wBAAwB,kBAAkB,EACjD,OAAO,aAAa,SAAS,EAC7B,OAAO,mBAAmB,aAAa,EACvC,OAAO,UAAU;AAMpB,UACG,QAAQ,cAAc,EACtB,YAAY,oCAAoC,EAChD,OAAO,sBAAsB;AAEhC,UACG,QAAQ,OAAO,EACf,YAAY,wBAAwB,EACpC,OAAO,0BAA0B,mCAAmC,EACpE;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,uBAAuB,OAAO,EACrC,OAAO,gCAAgC,eAAe,EACtD,OAAO,kCAAkC,aAAa,EACtD,OAAO,wCAAwC,gBAAgB,EAC/D,OAAO,mBAAmB,aAAa,EACvC,OAAO,KAAK;AAEf,UAAQ,MAAM,QAAQ,IAAI;AAE1B,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import type { AIOptions } from '@intlayer/api';\nimport { GetConfigurationOptions } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n DiffMode,\n ListGitFilesOptions,\n} from '../../chokidar/dist/types/listGitFiles';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { fill, FillOptions } from './fill';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\n\nconst CJS_ESM_Dirname = __dirname ?? dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(\n readFileSync(resolve(CJS_ESM_Dirname, '../../package.json'), 'utf8')\n);\n\nconst logOptions = [\n ['--verbose', 'Verbose'],\n ['--prefix [prefix]', 'Prefix'],\n];\n\nconst configurationOptions = [\n ['--env-file [envFile]', 'Environment file'],\n ['-e, --env [env]', 'Environment'],\n ['--base-dir [baseDir]', 'Base directory'],\n ...logOptions,\n];\n\nconst aiOptions = [\n ['--provider [provider]', 'Provider'],\n ['--temperature [temperature]', 'Temperature'],\n ['--model [model]', 'Model'],\n ['--api-key [apiKey]', 'Provider API key'],\n ['--custom-prompt [prompt]', 'Custom prompt'],\n ['--application-context [applicationContext]', 'Application context'],\n];\n\nconst gitOptions = [\n ['--git-diff [gitDiff]', 'Git diff mode - Check git diff between two refs'],\n ['--git-diff-base [gitDiffBase]', 'Git diff base ref'],\n ['--git-diff-current [gitDiffCurrent]', 'Git diff current ref'],\n ['--uncommitted [uncommitted]', 'Uncommitted'],\n ['--unpushed [unpushed]', 'Unpushed'],\n ['--untracked [untracked]', 'Untracked'],\n];\n\n/**\n * Helper functions to apply common options to commands\n */\nconst applyOptions = (command: Command, options: string[][]) => {\n options.forEach(([flag, description]) => command.option(flag, description));\n return command;\n};\n\nconst removeUndefined = <T extends Record<string, any>>(obj: T): T =>\n Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined)\n ) as T;\n\nconst applyConfigOptions = (command: Command) =>\n applyOptions(command, configurationOptions);\nconst applyAIOptions = (command: Command) => applyOptions(command, aiOptions);\nconst applyGitOptions = (command: Command) => applyOptions(command, gitOptions);\n\nconst extractAiOptions = (options: AIOptions) => {\n const isOptionEmpty = !Object.values(options).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const { apiKey, provider, model, temperature, applicationContext } = options;\n\n return removeUndefined({\n apiKey: apiKey ?? configuration.ai?.apiKey,\n provider: provider ?? configuration.ai?.provider,\n model: model ?? configuration.ai?.model,\n temperature: temperature ?? configuration.ai?.temperature,\n applicationContext:\n applicationContext ?? configuration.ai?.applicationContext,\n });\n};\n\ntype GitOptions = {\n gitDiff?: boolean;\n gitDiffBase?: string;\n gitDiffCurrent?: string;\n uncommitted?: boolean;\n unpushed?: boolean;\n untracked?: boolean;\n};\n\nconst extractGitOptions = (\n options: GitOptions\n): ListGitFilesOptions | undefined => {\n const isOptionEmpty = !Object.values(options).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const {\n gitDiff,\n gitDiffBase,\n gitDiffCurrent,\n uncommitted,\n unpushed,\n untracked,\n } = options;\n\n const mode = [\n gitDiff && 'gitDiff',\n uncommitted && 'uncommitted',\n unpushed && 'unpushed',\n untracked && 'untracked',\n ].filter(Boolean) as DiffMode[];\n\n return removeUndefined({\n mode,\n baseRef: gitDiffBase,\n currentRef: gitDiffCurrent,\n absolute: true,\n });\n};\n\ntype LogOptions = {\n prefix?: string;\n verbose?: boolean;\n};\n\nexport type ConfigurationOptions = {\n baseDir?: string;\n env?: string;\n envFile?: string;\n} & LogOptions;\n\nconst extractConfigOptions = (\n options: ConfigurationOptions\n): GetConfigurationOptions | undefined => {\n const { baseDir, env, envFile, verbose, prefix } = options;\n\n const log = {\n prefix: prefix ?? '', // Should not consider the prefix set in the intlayer configuration file\n verbose,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n });\n};\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version(packageJson.version).description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n // Dictionary build command\n const buildOptions = {\n description: 'Build the dictionaries',\n options: [['-w, --watch', 'Watch for changes']],\n };\n\n // Add build command to dictionaries program\n const dictionariesBuildCmd = dictionariesProgram\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(dictionariesBuildCmd, buildOptions.options);\n applyConfigOptions(dictionariesBuildCmd);\n dictionariesBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootBuildCmd = program\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(rootBuildCmd, buildOptions.options);\n applyConfigOptions(rootBuildCmd);\n rootBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary pull command\n const pullOptions = {\n description: 'Pull dictionaries from the server',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to pull'],\n ['--newDictionariesPath [path]', 'Path to save the new dictionaries'],\n ],\n };\n\n // Add pull command to dictionaries program\n const dictionariesPullCmd = dictionariesProgram\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(dictionariesPullCmd, pullOptions.options);\n applyConfigOptions(dictionariesPullCmd);\n dictionariesPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: {\n ...options.configOptions,\n baseDir: options.baseDir,\n },\n });\n });\n\n // Add pull command to root program as well\n const rootPullCmd = program\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(rootPullCmd, pullOptions.options);\n applyConfigOptions(rootPullCmd);\n rootPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary push command\n const pushOptions = {\n description:\n 'Push all dictionaries. Create or update the pushed dictionaries',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to push'],\n [\n '-r, --deleteLocaleDictionary',\n 'Delete the local dictionaries after pushing',\n ],\n [\n '-k, --keepLocaleDictionary',\n 'Keep the local dictionaries after pushing',\n ],\n ],\n };\n\n // Add push command to dictionaries program\n const dictionariesPushCmd = dictionariesProgram\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(dictionariesPushCmd, pushOptions.options);\n applyConfigOptions(dictionariesPushCmd);\n applyGitOptions(dictionariesPushCmd);\n\n dictionariesPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n // Add push command to root program as well\n const rootPushCmd = program\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(rootPushCmd, pushOptions.options);\n applyConfigOptions(rootPushCmd);\n applyGitOptions(rootPushCmd);\n\n rootPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n const configGetCmd = configurationProgram\n .command('get')\n .description('Get the configuration');\n\n applyConfigOptions(configGetCmd);\n configGetCmd.action((options) => {\n getConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Define the `push config` subcommand and add it to the `push` command\n const configPushCmd = configurationProgram\n .command('push')\n .description('Push the configuration');\n\n applyConfigOptions(configPushCmd);\n configPushCmd.action((options) => {\n pushConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n /**\n * CONTENT DECLARATION\n */\n\n program\n .command('content list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n const fillProgram = program\n .command('fill')\n .description('Fill the dictionaries')\n .option('-f, --file [files...]', 'List of Dictionary files to fill')\n .option('--source-locale [sourceLocale]', 'Source locale to translate from')\n .option(\n '--output-locales [outputLocales...]',\n 'Target locales to translate to'\n )\n .option(\n '--mode [mode]',\n 'Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys',\n 'review'\n )\n .option('--keys [keys...]', 'Filter dictionaries based on keys')\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--path-filter [pathFilters...]',\n 'Filter dictionaries based on glob pattern'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) =>\n fill({\n ...options,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"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","names":[]}