@localheroai/cli 0.0.5 → 0.0.7

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 (116) hide show
  1. package/{README → README.md} +28 -10
  2. package/dist/api/auth.d.ts +2 -0
  3. package/dist/api/auth.js +28 -0
  4. package/dist/api/auth.js.map +1 -0
  5. package/dist/api/client.d.ts +3 -0
  6. package/dist/api/client.js +80 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/api/imports.d.ts +5 -0
  9. package/dist/api/imports.js +43 -0
  10. package/dist/api/imports.js.map +1 -0
  11. package/dist/api/projects.d.ts +2 -0
  12. package/dist/api/projects.js +42 -0
  13. package/dist/api/projects.js.map +1 -0
  14. package/dist/api/translations.d.ts +15 -0
  15. package/dist/api/translations.js +71 -0
  16. package/dist/api/translations.js.map +1 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +79 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands/_sync.js +22 -0
  21. package/dist/commands/_sync.js.map +1 -0
  22. package/dist/commands/_translate.js +3 -0
  23. package/dist/commands/_translate.js.map +1 -0
  24. package/dist/commands/init.d.ts +1 -0
  25. package/dist/commands/init.js +439 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/login.d.ts +16 -0
  28. package/dist/commands/login.js +58 -0
  29. package/dist/commands/login.js.map +1 -0
  30. package/dist/commands/pull.js +22 -0
  31. package/dist/commands/pull.js.map +1 -0
  32. package/dist/commands/push.js +56 -0
  33. package/dist/commands/push.js.map +1 -0
  34. package/dist/commands/sync.d.ts +20 -0
  35. package/dist/commands/sync.js +22 -0
  36. package/dist/commands/sync.js.map +1 -0
  37. package/dist/commands/translate.d.ts +14 -0
  38. package/dist/commands/translate.js +152 -0
  39. package/dist/commands/translate.js.map +1 -0
  40. package/dist/index.d.ts +5 -0
  41. package/dist/index.js +8 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/types/index.d.ts +75 -0
  44. package/dist/types/index.js +17 -0
  45. package/dist/types/index.js.map +1 -0
  46. package/dist/types/translate/index.js +2 -0
  47. package/dist/types/translate/index.js.map +1 -0
  48. package/dist/utils/auth.d.ts +2 -0
  49. package/dist/utils/auth.js +29 -0
  50. package/dist/utils/auth.js.map +1 -0
  51. package/dist/utils/common.js +9 -0
  52. package/dist/utils/common.js.map +1 -0
  53. package/dist/utils/config.d.ts +23 -0
  54. package/dist/utils/config.js +137 -0
  55. package/dist/utils/config.js.map +1 -0
  56. package/dist/utils/errors.js +37 -0
  57. package/dist/utils/errors.js.map +1 -0
  58. package/dist/utils/files.d.ts +32 -0
  59. package/dist/utils/files.js +355 -0
  60. package/dist/utils/files.js.map +1 -0
  61. package/dist/utils/git.d.ts +21 -0
  62. package/dist/utils/git.js +87 -0
  63. package/dist/utils/git.js.map +1 -0
  64. package/dist/utils/github.d.ts +241 -0
  65. package/dist/utils/github.js +161 -0
  66. package/dist/utils/github.js.map +1 -0
  67. package/dist/utils/import-service.d.ts +4 -0
  68. package/dist/utils/import-service.js +218 -0
  69. package/dist/utils/import-service.js.map +1 -0
  70. package/dist/utils/prompt-service.d.ts +44 -0
  71. package/dist/utils/prompt-service.js +104 -0
  72. package/dist/utils/prompt-service.js.map +1 -0
  73. package/dist/utils/sync-service.d.ts +58 -0
  74. package/dist/utils/sync-service.js +159 -0
  75. package/dist/utils/sync-service.js.map +1 -0
  76. package/dist/utils/translation-processor.js +197 -0
  77. package/dist/utils/translation-processor.js.map +1 -0
  78. package/dist/utils/translation-updater/common.d.ts +6 -0
  79. package/{src → dist}/utils/translation-updater/common.js +16 -10
  80. package/dist/utils/translation-updater/common.js.map +1 -0
  81. package/dist/utils/translation-updater/index.d.ts +5 -0
  82. package/{src → dist}/utils/translation-updater/index.js +21 -9
  83. package/dist/utils/translation-updater/index.js.map +1 -0
  84. package/dist/utils/translation-updater/json-handler.d.ts +5 -0
  85. package/dist/utils/translation-updater/json-handler.js +123 -0
  86. package/dist/utils/translation-updater/json-handler.js.map +1 -0
  87. package/dist/utils/translation-updater/yaml-handler.d.ts +5 -0
  88. package/dist/utils/translation-updater/yaml-handler.js +193 -0
  89. package/dist/utils/translation-updater/yaml-handler.js.map +1 -0
  90. package/dist/utils/translation-utils.d.ts +30 -0
  91. package/dist/utils/translation-utils.js +334 -0
  92. package/dist/utils/translation-utils.js.map +1 -0
  93. package/dist/utils/updater.js +38 -0
  94. package/dist/utils/updater.js.map +1 -0
  95. package/package.json +26 -26
  96. package/src/api/auth.js +0 -24
  97. package/src/api/client.js +0 -83
  98. package/src/api/imports.js +0 -22
  99. package/src/api/projects.js +0 -24
  100. package/src/api/translations.js +0 -58
  101. package/src/cli.js +0 -78
  102. package/src/commands/init.js +0 -485
  103. package/src/commands/login.js +0 -80
  104. package/src/commands/sync.js +0 -28
  105. package/src/commands/translate.js +0 -267
  106. package/src/utils/auth.js +0 -23
  107. package/src/utils/config.js +0 -125
  108. package/src/utils/files.js +0 -381
  109. package/src/utils/git.js +0 -72
  110. package/src/utils/github.js +0 -128
  111. package/src/utils/import-service.js +0 -128
  112. package/src/utils/prompt-service.js +0 -67
  113. package/src/utils/sync-service.js +0 -147
  114. package/src/utils/translation-updater/json-handler.js +0 -111
  115. package/src/utils/translation-updater/yaml-handler.js +0 -207
  116. package/src/utils/translation-utils.js +0 -278
