@sembix/cli 1.1.0 → 1.2.1
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/.env.example +7 -0
- package/README.md +161 -8
- package/dist/__tests__/config-schema.test.js +1 -1
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +75 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/integration/configure.test.d.ts +2 -0
- package/dist/__tests__/integration/configure.test.d.ts.map +1 -0
- package/dist/__tests__/integration/configure.test.js +247 -0
- package/dist/__tests__/integration/configure.test.js.map +1 -0
- package/dist/commands/__tests__/configure.test.d.ts +2 -0
- package/dist/commands/__tests__/configure.test.d.ts.map +1 -0
- package/dist/commands/__tests__/configure.test.js +229 -0
- package/dist/commands/__tests__/configure.test.js.map +1 -0
- package/dist/commands/configure.d.ts +6 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +90 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/config-schema.d.ts +31 -335
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -3
- package/dist/config.js.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/prompts/__tests__/environment-setup.test.d.ts +2 -0
- package/dist/prompts/__tests__/environment-setup.test.d.ts.map +1 -0
- package/dist/prompts/__tests__/environment-setup.test.js +206 -0
- package/dist/prompts/__tests__/environment-setup.test.js.map +1 -0
- package/dist/prompts/__tests__/hub-integration.test.d.ts +2 -0
- package/dist/prompts/__tests__/hub-integration.test.d.ts.map +1 -0
- package/dist/prompts/__tests__/hub-integration.test.js +126 -0
- package/dist/prompts/__tests__/hub-integration.test.js.map +1 -0
- package/dist/prompts/hub-integration-step.js +3 -3
- package/dist/prompts/hub-integration.js +3 -3
- package/dist/sembix-cli-1.2.1.tgz +0 -0
- package/dist/utils/__tests__/config-file.test.d.ts +2 -0
- package/dist/utils/__tests__/config-file.test.d.ts.map +1 -0
- package/dist/utils/__tests__/config-file.test.js +218 -0
- package/dist/utils/__tests__/config-file.test.js.map +1 -0
- package/dist/utils/config-file.d.ts +23 -0
- package/dist/utils/config-file.d.ts.map +1 -0
- package/dist/utils/config-file.js +100 -0
- package/dist/utils/config-file.js.map +1 -0
- package/dist/utils/config-loader.js +7 -7
- package/package.json +24 -24
- package/dist/sembix-cli-1.1.0.tgz +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
// Mock os module BEFORE importing the module under test
|
|
6
|
+
vi.mock('os', () => ({
|
|
7
|
+
homedir: vi.fn(() => '/home/testuser'),
|
|
8
|
+
}));
|
|
9
|
+
// Mock fs modules
|
|
10
|
+
vi.mock('fs', () => ({
|
|
11
|
+
existsSync: vi.fn(),
|
|
12
|
+
promises: {
|
|
13
|
+
readFile: vi.fn(),
|
|
14
|
+
writeFile: vi.fn(),
|
|
15
|
+
mkdir: vi.fn(),
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
// NOW import the module under test
|
|
19
|
+
import { readConfig, writeConfig, getConfigPath, configExists, } from '../config-file.js';
|
|
20
|
+
const mockExistsSync = vi.mocked(existsSync);
|
|
21
|
+
const mockReadFile = vi.mocked(fs.readFile);
|
|
22
|
+
const mockWriteFile = vi.mocked(fs.writeFile);
|
|
23
|
+
const mockMkdir = vi.mocked(fs.mkdir);
|
|
24
|
+
const mockHomedir = vi.mocked(homedir);
|
|
25
|
+
describe('config-file', () => {
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
vi.clearAllMocks();
|
|
28
|
+
mockHomedir.mockReturnValue('/home/testuser');
|
|
29
|
+
});
|
|
30
|
+
describe('getConfigPath', () => {
|
|
31
|
+
it('should return the correct config path', () => {
|
|
32
|
+
const path = getConfigPath();
|
|
33
|
+
expect(path).toBe('/home/testuser/.sembix/config');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('configExists', () => {
|
|
37
|
+
it('should return true when config file exists', () => {
|
|
38
|
+
mockExistsSync.mockReturnValue(true);
|
|
39
|
+
expect(configExists()).toBe(true);
|
|
40
|
+
expect(mockExistsSync).toHaveBeenCalledWith('/home/testuser/.sembix/config');
|
|
41
|
+
});
|
|
42
|
+
it('should return false when config file does not exist', () => {
|
|
43
|
+
mockExistsSync.mockReturnValue(false);
|
|
44
|
+
expect(configExists()).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('readConfig', () => {
|
|
48
|
+
it('should return empty object when config file does not exist', async () => {
|
|
49
|
+
mockExistsSync.mockReturnValue(false);
|
|
50
|
+
const config = await readConfig();
|
|
51
|
+
expect(config).toEqual({});
|
|
52
|
+
});
|
|
53
|
+
it('should parse valid config file with github_token', async () => {
|
|
54
|
+
mockExistsSync.mockReturnValue(true);
|
|
55
|
+
mockReadFile.mockResolvedValue('github_token=ghp_test123\n');
|
|
56
|
+
const config = await readConfig();
|
|
57
|
+
expect(config).toEqual({
|
|
58
|
+
github_token: 'ghp_test123',
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
it('should parse valid config file with both fields', async () => {
|
|
62
|
+
mockExistsSync.mockReturnValue(true);
|
|
63
|
+
mockReadFile.mockResolvedValue('github_token=ghp_test123\ndefault_github_org=acme-corp\n');
|
|
64
|
+
const config = await readConfig();
|
|
65
|
+
expect(config).toEqual({
|
|
66
|
+
github_token: 'ghp_test123',
|
|
67
|
+
default_github_org: 'acme-corp',
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
it('should ignore comments and empty lines', async () => {
|
|
71
|
+
mockExistsSync.mockReturnValue(true);
|
|
72
|
+
mockReadFile.mockResolvedValue(`
|
|
73
|
+
# This is a comment
|
|
74
|
+
github_token=ghp_test123
|
|
75
|
+
|
|
76
|
+
; Another comment style
|
|
77
|
+
default_github_org=acme-corp
|
|
78
|
+
`);
|
|
79
|
+
const config = await readConfig();
|
|
80
|
+
expect(config).toEqual({
|
|
81
|
+
github_token: 'ghp_test123',
|
|
82
|
+
default_github_org: 'acme-corp',
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it('should handle values with equals signs', async () => {
|
|
86
|
+
mockExistsSync.mockReturnValue(true);
|
|
87
|
+
mockReadFile.mockResolvedValue('github_token=ghp_test=123=456\n');
|
|
88
|
+
const config = await readConfig();
|
|
89
|
+
expect(config).toEqual({
|
|
90
|
+
github_token: 'ghp_test=123=456',
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
it('should trim whitespace from keys and values', async () => {
|
|
94
|
+
mockExistsSync.mockReturnValue(true);
|
|
95
|
+
mockReadFile.mockResolvedValue(' github_token = ghp_test123 \n');
|
|
96
|
+
const config = await readConfig();
|
|
97
|
+
expect(config).toEqual({
|
|
98
|
+
github_token: 'ghp_test123',
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
it('should ignore unknown keys', async () => {
|
|
102
|
+
mockExistsSync.mockReturnValue(true);
|
|
103
|
+
mockReadFile.mockResolvedValue('github_token=ghp_test123\nunknown_key=value\ndefault_github_org=acme\n');
|
|
104
|
+
const config = await readConfig();
|
|
105
|
+
expect(config).toEqual({
|
|
106
|
+
github_token: 'ghp_test123',
|
|
107
|
+
default_github_org: 'acme',
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
it('should return empty object on read error', async () => {
|
|
111
|
+
mockExistsSync.mockReturnValue(true);
|
|
112
|
+
mockReadFile.mockRejectedValue(new Error('Permission denied'));
|
|
113
|
+
const config = await readConfig();
|
|
114
|
+
expect(config).toEqual({});
|
|
115
|
+
});
|
|
116
|
+
it('should handle invalid format gracefully', async () => {
|
|
117
|
+
mockExistsSync.mockReturnValue(true);
|
|
118
|
+
mockReadFile.mockResolvedValue('invalid line without equals\n');
|
|
119
|
+
const config = await readConfig();
|
|
120
|
+
expect(config).toEqual({});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('writeConfig', () => {
|
|
124
|
+
it('should create directory if it does not exist', async () => {
|
|
125
|
+
mockExistsSync.mockReturnValue(false);
|
|
126
|
+
mockMkdir.mockResolvedValue(undefined);
|
|
127
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
128
|
+
const config = {
|
|
129
|
+
github_token: 'ghp_test123',
|
|
130
|
+
};
|
|
131
|
+
await writeConfig(config);
|
|
132
|
+
expect(mockMkdir).toHaveBeenCalledWith('/home/testuser/.sembix', {
|
|
133
|
+
recursive: true,
|
|
134
|
+
mode: 0o700,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
it('should not create directory if it already exists', async () => {
|
|
138
|
+
mockExistsSync.mockReturnValue(true);
|
|
139
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
140
|
+
const config = {
|
|
141
|
+
github_token: 'ghp_test123',
|
|
142
|
+
};
|
|
143
|
+
await writeConfig(config);
|
|
144
|
+
expect(mockMkdir).not.toHaveBeenCalled();
|
|
145
|
+
});
|
|
146
|
+
it('should write config with github_token only', async () => {
|
|
147
|
+
mockExistsSync.mockReturnValue(true);
|
|
148
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
149
|
+
const config = {
|
|
150
|
+
github_token: 'ghp_test123',
|
|
151
|
+
};
|
|
152
|
+
await writeConfig(config);
|
|
153
|
+
expect(mockWriteFile).toHaveBeenCalledWith('/home/testuser/.sembix/config', expect.stringContaining('github_token=ghp_test123'), { mode: 0o600 });
|
|
154
|
+
});
|
|
155
|
+
it('should write config with both fields', async () => {
|
|
156
|
+
mockExistsSync.mockReturnValue(true);
|
|
157
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
158
|
+
const config = {
|
|
159
|
+
github_token: 'ghp_test123',
|
|
160
|
+
default_github_org: 'acme-corp',
|
|
161
|
+
};
|
|
162
|
+
await writeConfig(config);
|
|
163
|
+
const writeCall = mockWriteFile.mock.calls[0];
|
|
164
|
+
const content = writeCall[1];
|
|
165
|
+
expect(content).toContain('github_token=ghp_test123');
|
|
166
|
+
expect(content).toContain('default_github_org=acme-corp');
|
|
167
|
+
expect(writeCall[2]).toEqual({ mode: 0o600 });
|
|
168
|
+
});
|
|
169
|
+
it('should include header comments', async () => {
|
|
170
|
+
mockExistsSync.mockReturnValue(true);
|
|
171
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
172
|
+
const config = {
|
|
173
|
+
github_token: 'ghp_test123',
|
|
174
|
+
};
|
|
175
|
+
await writeConfig(config);
|
|
176
|
+
const content = mockWriteFile.mock.calls[0][1];
|
|
177
|
+
expect(content).toContain('# Sembix CLI Configuration');
|
|
178
|
+
expect(content).toContain('# Generated by: sembix configure');
|
|
179
|
+
});
|
|
180
|
+
it('should end with trailing newline', async () => {
|
|
181
|
+
mockExistsSync.mockReturnValue(true);
|
|
182
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
183
|
+
const config = {
|
|
184
|
+
github_token: 'ghp_test123',
|
|
185
|
+
};
|
|
186
|
+
await writeConfig(config);
|
|
187
|
+
const content = mockWriteFile.mock.calls[0][1];
|
|
188
|
+
expect(content.endsWith('\n')).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
it('should handle empty config object', async () => {
|
|
191
|
+
mockExistsSync.mockReturnValue(true);
|
|
192
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
193
|
+
const config = {};
|
|
194
|
+
await writeConfig(config);
|
|
195
|
+
const content = mockWriteFile.mock.calls[0][1];
|
|
196
|
+
expect(content).toContain('# Sembix CLI Configuration');
|
|
197
|
+
expect(content).not.toContain('github_token=');
|
|
198
|
+
expect(content).not.toContain('default_github_org=');
|
|
199
|
+
});
|
|
200
|
+
it('should propagate write errors', async () => {
|
|
201
|
+
mockExistsSync.mockReturnValue(true);
|
|
202
|
+
mockWriteFile.mockRejectedValue(new Error('Disk full'));
|
|
203
|
+
const config = {
|
|
204
|
+
github_token: 'ghp_test123',
|
|
205
|
+
};
|
|
206
|
+
await expect(writeConfig(config)).rejects.toThrow('Disk full');
|
|
207
|
+
});
|
|
208
|
+
it('should propagate mkdir errors', async () => {
|
|
209
|
+
mockExistsSync.mockReturnValue(false);
|
|
210
|
+
mockMkdir.mockRejectedValue(new Error('Permission denied'));
|
|
211
|
+
const config = {
|
|
212
|
+
github_token: 'ghp_test123',
|
|
213
|
+
};
|
|
214
|
+
await expect(writeConfig(config)).rejects.toThrow('Permission denied');
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=config-file.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/config-file.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface SembixConfig {
|
|
2
|
+
github_token?: string;
|
|
3
|
+
default_github_org?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Reads the configuration from ~/.sembix/config
|
|
7
|
+
* Returns an empty object if the file doesn't exist
|
|
8
|
+
*/
|
|
9
|
+
export declare function readConfig(): Promise<SembixConfig>;
|
|
10
|
+
/**
|
|
11
|
+
* Writes configuration to ~/.sembix/config
|
|
12
|
+
* Creates the directory if it doesn't exist
|
|
13
|
+
*/
|
|
14
|
+
export declare function writeConfig(config: SembixConfig): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the path to the config file for display purposes
|
|
17
|
+
*/
|
|
18
|
+
export declare function getConfigPath(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if the config file exists
|
|
21
|
+
*/
|
|
22
|
+
export declare function configExists(): boolean;
|
|
23
|
+
//# sourceMappingURL=config-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../../src/utils/config-file.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAWD;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAaxD;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrE;AAwDD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
const CONFIG_DIR = join(homedir(), '.sembix');
|
|
6
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config');
|
|
7
|
+
/**
|
|
8
|
+
* Ensures the ~/.sembix directory exists with proper permissions
|
|
9
|
+
*/
|
|
10
|
+
async function ensureConfigDirectory() {
|
|
11
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
12
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Reads the configuration from ~/.sembix/config
|
|
17
|
+
* Returns an empty object if the file doesn't exist
|
|
18
|
+
*/
|
|
19
|
+
export async function readConfig() {
|
|
20
|
+
try {
|
|
21
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
const content = await fs.readFile(CONFIG_FILE, 'utf-8');
|
|
25
|
+
return parseConfig(content);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// If we can't read the config, return empty object
|
|
29
|
+
// This allows the app to fall back to other config sources
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Writes configuration to ~/.sembix/config
|
|
35
|
+
* Creates the directory if it doesn't exist
|
|
36
|
+
*/
|
|
37
|
+
export async function writeConfig(config) {
|
|
38
|
+
await ensureConfigDirectory();
|
|
39
|
+
const content = formatConfig(config);
|
|
40
|
+
// Write with restricted permissions (only user can read/write)
|
|
41
|
+
await fs.writeFile(CONFIG_FILE, content, { mode: 0o600 });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parses INI-style config content into a SembixConfig object
|
|
45
|
+
*/
|
|
46
|
+
function parseConfig(content) {
|
|
47
|
+
const config = {};
|
|
48
|
+
const lines = content.split('\n');
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
const trimmed = line.trim();
|
|
51
|
+
// Skip empty lines and comments
|
|
52
|
+
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith(';')) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Parse key=value pairs
|
|
56
|
+
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
57
|
+
if (match) {
|
|
58
|
+
const key = match[1].trim();
|
|
59
|
+
const value = match[2].trim();
|
|
60
|
+
if (key === 'github_token') {
|
|
61
|
+
config.github_token = value;
|
|
62
|
+
}
|
|
63
|
+
else if (key === 'default_github_org') {
|
|
64
|
+
config.default_github_org = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return config;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Formats a SembixConfig object into INI-style content
|
|
72
|
+
*/
|
|
73
|
+
function formatConfig(config) {
|
|
74
|
+
const lines = [
|
|
75
|
+
'# Sembix CLI Configuration',
|
|
76
|
+
'# Generated by: sembix configure',
|
|
77
|
+
'',
|
|
78
|
+
];
|
|
79
|
+
if (config.github_token) {
|
|
80
|
+
lines.push(`github_token=${config.github_token}`);
|
|
81
|
+
}
|
|
82
|
+
if (config.default_github_org) {
|
|
83
|
+
lines.push(`default_github_org=${config.default_github_org}`);
|
|
84
|
+
}
|
|
85
|
+
lines.push(''); // trailing newline
|
|
86
|
+
return lines.join('\n');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns the path to the config file for display purposes
|
|
90
|
+
*/
|
|
91
|
+
export function getConfigPath() {
|
|
92
|
+
return CONFIG_FILE;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Checks if the config file exists
|
|
96
|
+
*/
|
|
97
|
+
export function configExists() {
|
|
98
|
+
return existsSync(CONFIG_FILE);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=config-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/utils/config-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAO/C;;GAEG;AACH,KAAK,UAAU,qBAAqB;IAClC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;QACnD,2DAA2D;QAC3D,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAoB;IACpD,MAAM,qBAAqB,EAAE,CAAC;IAE9B,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAErC,+DAA+D;IAC/D,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAEhC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,gCAAgC;QAChC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACnE,SAAS;QACX,CAAC;QAED,wBAAwB;QACxB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAE9B,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;gBAC3B,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC;YAC9B,CAAC;iBAAM,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;gBACxC,MAAM,CAAC,kBAAkB,GAAG,KAAK,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,MAAoB;IACxC,MAAM,KAAK,GAAa;QACtB,4BAA4B;QAC5B,kCAAkC;QAClC,EAAE;KACH,CAAC;IAEF,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -27,7 +27,7 @@ export async function loadConfigFile(configPath) {
|
|
|
27
27
|
}
|
|
28
28
|
else {
|
|
29
29
|
// Extract error messages from Zod
|
|
30
|
-
const errors = result.error.
|
|
30
|
+
const errors = result.error.issues.map(err => {
|
|
31
31
|
const path = err.path.join('.');
|
|
32
32
|
return `${path}: ${err.message}`;
|
|
33
33
|
});
|
|
@@ -305,19 +305,19 @@ function validateMergedConfig(merged, cliFlags) {
|
|
|
305
305
|
if (cliFlags.awsAccountId !== undefined && merged.awsAccountId) {
|
|
306
306
|
const result = awsAccountIdSchema.safeParse(merged.awsAccountId);
|
|
307
307
|
if (!result.success) {
|
|
308
|
-
errors.push(`--aws-account-id: ${result.error.
|
|
308
|
+
errors.push(`--aws-account-id: ${result.error.issues[0].message}`);
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
if (cliFlags.customerRoleArn !== undefined && merged.customerRoleArn) {
|
|
312
312
|
const result = iamRoleArnSchema.safeParse(merged.customerRoleArn);
|
|
313
313
|
if (!result.success) {
|
|
314
|
-
errors.push(`--customer-role-arn: ${result.error.
|
|
314
|
+
errors.push(`--customer-role-arn: ${result.error.issues[0].message}`);
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
if (cliFlags.cloudfrontCertArn !== undefined && merged.tls?.cloudfrontCertArn) {
|
|
318
318
|
const result = acmCertArnSchema.safeParse(merged.tls.cloudfrontCertArn);
|
|
319
319
|
if (!result.success) {
|
|
320
|
-
errors.push(`--cloudfront-cert-arn: ${result.error.
|
|
320
|
+
errors.push(`--cloudfront-cert-arn: ${result.error.issues[0].message}`);
|
|
321
321
|
}
|
|
322
322
|
// Special check: CloudFront cert must be in us-east-1
|
|
323
323
|
if (result.success && !merged.tls.cloudfrontCertArn.includes('us-east-1')) {
|
|
@@ -327,13 +327,13 @@ function validateMergedConfig(merged, cliFlags) {
|
|
|
327
327
|
if (cliFlags.bffAlbCertArn !== undefined && merged.tls?.bffAlbCertificateArn) {
|
|
328
328
|
const result = acmCertArnSchema.safeParse(merged.tls.bffAlbCertificateArn);
|
|
329
329
|
if (!result.success) {
|
|
330
|
-
errors.push(`--bff-alb-cert-arn: ${result.error.
|
|
330
|
+
errors.push(`--bff-alb-cert-arn: ${result.error.issues[0].message}`);
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
if (cliFlags.hostedZoneId !== undefined && merged.tls?.hostedZoneId) {
|
|
334
334
|
const result = route53ZoneIdSchema.safeParse(merged.tls.hostedZoneId);
|
|
335
335
|
if (!result.success) {
|
|
336
|
-
errors.push(`--hosted-zone-id: ${result.error.
|
|
336
|
+
errors.push(`--hosted-zone-id: ${result.error.issues[0].message}`);
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
339
|
// Validate IAM roles from CLI flags
|
|
@@ -348,7 +348,7 @@ function validateMergedConfig(merged, cliFlags) {
|
|
|
348
348
|
if (value) {
|
|
349
349
|
const result = iamRoleArnSchema.safeParse(value);
|
|
350
350
|
if (!result.success) {
|
|
351
|
-
errors.push(`${name}: ${result.error.
|
|
351
|
+
errors.push(`${name}: ${result.error.issues[0].message}`);
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
354
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sembix/cli",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "CLI tool for managing Sembix products",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -53,37 +53,37 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@inquirer/prompts": "^
|
|
57
|
-
"@octokit/rest": "^
|
|
58
|
-
"chalk": "^5.
|
|
59
|
-
"commander": "^
|
|
60
|
-
"dotenv": "^
|
|
61
|
-
"js-yaml": "^4.1.
|
|
56
|
+
"@inquirer/prompts": "^8.0.1",
|
|
57
|
+
"@octokit/rest": "^22.0.1",
|
|
58
|
+
"chalk": "^5.6.2",
|
|
59
|
+
"commander": "^14.0.2",
|
|
60
|
+
"dotenv": "^17.2.3",
|
|
61
|
+
"js-yaml": "^4.1.1",
|
|
62
62
|
"libsodium-wrappers": "^0.7.15",
|
|
63
|
-
"ora": "^
|
|
64
|
-
"zod": "^
|
|
63
|
+
"ora": "^9.0.0",
|
|
64
|
+
"zod": "^4.1.12"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@semantic-release/changelog": "^6.0.3",
|
|
68
|
-
"@semantic-release/commit-analyzer": "^13.0.
|
|
68
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
69
69
|
"@semantic-release/git": "^10.0.1",
|
|
70
|
-
"@semantic-release/github": "^
|
|
71
|
-
"@semantic-release/npm": "^
|
|
72
|
-
"@semantic-release/release-notes-generator": "^14.
|
|
70
|
+
"@semantic-release/github": "^12.0.2",
|
|
71
|
+
"@semantic-release/npm": "^13.1.2",
|
|
72
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
73
73
|
"@types/js-yaml": "^4.0.9",
|
|
74
|
-
"conventional-changelog-conventionalcommits": "^
|
|
74
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
75
75
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
76
|
-
"@types/node": "^
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
78
|
-
"@typescript-eslint/parser": "^8.
|
|
79
|
-
"@vitest/coverage-v8": "^4.0.
|
|
80
|
-
"@vitest/ui": "^4.0.
|
|
81
|
-
"eslint": "^9.
|
|
76
|
+
"@types/node": "^24.10.1",
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
|
78
|
+
"@typescript-eslint/parser": "^8.47.0",
|
|
79
|
+
"@vitest/coverage-v8": "^4.0.13",
|
|
80
|
+
"@vitest/ui": "^4.0.13",
|
|
81
|
+
"eslint": "^9.39.1",
|
|
82
82
|
"happy-dom": "^20.0.10",
|
|
83
|
-
"semantic-release": "^
|
|
84
|
-
"tsx": "^4.
|
|
85
|
-
"typescript": "^5.
|
|
86
|
-
"vitest": "^4.0.
|
|
83
|
+
"semantic-release": "^25.0.2",
|
|
84
|
+
"tsx": "^4.20.6",
|
|
85
|
+
"typescript": "^5.9.3",
|
|
86
|
+
"vitest": "^4.0.13"
|
|
87
87
|
},
|
|
88
88
|
"engines": {
|
|
89
89
|
"node": ">=20.0.0"
|
|
Binary file
|