@localheroai/cli 0.0.2 → 0.0.5

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.
@@ -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
- schemaVersion: '1.0',
9
- projectId: '',
10
- sourceLocale: 'en',
11
- outputLocales: [],
12
- translationFiles: {
13
- paths: [],
14
- ignore: []
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
- async getAuthConfig(basePath = process.cwd()) {
20
- try {
21
- const configPath = path.join(basePath, AUTH_CONFIG_FILE);
22
- const content = await fs.readFile(configPath, 'utf8');
23
- return JSON.parse(content);
24
- } catch {
25
- return null;
26
- }
27
- },
28
-
29
- async saveAuthConfig(config, basePath = process.cwd()) {
30
- const configPath = path.join(basePath, AUTH_CONFIG_FILE);
31
- await fs.writeFile(configPath, JSON.stringify(config, null, 2), {
32
- mode: 0o600 // User-only readable
33
- });
34
- },
35
-
36
- async getProjectConfig(basePath = process.cwd()) {
37
- try {
38
- const configPath = path.join(basePath, PROJECT_CONFIG_FILE);
39
- const content = await fs.readFile(configPath, 'utf8');
40
- const config = JSON.parse(content);
41
-
42
- if (config.schemaVersion !== DEFAULT_PROJECT_CONFIG.schemaVersion) {
43
- throw new Error(`Unsupported config schema version: ${config.schemaVersion}`);
44
- }
45
-
46
- return config;
47
- } catch (error) {
48
- if (error.code === 'ENOENT') {
49
- return null;
50
- }
51
- throw error;
52
- }
53
- },
54
-
55
- async saveProjectConfig(config, basePath = process.cwd()) {
56
- const configPath = path.join(basePath, PROJECT_CONFIG_FILE);
57
- const configWithSchema = {
58
- ...DEFAULT_PROJECT_CONFIG,
59
- ...config,
60
- schemaVersion: DEFAULT_PROJECT_CONFIG.schemaVersion
61
- };
62
- await fs.writeFile(configPath, JSON.stringify(configWithSchema, null, 2));
63
- },
64
-
65
- async validateProjectConfig(config) {
66
- const required = ['projectId', 'sourceLocale', 'outputLocales', 'translationFiles'];
67
- const missing = required.filter(key => !config[key]);
68
-
69
- if (missing.length) {
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
+ };