@@ -0,0 +1,334 @@
1
+ import path from 'path';
2
+ import { flattenTranslations, parseFile } from './files.js';
3
+ /**
4
+ * Find keys in source that are missing from target
5
+ * @param sourceKeys The source translation keys
6
+ * @param targetKeys The target translation keys
7
+ * @returns Object containing missing and skipped keys
8
+ */
9
+ export function findMissingTranslations(sourceKeys, targetKeys) {
10
+ const missingKeys = {};
11
+ const skippedKeys = {};
12
+ for (const [key, details] of Object.entries(sourceKeys)) {
13
+ if (typeof details === 'string') {
14
+ if (details.toLowerCase().includes('wip_') ||
15
+ details.toLowerCase().includes('_wip') ||
16
+ details.toLowerCase().includes('__skip_translation__')) {
17
+ skippedKeys[key] = {
18
+ value: details,
19
+ reason: 'wip'
20
+ };
21
+ continue;
22
+ }
23
+ if (!targetKeys[key]) {
24
+ missingKeys[key] = {
25
+ value: details,
26
+ sourceKey: key
27
+ };
28
+ }
29
+ continue;
30
+ }
31
+ if (typeof details === 'boolean') {
32
+ if (!targetKeys[key]) {
33
+ missingKeys[key] = {
34
+ value: details,
35
+ sourceKey: key
36
+ };
37
+ }
38
+ continue;
39
+ }
40
+ if (typeof details === 'object' && details !== null &&
41
+ typeof details.value === 'string' &&
42
+ (details.value.toLowerCase().includes('wip_') || details.value.toLowerCase().includes('_wip') ||
43
+ details.value.toLowerCase().includes('__skip_translation__'))) {
44
+ skippedKeys[key] = {
45
+ ...details,
46
+ reason: 'wip'
47
+ };
48
+ continue;
49
+ }
50
+ if (!targetKeys[key]) {
51
+ if (typeof details === 'object' && details !== null && 'value' in details) {
52
+ missingKeys[key] = {
53
+ ...details,
54
+ sourceKey: key
55
+ };
56
+ }
57
+ else {
58
+ missingKeys[key] = {
59
+ value: details,
60
+ sourceKey: key
61
+ };
62
+ }
63
+ }
64
+ }
65
+ return { missingKeys, skippedKeys };
66
+ }
67
+ /**
68
+ * Find all missing translations grouped by locale and source file
69
+ * @param sourceFiles Array of source translation files
70
+ * @param targetFilesByLocale Record of target files grouped by locale
71
+ * @param config Project configuration with sourceLocale and outputLocales
72
+ * @param verbose Whether to show verbose output
73
+ * @param logger Optional logger for console output
74
+ * @returns Record of missing translations by locale and source file
75
+ */
76
+ export function findMissingTranslationsByLocale(sourceFiles, targetFilesByLocale, config, verbose, logger = console) {
77
+ const missingByLocale = {};
78
+ for (const sourceFile of sourceFiles) {
79
+ if (!sourceFile.content)
80
+ continue;
81
+ const sourceContentRaw = Buffer.from(sourceFile.content, 'base64').toString();
82
+ const sourceContent = parseFile(sourceContentRaw, sourceFile.format, sourceFile.path);
83
+ const sourceKeys = flattenTranslations(sourceContent[config.sourceLocale] || sourceContent);
84
+ for (const targetLocale of config.outputLocales) {
85
+ const targetFiles = targetFilesByLocale[targetLocale] || [];
86
+ const result = processLocaleTranslations(sourceKeys, targetLocale, targetFiles, sourceFile, config.sourceLocale);
87
+ if (Object.keys(result.missingKeys).length > 0) {
88
+ const sourceFilePath = sourceFile.path;
89
+ const localeSourceKey = `${targetLocale}:${sourceFilePath}`;
90
+ // Create or update the entry for this locale and source file
91
+ if (!missingByLocale[localeSourceKey]) {
92
+ missingByLocale[localeSourceKey] = {
93
+ locale: targetLocale,
94
+ path: sourceFilePath,
95
+ targetPath: result.targetPath,
96
+ keys: {},
97
+ keyCount: 0
98
+ };
99
+ }
100
+ // Now it's safe to update since we made sure it exists
101
+ const entry = missingByLocale[localeSourceKey];
102
+ entry.keys = {
103
+ ...entry.keys,
104
+ ...result.missingKeys
105
+ };
106
+ entry.keyCount = (entry.keyCount || 0) + Object.keys(result.missingKeys).length;
107
+ }
108
+ if (verbose && Object.keys(result.skippedKeys).length > 0) {
109
+ logger.log(`\nℹ Skipped ${Object.keys(result.skippedKeys).length} keys marked as WIP in ${sourceFile.path}`);
110
+ }
111
+ }
112
+ }
113
+ return missingByLocale;
114
+ }
115
+ /**
116
+ * Batch missing keys by source file
117
+ * @param sourceFiles Array of source translation files
118
+ * @param missingByLocale Record of missing keys by locale and source file
119
+ * @returns Result containing batches and errors
120
+ */
121
+ export function batchKeysWithMissing(sourceFiles, missingByLocale) {
122
+ const MAX_BATCH_SIZE = 100;
123
+ const batches = [];
124
+ const errors = [];
125
+ const entriesBySourceFile = {};
126
+ // Group entries by source file
127
+ for (const [localeSourceKey, entry] of Object.entries(missingByLocale)) {
128
+ const { path: sourceFilePath } = entry;
129
+ if (!entriesBySourceFile[sourceFilePath]) {
130
+ entriesBySourceFile[sourceFilePath] = {
131
+ localeEntries: [],
132
+ locales: new Set(),
133
+ keys: {}
134
+ };
135
+ }
136
+ entriesBySourceFile[sourceFilePath].localeEntries.push(localeSourceKey);
137
+ entriesBySourceFile[sourceFilePath].locales.add(entry.locale);
138
+ for (const [key, value] of Object.entries(entry.keys)) {
139
+ if (!entriesBySourceFile[sourceFilePath].keys[key]) {
140
+ entriesBySourceFile[sourceFilePath].keys[key] = {};
141
+ }
142
+ entriesBySourceFile[sourceFilePath].keys[key][entry.locale] = value;
143
+ }
144
+ }
145
+ // Process each source file
146
+ for (const [sourceFilePath, data] of Object.entries(entriesBySourceFile)) {
147
+ const sourceFile = sourceFiles.find(f => f.path === sourceFilePath);
148
+ if (!sourceFile) {
149
+ errors.push({
150
+ type: 'missing_source_file',
151
+ message: `No source file found for path: ${sourceFilePath}`,
152
+ path: sourceFilePath
153
+ });
154
+ continue;
155
+ }
156
+ const allKeys = Object.entries(data.keys);
157
+ const chunkedKeys = [];
158
+ for (let i = 0; i < allKeys.length; i += MAX_BATCH_SIZE) {
159
+ chunkedKeys.push(allKeys.slice(i, i + MAX_BATCH_SIZE));
160
+ }
161
+ for (const keyChunk of chunkedKeys) {
162
+ const contentObj = { keys: {} };
163
+ for (const [key, translations] of keyChunk) {
164
+ const value = Object.values(translations)[0];
165
+ let extractedValue;
166
+ if (Array.isArray(value)) {
167
+ extractedValue = value;
168
+ }
169
+ else if (typeof value === 'boolean') {
170
+ extractedValue = value;
171
+ }
172
+ else if (typeof value === 'string') {
173
+ extractedValue = value;
174
+ }
175
+ else if (typeof value === 'object' && value !== null) {
176
+ if ('value' in value) {
177
+ extractedValue = value.value;
178
+ }
179
+ else {
180
+ extractedValue = JSON.stringify(value);
181
+ }
182
+ }
183
+ else {
184
+ extractedValue = String(value);
185
+ }
186
+ contentObj.keys[key] = {
187
+ value: extractedValue
188
+ };
189
+ }
190
+ batches.push({
191
+ sourceFilePath,
192
+ sourceFile: {
193
+ path: sourceFile.path,
194
+ format: sourceFile.format,
195
+ content: Buffer.from(JSON.stringify(contentObj)).toString('base64')
196
+ },
197
+ localeEntries: data.localeEntries,
198
+ locales: Array.from(data.locales)
199
+ });
200
+ }
201
+ }
202
+ return { batches, errors };
203
+ }
204
+ /**
205
+ * Find a target file that corresponds to the source file
206
+ * @param targetFiles Array of target translation files
207
+ * @param targetLocale The target locale
208
+ * @param sourceFile The source file
209
+ * @param sourceLocale The source locale
210
+ * @returns The matching target file, or undefined if not found
211
+ */
212
+ export function findTargetFile(targetFiles, targetLocale, sourceFile, sourceLocale) {
213
+ // First try exact directory matching (existing logic)
214
+ let found = targetFiles.find(f => f.locale === targetLocale &&
215
+ path.dirname(f.path) === path.dirname(sourceFile.path) &&
216
+ path.basename(f.path, path.extname(f.path)) === path.basename(sourceFile.path, path.extname(sourceFile.path)).replace(sourceLocale, targetLocale));
217
+ if (found)
218
+ return found;
219
+ // Then try filename-based matching regardless of directory (existing logic)
220
+ found = targetFiles.find(f => f.locale === targetLocale &&
221
+ path.basename(f.path, path.extname(f.path)) === path.basename(sourceFile.path, path.extname(sourceFile.path)).replace(sourceLocale, targetLocale));
222
+ if (found)
223
+ return found;
224
+ const sourceDirParts = path.dirname(sourceFile.path).split(path.sep);
225
+ const sourceFileBaseName = path.basename(sourceFile.path, path.extname(sourceFile.path));
226
+ // Check for corresponding file in subdirectories or parent directories
227
+ return targetFiles.find(f => {
228
+ if (f.locale !== targetLocale)
229
+ return false;
230
+ // Handle cases where files are in different subdirectories
231
+ const targetDirParts = path.dirname(f.path).split(path.sep);
232
+ const targetFileBaseName = path.basename(f.path, path.extname(f.path));
233
+ if (sourceFileBaseName === sourceLocale &&
234
+ targetFileBaseName === targetLocale &&
235
+ sourceDirParts.length === targetDirParts.length) {
236
+ return true;
237
+ }
238
+ // Nested directory structure
239
+ if (sourceDirParts.includes(sourceLocale) && targetDirParts.includes(targetLocale)) {
240
+ const sourceBasePath = sourceDirParts.slice(0, sourceDirParts.indexOf(sourceLocale)).join(path.sep);
241
+ const targetBasePath = targetDirParts.slice(0, targetDirParts.indexOf(targetLocale)).join(path.sep);
242
+ return sourceBasePath === targetBasePath &&
243
+ sourceFileBaseName === targetFileBaseName;
244
+ }
245
+ return false;
246
+ });
247
+ }
248
+ /**
249
+ * Generate a target file path based on source file and locales
250
+ * @param sourceFile The source translation file
251
+ * @param targetLocale The target locale
252
+ * @param sourceLocale The source locale
253
+ * @returns The generated target file path
254
+ */
255
+ export function generateTargetPath(sourceFile, targetLocale, sourceLocale) {
256
+ const sourceExt = path.extname(sourceFile.path);
257
+ const sourceDir = path.dirname(sourceFile.path);
258
+ const sourceName = path.basename(sourceFile.path, sourceExt);
259
+ // Case 1: File is named exactly as the source locale (e.g., "en.yml")
260
+ if (sourceName === sourceLocale) {
261
+ return path.join(sourceDir, `${targetLocale}${sourceExt}`);
262
+ }
263
+ // Case 2: File ends with .locale (e.g., "translations.en.yml")
264
+ if (sourceName.endsWith(`.${sourceLocale}`)) {
265
+ const baseName = sourceName.slice(0, -(sourceLocale.length + 1));
266
+ return path.join(sourceDir, `${baseName}.${targetLocale}${sourceExt}`);
267
+ }
268
+ // Case 3: File uses hyphen-locale format (e.g., "translations-en.yml")
269
+ if (sourceName.includes(`-${sourceLocale}`)) {
270
+ const baseName = sourceName.slice(0, -(sourceLocale.length + 1));
271
+ return path.join(sourceDir, `${baseName}-${targetLocale}${sourceExt}`);
272
+ }
273
+ // Case 4: Source locale is a directory name
274
+ const sourceParentDir = path.basename(sourceDir);
275
+ if (sourceParentDir === sourceLocale) {
276
+ const grandParentDir = path.dirname(sourceDir);
277
+ return path.join(grandParentDir, targetLocale, path.basename(sourceFile.path));
278
+ }
279
+ // Default case: If none of the above patterns match,
280
+ // construct the target path by replacing the locale in the filename only
281
+ const dirPath = path.dirname(sourceFile.path);
282
+ const fileName = path.basename(sourceFile.path);
283
+ const localeRegex = new RegExp(`\\b${sourceLocale}\\b`, 'g');
284
+ const newFileName = fileName.replace(localeRegex, targetLocale);
285
+ return path.join(dirPath, newFileName);
286
+ }
287
+ /**
288
+ * Process target content to extract translation keys
289
+ * @param targetContent The target content object
290
+ * @param targetLocale The target locale
291
+ * @returns Flattened translations
292
+ */
293
+ export function processTargetContent(targetContent, targetLocale) {
294
+ if (targetContent[targetLocale]) {
295
+ return flattenTranslations(targetContent[targetLocale]);
296
+ }
297
+ return flattenTranslations(targetContent);
298
+ }
299
+ /**
300
+ * Process translations for a specific locale
301
+ * @param sourceKeys The source translation keys
302
+ * @param targetLocale The target locale
303
+ * @param targetFiles Array of target translation files
304
+ * @param sourceFile The source file
305
+ * @param sourceLocale The source locale
306
+ * @returns Result with target path and missing/skipped keys
307
+ */
308
+ export function processLocaleTranslations(sourceKeys, targetLocale, targetFiles, sourceFile, sourceLocale) {
309
+ try {
310
+ const targetFile = findTargetFile(targetFiles, targetLocale, sourceFile, sourceLocale);
311
+ let targetKeys = {};
312
+ let targetPath = '';
313
+ if (targetFile) {
314
+ const targetContentRaw = Buffer.from(targetFile.content || '', 'base64').toString();
315
+ const targetContent = parseFile(targetContentRaw, targetFile.format, targetFile.path);
316
+ targetKeys = processTargetContent(targetContent, targetLocale);
317
+ targetPath = targetFile.path;
318
+ }
319
+ else {
320
+ targetPath = generateTargetPath(sourceFile, targetLocale, sourceLocale);
321
+ }
322
+ const { missingKeys, skippedKeys } = findMissingTranslations(sourceKeys, targetKeys);
323
+ return {
324
+ targetPath,
325
+ missingKeys,
326
+ skippedKeys,
327
+ targetFile
328
+ };
329
+ }
330
+ catch (error) {
331
+ throw new Error(`Failed to process translations for ${targetLocale}: ${error.message}`);
332
+ }
333
+ }
334
+ //# sourceMappingURL=translation-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-utils.js","sourceRoot":"","sources":["../../src/utils/translation-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { readTranslationFile } from './files.js';
2
+ import { updateTranslationFile } from './translation-updater/index.js';
3
+ /**
4
+ * Apply translation updates to files
5
+ * @param files Array of translation files to update
6
+ * @returns Result of the update operation
7
+ */
8
+ export async function applyTranslationUpdates(files) {
9
+ const errors = [];
10
+ try {
11
+ for (const file of files) {
12
+ try {
13
+ const currentFile = await readTranslationFile(file.path);
14
+ await updateTranslationFile(file.path, file.translations || {}, file.locale, currentFile.path);
15
+ }
16
+ catch (error) {
17
+ errors.push({
18
+ path: file.path,
19
+ message: error instanceof Error ? error.message : String(error)
20
+ });
21
+ }
22
+ }
23
+ return {
24
+ success: errors.length === 0,
25
+ errors: errors.length > 0 ? errors : undefined
26
+ };
27
+ }
28
+ catch (error) {
29
+ return {
30
+ success: false,
31
+ errors: [{
32
+ path: 'unknown',
33
+ message: error instanceof Error ? error.message : String(error)
34
+ }]
35
+ };
36
+ }
37
+ }
38
+ //# sourceMappingURL=updater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updater.js","sourceRoot":"","sources":["../../src/utils/updater.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAOvE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,KAAwB;IACpE,MAAM,MAAM,GAA6C,EAAE,CAAC;IAE5D,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzD,MAAM,qBAAqB,CACzB,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,YAAY,IAAI,EAAE,EACvB,IAAI,CAAC,MAAM,EACX,WAAW,CAAC,IAAI,CACjB,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAChE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC/C,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC;oBACP,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAChE,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localheroai/cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "CLI tool for managing translations with LocalHero.ai",
5
5
  "homepage": "https://localhero.ai",
