@localheroai/cli 0.0.2 → 0.0.3
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 +98 -0
- package/package.json +57 -57
- package/src/api/auth.js +20 -11
- package/src/api/client.js +70 -28
- package/src/api/imports.js +15 -13
- package/src/api/projects.js +17 -17
- package/src/api/translations.js +50 -29
- package/src/cli.js +49 -42
- package/src/commands/init.js +436 -236
- package/src/commands/login.js +59 -48
- package/src/commands/sync.js +28 -0
- package/src/commands/translate.js +227 -247
- package/src/utils/auth.js +15 -15
- package/src/utils/config.js +115 -86
- package/src/utils/files.js +338 -116
- package/src/utils/git.js +64 -8
- package/src/utils/github.js +75 -45
- package/src/utils/import-service.js +112 -129
- package/src/utils/prompt-service.js +66 -50
- package/src/utils/sync-service.js +147 -0
- package/src/utils/translation-updater/common.js +44 -0
- package/src/utils/translation-updater/index.js +36 -0
- package/src/utils/translation-updater/json-handler.js +112 -0
- package/src/utils/translation-updater/yaml-handler.js +181 -0
- package/src/utils/translation-utils.js +237 -0
- package/src/utils/defaults.js +0 -7
- package/src/utils/helpers.js +0 -3
- package/src/utils/project-service.js +0 -11
- package/src/utils/translation-updater.js +0 -154
package/src/utils/auth.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { configService } from './config.js';
|
|
2
2
|
|
|
3
3
|
export async function getApiKey() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const envKey = process.env.LOCALHERO_API_KEY;
|
|
5
|
+
if (typeof envKey === 'string' && envKey.trim() !== '') {
|
|
6
|
+
return envKey;
|
|
7
|
+
}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const config = await configService.getAuthConfig();
|
|
10
|
+
return config?.api_key;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export async function checkAuth() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
try {
|
|
15
|
+
const apiKey = await getApiKey();
|
|
16
|
+
const isValidFormat = typeof apiKey === 'string' &&
|
|
17
|
+
/^tk_[a-f0-9]+$/.test(apiKey);
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
19
|
+
return isValidFormat;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/utils/config.js
CHANGED
|
@@ -3,94 +3,123 @@ import path from 'path';
|
|
|
3
3
|
|
|
4
4
|
const AUTH_CONFIG_FILE = '.localhero_key';
|
|
5
5
|
const PROJECT_CONFIG_FILE = 'localhero.json';
|
|
6
|
-
|
|
7
6
|
const DEFAULT_PROJECT_CONFIG = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
schemaVersion: '1.0',
|
|
8
|
+
projectId: '',
|
|
9
|
+
sourceLocale: 'en',
|
|
10
|
+
outputLocales: [],
|
|
11
|
+
translationFiles: {
|
|
12
|
+
paths: [],
|
|
13
|
+
ignore: []
|
|
14
|
+
},
|
|
15
|
+
lastSyncedAt: null
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const defaultDeps = {
|
|
19
|
+
fs,
|
|
20
|
+
path,
|
|
21
|
+
process,
|
|
22
|
+
cwd: process.cwd
|
|
16
23
|
};
|
|
17
24
|
|
|
18
25
|
export const configService = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
throw new Error(`Missing required config: ${missing.join(', ')}. Run 'npx localhero init' to set up your project.`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!Array.isArray(config.outputLocales) || config.outputLocales.length === 0) {
|
|
74
|
-
throw new Error('outputLocales must be an array with at least one locale');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (config.outputLocales.length > 10) {
|
|
78
|
-
throw new Error('Maximum 10 target languages allowed per request');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!config.translationFiles.paths || !Array.isArray(config.translationFiles.paths)) {
|
|
82
|
-
throw new Error('translationFiles.paths must be an array of paths');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return true;
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
async getValidProjectConfig(basePath = process.cwd()) {
|
|
89
|
-
const config = await this.getProjectConfig(basePath);
|
|
90
|
-
if (!config) {
|
|
91
|
-
throw new Error('No localhero.json found. Run `npx localhero init` first');
|
|
92
|
-
}
|
|
93
|
-
await this.validateProjectConfig(config);
|
|
94
|
-
return config;
|
|
26
|
+
deps: { ...defaultDeps },
|
|
27
|
+
|
|
28
|
+
setDependencies(customDeps = {}) {
|
|
29
|
+
this.deps = { ...defaultDeps, ...customDeps };
|
|
30
|
+
return this;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
configFilePath(basePath) {
|
|
34
|
+
const { path } = this.deps;
|
|
35
|
+
const baseDir = basePath || this.deps.cwd();
|
|
36
|
+
return path.join(baseDir, PROJECT_CONFIG_FILE);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async getAuthConfig(basePath) {
|
|
40
|
+
const { fs, path } = this.deps;
|
|
41
|
+
const baseDir = basePath || this.deps.cwd();
|
|
42
|
+
try {
|
|
43
|
+
const configPath = path.join(baseDir, AUTH_CONFIG_FILE);
|
|
44
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
45
|
+
return JSON.parse(content);
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
async saveAuthConfig(config, basePath) {
|
|
52
|
+
const { fs, path } = this.deps;
|
|
53
|
+
const baseDir = basePath || this.deps.cwd();
|
|
54
|
+
const configPath = path.join(baseDir, AUTH_CONFIG_FILE);
|
|
55
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), {
|
|
56
|
+
mode: 0o600
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
async getProjectConfig(basePath) {
|
|
61
|
+
const { fs } = this.deps;
|
|
62
|
+
try {
|
|
63
|
+
const configPath = this.configFilePath(basePath);
|
|
64
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
65
|
+
const config = JSON.parse(content);
|
|
66
|
+
|
|
67
|
+
if (config.schemaVersion !== DEFAULT_PROJECT_CONFIG.schemaVersion) {
|
|
68
|
+
throw new Error(`Unsupported config schema version: ${config.schemaVersion}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return config;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error.code === 'ENOENT') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
95
77
|
}
|
|
96
|
-
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
async saveProjectConfig(config, basePath) {
|
|
81
|
+
const { fs } = this.deps;
|
|
82
|
+
const configPath = this.configFilePath(basePath);
|
|
83
|
+
const configWithSchema = {
|
|
84
|
+
...DEFAULT_PROJECT_CONFIG,
|
|
85
|
+
...config,
|
|
86
|
+
schemaVersion: DEFAULT_PROJECT_CONFIG.schemaVersion
|
|
87
|
+
};
|
|
88
|
+
await fs.writeFile(configPath, JSON.stringify(configWithSchema, null, 2));
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
async validateProjectConfig(config) {
|
|
92
|
+
const required = ['projectId', 'sourceLocale', 'outputLocales', 'translationFiles'];
|
|
93
|
+
const missing = required.filter(key => !config[key]);
|
|
94
|
+
|
|
95
|
+
if (missing.length) {
|
|
96
|
+
throw new Error(`Missing required config: ${missing.join(', ')}. Run 'npx @localheroai/cli init' to set up your project.`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!Array.isArray(config.outputLocales) || config.outputLocales.length === 0) {
|
|
100
|
+
throw new Error('outputLocales must be an array with at least one locale');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!config.translationFiles.paths || !Array.isArray(config.translationFiles.paths)) {
|
|
104
|
+
throw new Error('translationFiles.paths must be an array of paths');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return true;
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
async getValidProjectConfig(basePath) {
|
|
111
|
+
const config = await this.getProjectConfig(basePath);
|
|
112
|
+
if (!config) {
|
|
113
|
+
throw new Error('No project config found. Run `npx @localheroai/cli init` first');
|
|
114
|
+
}
|
|
115
|
+
await this.validateProjectConfig(config);
|
|
116
|
+
return config;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
async updateLastSyncedAt(basePath) {
|
|
120
|
+
const config = await this.getValidProjectConfig(basePath);
|
|
121
|
+
config.lastSyncedAt = new Date().toISOString();
|
|
122
|
+
await this.saveProjectConfig(config, basePath);
|
|
123
|
+
return config;
|
|
124
|
+
}
|
|
125
|
+
};
|