@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.
- package/{README → README.md} +28 -10
- package/dist/api/auth.d.ts +2 -0
- package/dist/api/auth.js +28 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/client.d.ts +3 -0
- package/dist/api/client.js +80 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/imports.d.ts +5 -0
- package/dist/api/imports.js +43 -0
- package/dist/api/imports.js.map +1 -0
- package/dist/api/projects.d.ts +2 -0
- package/dist/api/projects.js +42 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/translations.d.ts +15 -0
- package/dist/api/translations.js +71 -0
- package/dist/api/translations.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +79 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/_sync.js +22 -0
- package/dist/commands/_sync.js.map +1 -0
- package/dist/commands/_translate.js +3 -0
- package/dist/commands/_translate.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +439 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +16 -0
- package/dist/commands/login.js +58 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/pull.js +22 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.js +56 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/sync.d.ts +20 -0
- package/dist/commands/sync.js +22 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/translate.d.ts +14 -0
- package/dist/commands/translate.js +152 -0
- package/dist/commands/translate.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +75 -0
- package/dist/types/index.js +17 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/translate/index.js +2 -0
- package/dist/types/translate/index.js.map +1 -0
- package/dist/utils/auth.d.ts +2 -0
- package/dist/utils/auth.js +29 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/common.js +9 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/config.d.ts +23 -0
- package/dist/utils/config.js +137 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/errors.js +37 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/files.d.ts +32 -0
- package/dist/utils/files.js +355 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/git.d.ts +21 -0
- package/dist/utils/git.js +87 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/github.d.ts +241 -0
- package/dist/utils/github.js +161 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/import-service.d.ts +4 -0
- package/dist/utils/import-service.js +218 -0
- package/dist/utils/import-service.js.map +1 -0
- package/dist/utils/prompt-service.d.ts +44 -0
- package/dist/utils/prompt-service.js +104 -0
- package/dist/utils/prompt-service.js.map +1 -0
- package/dist/utils/sync-service.d.ts +58 -0
- package/dist/utils/sync-service.js +159 -0
- package/dist/utils/sync-service.js.map +1 -0
- package/dist/utils/translation-processor.js +197 -0
- package/dist/utils/translation-processor.js.map +1 -0
- package/dist/utils/translation-updater/common.d.ts +6 -0
- package/{src → dist}/utils/translation-updater/common.js +16 -10
- package/dist/utils/translation-updater/common.js.map +1 -0
- package/dist/utils/translation-updater/index.d.ts +5 -0
- package/{src → dist}/utils/translation-updater/index.js +21 -9
- package/dist/utils/translation-updater/index.js.map +1 -0
- package/dist/utils/translation-updater/json-handler.d.ts +5 -0
- package/dist/utils/translation-updater/json-handler.js +123 -0
- package/dist/utils/translation-updater/json-handler.js.map +1 -0
- package/dist/utils/translation-updater/yaml-handler.d.ts +5 -0
- package/dist/utils/translation-updater/yaml-handler.js +193 -0
- package/dist/utils/translation-updater/yaml-handler.js.map +1 -0
- package/dist/utils/translation-utils.d.ts +30 -0
- package/dist/utils/translation-utils.js +334 -0
- package/dist/utils/translation-utils.js.map +1 -0
- package/dist/utils/updater.js +38 -0
- package/dist/utils/updater.js.map +1 -0
- package/package.json +26 -26
- package/src/api/auth.js +0 -24
- package/src/api/client.js +0 -83
- package/src/api/imports.js +0 -22
- package/src/api/projects.js +0 -24
- package/src/api/translations.js +0 -58
- package/src/cli.js +0 -78
- package/src/commands/init.js +0 -485
- package/src/commands/login.js +0 -80
- package/src/commands/sync.js +0 -28
- package/src/commands/translate.js +0 -267
- package/src/utils/auth.js +0 -23
- package/src/utils/config.js +0 -125
- package/src/utils/files.js +0 -381
- package/src/utils/git.js +0 -72
- package/src/utils/github.js +0 -128
- package/src/utils/import-service.js +0 -128
- package/src/utils/prompt-service.js +0 -67
- package/src/utils/sync-service.js +0 -147
- package/src/utils/translation-updater/json-handler.js +0 -111
- package/src/utils/translation-updater/yaml-handler.js +0 -207
- package/src/utils/translation-utils.js +0 -278
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { syncService as defaultSyncService } from '../utils/sync-service.js';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export async function sync({ verbose = false } = {}, deps = { syncService: defaultSyncService }) {
|
|
4
|
+
const { syncService } = deps;
|
|
5
|
+
const { hasUpdates, updates } = await syncService.checkForUpdates(verbose);
|
|
6
|
+
if (!hasUpdates) {
|
|
7
|
+
console.log(chalk.green('✓ All translations are up to date'));
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const result = await syncService.applyUpdates(updates, verbose);
|
|
11
|
+
const { totalUpdates = 0, totalDeleted = 0 } = result;
|
|
12
|
+
if (!verbose) {
|
|
13
|
+
if (totalUpdates > 0) {
|
|
14
|
+
console.log(chalk.green(`✓ Updated ${totalUpdates} translations`));
|
|
15
|
+
}
|
|
16
|
+
if (totalDeleted > 0) {
|
|
17
|
+
console.log(chalk.green(`✓ Deleted ${totalDeleted} keys`));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,MAAM,OAAO,CAAC;AAuB1B,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,EAAE,OAAO,GAAG,KAAK,KAA4B,EAAE,EAC/C,OAAyB,EAAE,WAAW,EAAE,kBAAkB,EAAE;IAE5D,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAE3E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEhE,MAAM,EAAE,YAAY,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC;IAEtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,YAAY,eAAe,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,YAAY,OAAO,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TranslateOptions } from '../types/index.js';
|
|
2
|
+
import { configService } from '../utils/config.js';
|
|
3
|
+
interface TranslateDependencies {
|
|
4
|
+
console?: Console;
|
|
5
|
+
basePath?: string;
|
|
6
|
+
configUtils?: typeof configService;
|
|
7
|
+
}
|
|
8
|
+
interface TranslateResult {
|
|
9
|
+
totalTranslated: number;
|
|
10
|
+
skipped: number;
|
|
11
|
+
errors: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function translate({ verbose, commit }?: TranslateOptions, deps?: TranslateDependencies): Promise<TranslateResult>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { configService } from '../utils/config.js';
|
|
3
|
+
import { findTranslationFiles } from '../utils/files.js';
|
|
4
|
+
import { createTranslationJob, checkJobStatus } from '../api/translations.js';
|
|
5
|
+
import { updateTranslationFile } from '../utils/translation-updater/index.js';
|
|
6
|
+
import { checkAuth } from '../utils/auth.js';
|
|
7
|
+
import { findMissingTranslations, batchKeysWithMissing, findMissingTranslationsByLocale } from '../utils/translation-utils.js';
|
|
8
|
+
import { syncService } from '../utils/sync-service.js';
|
|
9
|
+
import { autoCommitChanges } from '../utils/github.js';
|
|
10
|
+
import { processTranslationBatches } from '../utils/translation-processor.js';
|
|
11
|
+
import { ApiResponseError } from '../types/index.js';
|
|
12
|
+
const defaultDeps = {
|
|
13
|
+
console,
|
|
14
|
+
configUtils: configService,
|
|
15
|
+
authUtils: { checkAuth },
|
|
16
|
+
fileUtils: { findTranslationFiles },
|
|
17
|
+
translationUtils: {
|
|
18
|
+
createTranslationJob,
|
|
19
|
+
checkJobStatus,
|
|
20
|
+
updateTranslationFile,
|
|
21
|
+
findMissingTranslations,
|
|
22
|
+
batchKeysWithMissing,
|
|
23
|
+
findMissingTranslationsByLocale
|
|
24
|
+
},
|
|
25
|
+
syncService,
|
|
26
|
+
gitUtils: { autoCommitChanges }
|
|
27
|
+
};
|
|
28
|
+
export async function translate(options = {}, deps = defaultDeps) {
|
|
29
|
+
const { console, configUtils, authUtils, fileUtils, translationUtils, syncService, gitUtils } = deps;
|
|
30
|
+
const { verbose } = options;
|
|
31
|
+
const isAuthenticated = await authUtils.checkAuth();
|
|
32
|
+
if (!isAuthenticated) {
|
|
33
|
+
console.error(chalk.red('\n✖ Your API key is invalid. Please run `npx @localheroai/cli login` to authenticate.\n'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const config = await configUtils.getProjectConfig();
|
|
37
|
+
if (!config) {
|
|
38
|
+
console.error(chalk.red('\n✖ No configuration found. Please run `npx @localheroai/cli init` first.\n'));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!config.translationFiles?.paths) {
|
|
43
|
+
console.error(chalk.red('\n✖ Invalid configuration: missing translationFiles.paths. Please run `npx @localheroai/cli init` to set up your configuration.\n'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const { hasUpdates, updates } = await syncService.checkForUpdates(verbose);
|
|
48
|
+
if (hasUpdates && updates) {
|
|
49
|
+
await syncService.applyUpdates(updates, verbose);
|
|
50
|
+
}
|
|
51
|
+
if (verbose) {
|
|
52
|
+
console.log(chalk.blue('\nℹ Using configuration:'));
|
|
53
|
+
console.log(chalk.gray(` Project ID: ${config.projectId}`));
|
|
54
|
+
console.log(chalk.gray(` Source locale: ${config.sourceLocale}`));
|
|
55
|
+
console.log(chalk.gray(` Output locales: ${config.outputLocales.join(', ')}`));
|
|
56
|
+
console.log(chalk.gray(` Translation files: ${config.translationFiles.paths.join(', ')}`));
|
|
57
|
+
}
|
|
58
|
+
const result = await fileUtils.findTranslationFiles(config, { verbose, returnFullResult: true });
|
|
59
|
+
const { sourceFiles, targetFilesByLocale, allFiles } = result;
|
|
60
|
+
if (!allFiles || allFiles.length === 0) {
|
|
61
|
+
console.error(chalk.red('\n✖ No translation files found in the specified paths.\n'));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
if (verbose) {
|
|
65
|
+
console.log(chalk.blue(`\nℹ Found ${allFiles.length} translation files`));
|
|
66
|
+
}
|
|
67
|
+
if (sourceFiles.length === 0) {
|
|
68
|
+
console.error(chalk.red(`\n✖ No source files found for locale ${config.sourceLocale}\n`));
|
|
69
|
+
console.error(chalk.yellow('This could be due to one of the following issues:'));
|
|
70
|
+
console.error(chalk.yellow(` 1. No translation files with the source locale "${config.sourceLocale}" exist in the configured paths`));
|
|
71
|
+
console.error(chalk.yellow(' 2. The locale identifiers in your filenames don\'t match the expected pattern'));
|
|
72
|
+
console.error(chalk.yellow(' 3. There was an error parsing one or more files (check for syntax errors in YAML or JSON)\n'));
|
|
73
|
+
console.error(chalk.yellow('Try running with the --verbose flag for more detailed information.\n'));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
if (verbose) {
|
|
77
|
+
console.log(chalk.blue(`ℹ Found ${sourceFiles.length} source files for locale ${config.sourceLocale}`));
|
|
78
|
+
}
|
|
79
|
+
const missingByLocale = translationUtils.findMissingTranslationsByLocale(sourceFiles, targetFilesByLocale, config, !!verbose, console);
|
|
80
|
+
const missingLocalesSummary = {};
|
|
81
|
+
Object.values(missingByLocale).forEach((data) => {
|
|
82
|
+
const { locale, keyCount = 0 } = data;
|
|
83
|
+
if (!missingLocalesSummary[locale]) {
|
|
84
|
+
missingLocalesSummary[locale] = { keyCount: 0, fileCount: 0 };
|
|
85
|
+
}
|
|
86
|
+
missingLocalesSummary[locale].keyCount += keyCount;
|
|
87
|
+
missingLocalesSummary[locale].fileCount += 1;
|
|
88
|
+
});
|
|
89
|
+
const missingLocales = Object.keys(missingLocalesSummary);
|
|
90
|
+
if (missingLocales.length === 0) {
|
|
91
|
+
console.log(chalk.green('✓ All translations are up to date'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (verbose) {
|
|
95
|
+
console.log(chalk.blue('\nℹ Missing translations:'));
|
|
96
|
+
for (const [locale, data] of Object.entries(missingLocalesSummary)) {
|
|
97
|
+
console.log(chalk.gray(` ${locale}: ${data.keyCount} keys in ${data.fileCount} files`));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const { batches, errors } = translationUtils.batchKeysWithMissing(sourceFiles, missingByLocale);
|
|
101
|
+
if (errors.length > 0) {
|
|
102
|
+
console.error(chalk.red('\n✖ Errors occurred while preparing translation jobs:'));
|
|
103
|
+
for (const error of errors) {
|
|
104
|
+
console.error(chalk.red(` ${error.message}`));
|
|
105
|
+
}
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const translationResult = await processTranslationBatches(batches, missingByLocale, config, !!verbose, { console, translationUtils });
|
|
110
|
+
await configUtils.updateLastSyncedAt();
|
|
111
|
+
console.log(chalk.green('✓ Translations complete!'));
|
|
112
|
+
console.log(`» Updated ${translationResult.uniqueKeysTranslated.size} keys in ${translationResult.totalLanguages} languages`);
|
|
113
|
+
if (translationResult.uniqueKeysTranslated.size > 0) {
|
|
114
|
+
try {
|
|
115
|
+
gitUtils.autoCommitChanges(config.translationFiles.paths.join(' '));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
const err = error;
|
|
119
|
+
console.warn(chalk.yellow(`\nℹ Could not auto-commit changes: ${err.message}`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (translationResult.resultsBaseUrl && translationResult.allJobIds.length > 0) {
|
|
123
|
+
const jobIdsParam = translationResult.allJobIds.join(',');
|
|
124
|
+
console.log(`» View results at: ${translationResult.resultsBaseUrl}?job_ids=${jobIdsParam}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (error instanceof ApiResponseError) {
|
|
129
|
+
console.error(chalk.red(`\n✖ API error processing translation jobs: ${error.cliErrorMessage || error.message}`));
|
|
130
|
+
if (error.details) {
|
|
131
|
+
console.error(chalk.red(` ${error.details}`));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Handle any other type of error
|
|
136
|
+
const err = error;
|
|
137
|
+
console.error(chalk.red(`\n✖ Error processing translation jobs: ${err.message}`));
|
|
138
|
+
if (err.stack) {
|
|
139
|
+
const stackLines = err.stack.split('\n').slice(1);
|
|
140
|
+
console.error(chalk.dim('\nStack trace:'));
|
|
141
|
+
stackLines.forEach(line => {
|
|
142
|
+
const trimmed = line.trim();
|
|
143
|
+
if (trimmed.startsWith(' at ')) {
|
|
144
|
+
console.error(chalk.dim(trimmed));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/commands/translate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { login } from './commands/login.js';
|
|
2
|
+
export { pull } from './commands/pull.js';
|
|
3
|
+
export { init } from './commands/init.js';
|
|
4
|
+
export { translate } from './commands/translate.js';
|
|
5
|
+
export { configService } from './utils/config.js';
|
|
6
|
+
export { gitService } from './utils/git.js';
|
|
7
|
+
export * from './types/index.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export interface AuthConfig {
|
|
2
|
+
api_key: string;
|
|
3
|
+
last_verified: string;
|
|
4
|
+
}
|
|
5
|
+
export interface TranslationFile {
|
|
6
|
+
paths: string[];
|
|
7
|
+
ignore?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ProjectConfig {
|
|
10
|
+
schemaVersion: string;
|
|
11
|
+
projectId: string;
|
|
12
|
+
sourceLocale: string;
|
|
13
|
+
outputLocales: string[];
|
|
14
|
+
translationFiles: TranslationFile;
|
|
15
|
+
lastSyncedAt: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface ApiError {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
export interface Project {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Organization {
|
|
26
|
+
name: string;
|
|
27
|
+
projects: Project[];
|
|
28
|
+
}
|
|
29
|
+
export interface VerifyApiKeyResult {
|
|
30
|
+
error?: ApiError;
|
|
31
|
+
organization?: Organization;
|
|
32
|
+
}
|
|
33
|
+
export interface TranslationOptions {
|
|
34
|
+
verbose?: boolean;
|
|
35
|
+
commit?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface SyncOptions {
|
|
38
|
+
verbose?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface FsDependencies {
|
|
41
|
+
readFile: (path: string, options: {
|
|
42
|
+
encoding: string;
|
|
43
|
+
}) => Promise<string>;
|
|
44
|
+
writeFile: (path: string, data: string, options?: any) => Promise<void>;
|
|
45
|
+
mkdir: (path: string, options?: any) => Promise<void>;
|
|
46
|
+
readdir: (path: string) => Promise<string[]>;
|
|
47
|
+
stat: (path: string) => Promise<any>;
|
|
48
|
+
access: (path: string, mode?: number) => Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export interface ConsoleDependencies {
|
|
51
|
+
log: (message?: any, ...optionalParams: any[]) => void;
|
|
52
|
+
error: (message?: any, ...optionalParams: any[]) => void;
|
|
53
|
+
warn: (message?: any, ...optionalParams: any[]) => void;
|
|
54
|
+
}
|
|
55
|
+
export interface ApiRequestOptions {
|
|
56
|
+
method?: string;
|
|
57
|
+
headers?: Record<string, string>;
|
|
58
|
+
body?: any;
|
|
59
|
+
apiKey?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ApiClientConfig {
|
|
62
|
+
baseUrl?: string;
|
|
63
|
+
apiKey?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface TranslationData {
|
|
66
|
+
[locale: string]: {
|
|
67
|
+
[key: string]: string | TranslationData;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export interface TranslationUpdateResult {
|
|
71
|
+
added: number;
|
|
72
|
+
updated: number;
|
|
73
|
+
unchanged: number;
|
|
74
|
+
errors: string[];
|
|
75
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// API Response Types
|
|
2
|
+
export class ApiResponseError extends Error {
|
|
3
|
+
cliErrorMessage;
|
|
4
|
+
code;
|
|
5
|
+
details;
|
|
6
|
+
data;
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'ApiResponseError';
|
|
10
|
+
// These need to be initialized in the constructor
|
|
11
|
+
this.cliErrorMessage = message;
|
|
12
|
+
this.code = 'API_ERROR';
|
|
13
|
+
this.details = null;
|
|
14
|
+
this.data = null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AA2DA,qBAAqB;AACrB,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,eAAe,CAAS;IACxB,IAAI,CAAS;IACb,OAAO,CAAa;IACpB,IAAI,CAAM;IAEV,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,kDAAkD;QAClD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/translate/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { configService } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gets the API key from environment variable or config file
|
|
4
|
+
* @returns The API key string or undefined if not found
|
|
5
|
+
*/
|
|
6
|
+
export async function getApiKey() {
|
|
7
|
+
const envKey = process.env.LOCALHERO_API_KEY;
|
|
8
|
+
if (typeof envKey === 'string' && envKey.trim() !== '') {
|
|
9
|
+
return envKey;
|
|
10
|
+
}
|
|
11
|
+
const config = await configService.getAuthConfig();
|
|
12
|
+
return config?.api_key;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Checks if the user is authenticated with a valid API key
|
|
16
|
+
* @returns Boolean indicating if a valid API key was found
|
|
17
|
+
*/
|
|
18
|
+
export async function checkAuth() {
|
|
19
|
+
try {
|
|
20
|
+
const apiKey = await getApiKey();
|
|
21
|
+
const isValidFormat = typeof apiKey === 'string' &&
|
|
22
|
+
/^tk_[a-f0-9]+$/.test(apiKey);
|
|
23
|
+
return isValidFormat;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACvD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAsB,MAAM,aAAa,CAAC,aAAa,EAAE,CAAC;IACtE,OAAO,MAAM,EAAE,OAAO,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,OAAO,MAAM,KAAK,QAAQ;YAC9C,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sleep for a specified number of milliseconds
|
|
3
|
+
* @param ms Number of milliseconds to sleep
|
|
4
|
+
* @returns Promise that resolves after the specified time
|
|
5
|
+
*/
|
|
6
|
+
export function sleep(ms) {
|
|
7
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { AuthConfig, ProjectConfig } from '../types/index.js';
|
|
4
|
+
interface ConfigDependencies {
|
|
5
|
+
fs: typeof fs;
|
|
6
|
+
path: typeof path;
|
|
7
|
+
process: typeof process;
|
|
8
|
+
cwd: () => string;
|
|
9
|
+
}
|
|
10
|
+
interface ConfigService {
|
|
11
|
+
deps: ConfigDependencies;
|
|
12
|
+
setDependencies(customDeps?: Partial<ConfigDependencies>): ConfigService;
|
|
13
|
+
configFilePath(basePath?: string): string;
|
|
14
|
+
getAuthConfig(basePath?: string): Promise<AuthConfig | null>;
|
|
15
|
+
saveAuthConfig(config: AuthConfig, basePath?: string): Promise<void>;
|
|
16
|
+
getProjectConfig(basePath?: string): Promise<ProjectConfig | null>;
|
|
17
|
+
saveProjectConfig(config: Partial<ProjectConfig>, basePath?: string): Promise<void>;
|
|
18
|
+
validateProjectConfig(config: ProjectConfig): Promise<boolean>;
|
|
19
|
+
getValidProjectConfig(basePath?: string): Promise<ProjectConfig>;
|
|
20
|
+
updateLastSyncedAt(basePath?: string): Promise<ProjectConfig>;
|
|
21
|
+
}
|
|
22
|
+
export declare const configService: ConfigService;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const AUTH_CONFIG_FILE = '.localhero_key';
|
|
4
|
+
const PROJECT_CONFIG_FILE = 'localhero.json';
|
|
5
|
+
const DEFAULT_PROJECT_CONFIG = {
|
|
6
|
+
schemaVersion: '1.0',
|
|
7
|
+
projectId: '',
|
|
8
|
+
sourceLocale: 'en',
|
|
9
|
+
outputLocales: [],
|
|
10
|
+
translationFiles: {
|
|
11
|
+
paths: [],
|
|
12
|
+
ignore: []
|
|
13
|
+
},
|
|
14
|
+
lastSyncedAt: null
|
|
15
|
+
};
|
|
16
|
+
const defaultDeps = {
|
|
17
|
+
fs,
|
|
18
|
+
path,
|
|
19
|
+
process,
|
|
20
|
+
cwd: process.cwd
|
|
21
|
+
};
|
|
22
|
+
export const configService = {
|
|
23
|
+
deps: { ...defaultDeps },
|
|
24
|
+
/**
|
|
25
|
+
* Set custom dependencies for testing
|
|
26
|
+
*/
|
|
27
|
+
setDependencies(customDeps = {}) {
|
|
28
|
+
this.deps = { ...defaultDeps, ...customDeps };
|
|
29
|
+
return this;
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* Get the path to the config file
|
|
33
|
+
*/
|
|
34
|
+
configFilePath(basePath) {
|
|
35
|
+
const { path } = this.deps;
|
|
36
|
+
const baseDir = basePath || this.deps.cwd();
|
|
37
|
+
return path.join(baseDir, PROJECT_CONFIG_FILE);
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Get the authentication config
|
|
41
|
+
*/
|
|
42
|
+
async getAuthConfig(basePath) {
|
|
43
|
+
const { fs, path } = this.deps;
|
|
44
|
+
const baseDir = basePath || this.deps.cwd();
|
|
45
|
+
try {
|
|
46
|
+
const configPath = path.join(baseDir, AUTH_CONFIG_FILE);
|
|
47
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
48
|
+
return JSON.parse(content);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Save the authentication config
|
|
56
|
+
*/
|
|
57
|
+
async saveAuthConfig(config, basePath) {
|
|
58
|
+
const { fs, path } = this.deps;
|
|
59
|
+
const baseDir = basePath || this.deps.cwd();
|
|
60
|
+
const configPath = path.join(baseDir, AUTH_CONFIG_FILE);
|
|
61
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), {
|
|
62
|
+
mode: 0o600
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Get the project config
|
|
67
|
+
*/
|
|
68
|
+
async getProjectConfig(basePath) {
|
|
69
|
+
const { fs } = this.deps;
|
|
70
|
+
try {
|
|
71
|
+
const configPath = this.configFilePath(basePath);
|
|
72
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
73
|
+
const config = JSON.parse(content);
|
|
74
|
+
if (config.schemaVersion !== DEFAULT_PROJECT_CONFIG.schemaVersion) {
|
|
75
|
+
throw new Error(`Unsupported config schema version: ${config.schemaVersion}`);
|
|
76
|
+
}
|
|
77
|
+
return config;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error.code === 'ENOENT') {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Save the project config
|
|
88
|
+
*/
|
|
89
|
+
async saveProjectConfig(config, basePath) {
|
|
90
|
+
const { fs } = this.deps;
|
|
91
|
+
const configPath = this.configFilePath(basePath);
|
|
92
|
+
const configWithSchema = {
|
|
93
|
+
...DEFAULT_PROJECT_CONFIG,
|
|
94
|
+
...config,
|
|
95
|
+
schemaVersion: DEFAULT_PROJECT_CONFIG.schemaVersion
|
|
96
|
+
};
|
|
97
|
+
await fs.writeFile(configPath, JSON.stringify(configWithSchema, null, 2));
|
|
98
|
+
},
|
|
99
|
+
/**
|
|
100
|
+
* Validate the project config
|
|
101
|
+
*/
|
|
102
|
+
async validateProjectConfig(config) {
|
|
103
|
+
const required = ['projectId', 'sourceLocale', 'outputLocales', 'translationFiles'];
|
|
104
|
+
const missing = required.filter(key => !(key in config));
|
|
105
|
+
if (missing.length) {
|
|
106
|
+
throw new Error(`Missing required config: ${missing.join(', ')}. Run 'npx @localheroai/cli init' to set up your project.`);
|
|
107
|
+
}
|
|
108
|
+
if (!Array.isArray(config.outputLocales) || config.outputLocales.length === 0) {
|
|
109
|
+
throw new Error('outputLocales must be an array with at least one locale');
|
|
110
|
+
}
|
|
111
|
+
if (!config.translationFiles.paths || !Array.isArray(config.translationFiles.paths)) {
|
|
112
|
+
throw new Error('translationFiles.paths must be an array of paths');
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* Get the project config and validate it
|
|
118
|
+
*/
|
|
119
|
+
async getValidProjectConfig(basePath) {
|
|
120
|
+
const config = await this.getProjectConfig(basePath);
|
|
121
|
+
if (!config) {
|
|
122
|
+
throw new Error('No project config found. Run `npx @localheroai/cli init` first');
|
|
123
|
+
}
|
|
124
|
+
await this.validateProjectConfig(config);
|
|
125
|
+
return config;
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Update the lastSyncedAt field in the project config
|
|
129
|
+
*/
|
|
130
|
+
async updateLastSyncedAt(basePath) {
|
|
131
|
+
const config = await this.getValidProjectConfig(basePath);
|
|
132
|
+
config.lastSyncedAt = new Date().toISOString();
|
|
133
|
+
await this.saveProjectConfig(config, basePath);
|
|
134
|
+
return config;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for CLI errors that should exit the process
|
|
3
|
+
*/
|
|
4
|
+
export class CliError extends Error {
|
|
5
|
+
exitCode;
|
|
6
|
+
constructor(message, exitCode = 1) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'CliError';
|
|
9
|
+
this.exitCode = exitCode;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a new CLI error
|
|
14
|
+
* @param message Error message
|
|
15
|
+
* @param exitCode Optional exit code, defaults to 1
|
|
16
|
+
* @returns A new CliError
|
|
17
|
+
*/
|
|
18
|
+
export function cliError(message, exitCode = 1) {
|
|
19
|
+
return new CliError(message, exitCode);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Handle a CLI error
|
|
23
|
+
* @param error The error to handle
|
|
24
|
+
* @param exitProcess Whether to exit the process (defaults to true)
|
|
25
|
+
* @returns The exit code if not exiting process
|
|
26
|
+
*/
|
|
27
|
+
export function handleCliError(error, exitProcess = true) {
|
|
28
|
+
const isCliError = error instanceof CliError;
|
|
29
|
+
const exitCode = isCliError ? error.exitCode : 1;
|
|
30
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
31
|
+
console.error(`\n✖ ${message}\n`);
|
|
32
|
+
if (exitProcess) {
|
|
33
|
+
process.exit(exitCode);
|
|
34
|
+
}
|
|
35
|
+
return exitCode;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAS;IAEjB,YAAY,OAAe,EAAE,WAAmB,CAAC;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,WAAmB,CAAC;IAC5D,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,cAAuB,IAAI;IACxE,MAAM,UAAU,GAAG,KAAK,YAAY,QAAQ,CAAC;IAC7C,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvE,OAAO,CAAC,KAAK,CAAC,OAAO,OAAO,IAAI,CAAC,CAAC;IAElC,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function parseFile(content: any, format: any, filePath?: string): any;
|
|
2
|
+
export function extractLocaleFromPath(filePath: any, localeRegex: any, knownLocales?: any[]): any;
|
|
3
|
+
export function isValidLocale(locale: any): boolean;
|
|
4
|
+
export function flattenTranslations(obj: any, parentKey?: string): {};
|
|
5
|
+
export function findTranslationFiles(config: any, options?: {}): Promise<{
|
|
6
|
+
path: any;
|
|
7
|
+
format: string;
|
|
8
|
+
locale: any;
|
|
9
|
+
}[] | {
|
|
10
|
+
allFiles: {
|
|
11
|
+
path: any;
|
|
12
|
+
format: string;
|
|
13
|
+
locale: any;
|
|
14
|
+
}[];
|
|
15
|
+
sourceFiles: {
|
|
16
|
+
path: any;
|
|
17
|
+
format: string;
|
|
18
|
+
locale: any;
|
|
19
|
+
}[];
|
|
20
|
+
targetFilesByLocale: {};
|
|
21
|
+
}>;
|
|
22
|
+
export function unflattenTranslations(flatObj: any): {};
|
|
23
|
+
export function detectJsonFormat(obj: any): "nested" | "mixed" | "flat";
|
|
24
|
+
export function preserveJsonStructure(originalObj: any, newTranslations: any, format: any): any;
|
|
25
|
+
export function directoryExists(path: any, fsModule?: typeof fs): Promise<boolean>;
|
|
26
|
+
export function findFirstExistingPath(paths: any, fsModule?: typeof fs): Promise<any>;
|
|
27
|
+
export function getDirectoryContents(dir: any, fsModule?: typeof fs): Promise<{
|
|
28
|
+
files: string[];
|
|
29
|
+
jsonFiles: string[];
|
|
30
|
+
yamlFiles: string[];
|
|
31
|
+
} | null>;
|
|
32
|
+
import { promises as fs } from 'fs';
|