6
6
  "repository": {
@@ -8,25 +8,31 @@
8
8
  "url": "https://github.com/localheroai/cli"
9
9
  },
10
10
  "type": "module",
11
- "main": "src/index.js",
11
+ "main": "dist/index.js",
12
12
  "bin": {
13
- "localheroai": "./src/cli.js"
13
+ "localheroai": "./dist/cli.js"
14
14
  },
15
15
  "scripts": {
16
- "start": "node src/cli.js",
16
+ "build": "tsc && chmod +x dist/cli.js",
17
+ "start": "node dist/cli.js",
18
+ "dev": "tsc --watch",
19
+ "prepublishOnly": "npm run build",
17
20
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
18
- "lint": "eslint .",
19
- "postinstall": "chmod +x src/cli.js"
21
+ "lint": "eslint 'src/**/*.{js,ts}'",
22
+ "postinstall": "chmod +x dist/cli.js",
23
+ "build:run": "npm run build && npm start"
20
24
  },
21
25
  "keywords": [
22
26
  "i18n",
23
27
  "translation",
24
28
  "cli",
25
- "localization"
29
+ "localization",
30
+ "localhero.ai"
26
31
  ],
27
32
  "author": "LocalHero.ai",
28
33
  "license": "MIT",
29
34
  "dependencies": {
35
+ "@oclif/core": "^3.25.0",
30
36
  "chalk": "^5.3.0",
31
37
  "commander": "^12.0.0",
32
38
  "glob": "^10.3.10",
@@ -35,33 +41,27 @@
35
41
  },
36
42
  "devDependencies": {
37
43
  "@babel/preset-env": "^7.24.0",
44
+ "@eslint/js": "^9.24.0",
38
45
  "@inquirer/testing": "^2.1.36",
39
46
  "@jest/globals": "^29.7.0",
40
- "eslint": "^9.19.0",
47
+ "@types/inquirer": "^9.0.7",
48
+ "@types/jest": "^29.5.14",
49
+ "@types/node": "^22.14.0",
50
+ "@typescript-eslint/eslint-plugin": "^8.30.1",
51
+ "@typescript-eslint/parser": "^8.30.1",
52
+ "@typescript-eslint/typescript-estree": "^8.30.1",
53
+ "eslint": "^8.57.0",
41
54
  "globals": "^15.14.0",
42
- "jest": "^29.7.0"
55
+ "jest": "^29.7.0",
56
+ "ts-jest": "^29.1.2",
57
+ "typescript": "^5.8.3"
43
58
  },
44
59
  "engines": {
45
60
  "node": ">=22.0.0"
46
61
  },
47
62
  "files": [
48
- "src",
63
+ "dist",
49
64
  "README",
50
65
  "LICENSE"
51
- ],
52
- "jest": {
53
- "testEnvironment": "node",
54
- "transform": {},
55
- "moduleNameMapper": {
56
- "^(\\.{1,2}/.*)\\.js$": "$1"
57
- },
58
- "testMatch": [
59
- "**/tests/**/*.test.js"
60
- ],
61
- "testEnvironmentOptions": {
62
- "extensionsToTreatAsEsm": [
63
- ".js"
64
- ]
65
- }
66
- }
66
+ ]
67
67
  }
package/src/api/auth.js DELETED
@@ -1,24 +0,0 @@
1
- import { apiRequest } from './client.js';
2
-
3
- export async function verifyApiKey(apiKey) {
4
- try {
5
- return await apiRequest('/api/v1/auth/verify', {
6
- apiKey
7
- });
8
- } catch (error) {
9
- if (error.code === 'invalid_api_key') {
10
- return {
11
- error: {
12
- code: 'invalid_api_key',
13
- message: error.message
14
- }
15
- };
16
- }
17
- return {
18
- error: {
19
- code: 'verification_failed',
20
- message: error.message || 'Failed to verify API key'
21
- }
22
- };
23
- }
24
- }
package/src/api/client.js DELETED
@@ -1,83 +0,0 @@
1
- const DEFAULT_API_HOST = 'https://api.localhero.ai';
2
-
3
- export function getApiHost() {
4
- return process.env.LOCALHERO_API_HOST || DEFAULT_API_HOST;
5
- }
6
-
7
- function getNetworkErrorMessage(error) {
8
- if (error.code === 'ECONNREFUSED') {
9
- return `Unable to connect to ${getApiHost()}. Please check your internet connection and try again.`;
10
- }
11
- if (error.cause?.code === 'ENOTFOUND') {
12
- return `Could not resolve host ${getApiHost()}. Please check your internet connection and try again.`;
13
- }
14
- if (error.cause?.code === 'ETIMEDOUT') {
15
- return `Connection to ${getApiHost()} timed out. Please try again later.`;
16
- }
17
- return `Network error while connecting to ${getApiHost()}. Please check your internet connection and try again.`;
18
- }
19
-
20
- export async function apiRequest(endpoint, options = {}) {
21
- const apiHost = getApiHost();
22
- const url = `${apiHost}${endpoint}`;
23
- const apiKey = process.env.LOCALHERO_API_KEY || options.apiKey;
24
-
25
- const headers = {
26
- 'Content-Type': 'application/json',
27
- ...options.headers
28
- };
29
-
30
- if (apiKey) {
31
- headers['Authorization'] = `Bearer ${apiKey}`;
32
- }
33
-
34
- const fetchOptions = {
35
- method: options.method || 'GET',
36
- headers,
37
- };
38
-
39
- if (options.body) {
40
- fetchOptions.body = options.body;
41
- }
42
-
43
- let response;
44
- try {
45
- response = await fetch(url, fetchOptions);
46
- } catch (error) {
47
- const message = getNetworkErrorMessage(error);
48
- error.message = message;
49
- error.cliErrorMessage = message;
50
- throw error;
51
- }
52
-
53
- let data;
54
- try {
55
- data = await response.json();
56
- } catch (error) {
57
- const message = 'Failed to parse API response';
58
- error.message = message;
59
- error.cliErrorMessage = message;
60
- throw error;
61
- }
62
-
63
- if (!response.ok) {
64
- if (response.status === 401 && data?.error?.code === 'invalid_api_key') {
65
- const message = 'Your API key is invalid or has been revoked. Please run `npx @localheroai/cli login` to update your API key.';
66
- const error = new Error(message);
67
- error.cliErrorMessage = message;
68
- error.code = 'invalid_api_key';
69
- error.data = data;
70
- throw error;
71
- }
72
- const message = Array.isArray(data?.errors)
73
- ? data.errors.map(err => typeof err === 'string' ? err : err.message).join(', ')
74
- : data?.error?.message || 'API request failed';
75
- const error = new Error(message);
76
- error.cliErrorMessage = message;
77
- error.code = data?.error?.code || 'API_ERROR';
78
- error.data = data;
79
- throw error;
80
- }
81
-
82
- return data;
83
- }
@@ -1,22 +0,0 @@
1
- import { getApiKey } from '../utils/auth.js';
2
- import { apiRequest } from './client.js';
3
-
4
- export async function createImport({ projectId, translations }) {
5
- const apiKey = await getApiKey();
6
- const response = await apiRequest(`/api/v1/projects/${projectId}/imports`, {
7
- method: 'POST',
8
- body: JSON.stringify({
9
- translations
10
- }),
11
- apiKey
12
- });
13
- return response;
14
- }
15
-
16
- export async function checkImportStatus(projectId, importId) {
17
- const apiKey = await getApiKey();
18
- const response = await apiRequest(`/api/v1/projects/${projectId}/imports/${importId}`, {
19
- apiKey
20
- });
21
- return response.import;
22
- }
@@ -1,24 +0,0 @@
1
- import { getApiKey } from '../utils/auth.js';
2
- import { apiRequest } from './client.js';
3
-
4
- export async function listProjects() {
5
- const apiKey = await getApiKey();
6
- const response = await apiRequest('/api/v1/projects', { apiKey });
7
- return response.projects;
8
- }
9
-
10
- export async function createProject(data) {
11
- const apiKey = await getApiKey();
12
- const response = await apiRequest('/api/v1/projects', {
13
- method: 'POST',
14
- body: JSON.stringify({
15
- project: {
16
- name: data.name,
17
- source_language: data.sourceLocale,
18
- target_languages: data.targetLocales
19
- }
20
- }),
21
- apiKey
22
- });
23
- return response.project;
24
- }