@sembix/cli 1.1.0 → 1.2.0

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 (42) hide show
  1. package/.env.example +7 -0
  2. package/README.md +161 -8
  3. package/dist/__tests__/config.test.d.ts +2 -0
  4. package/dist/__tests__/config.test.d.ts.map +1 -0
  5. package/dist/__tests__/config.test.js +75 -0
  6. package/dist/__tests__/config.test.js.map +1 -0
  7. package/dist/__tests__/integration/configure.test.d.ts +2 -0
  8. package/dist/__tests__/integration/configure.test.d.ts.map +1 -0
  9. package/dist/__tests__/integration/configure.test.js +247 -0
  10. package/dist/__tests__/integration/configure.test.js.map +1 -0
  11. package/dist/commands/__tests__/configure.test.d.ts +2 -0
  12. package/dist/commands/__tests__/configure.test.d.ts.map +1 -0
  13. package/dist/commands/__tests__/configure.test.js +229 -0
  14. package/dist/commands/__tests__/configure.test.js.map +1 -0
  15. package/dist/commands/configure.d.ts +6 -0
  16. package/dist/commands/configure.d.ts.map +1 -0
  17. package/dist/commands/configure.js +90 -0
  18. package/dist/commands/configure.js.map +1 -0
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +19 -3
  21. package/dist/config.js.map +1 -1
  22. package/dist/index.js +17 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/prompts/__tests__/environment-setup.test.d.ts +2 -0
  25. package/dist/prompts/__tests__/environment-setup.test.d.ts.map +1 -0
  26. package/dist/prompts/__tests__/environment-setup.test.js +206 -0
  27. package/dist/prompts/__tests__/environment-setup.test.js.map +1 -0
  28. package/dist/prompts/__tests__/hub-integration.test.d.ts +2 -0
  29. package/dist/prompts/__tests__/hub-integration.test.d.ts.map +1 -0
  30. package/dist/prompts/__tests__/hub-integration.test.js +126 -0
  31. package/dist/prompts/__tests__/hub-integration.test.js.map +1 -0
  32. package/dist/sembix-cli-1.2.0.tgz +0 -0
  33. package/dist/utils/__tests__/config-file.test.d.ts +2 -0
  34. package/dist/utils/__tests__/config-file.test.d.ts.map +1 -0
  35. package/dist/utils/__tests__/config-file.test.js +218 -0
  36. package/dist/utils/__tests__/config-file.test.js.map +1 -0
  37. package/dist/utils/config-file.d.ts +23 -0
  38. package/dist/utils/config-file.d.ts.map +1 -0
  39. package/dist/utils/config-file.js +100 -0
  40. package/dist/utils/config-file.js.map +1 -0
  41. package/package.json +1 -1
  42. package/dist/sembix-cli-1.1.0.tgz +0 -0
package/.env.example CHANGED
@@ -1,3 +1,10 @@
1
+ # Sembix CLI Environment Variables
2
+ #
3
+ # RECOMMENDED: Use 'sembix configure' instead of this .env file
4
+ # This will securely store your credentials in ~/.sembix/config
5
+ #
6
+ # Run: sembix configure
7
+
1
8
  # GitHub Personal Access Token
2
9
  # Required scopes: repo, workflow
3
10
  GITHUB_TOKEN=ghp_your_token_here
package/README.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  A terminal-based CLI tool for managing Sembix products. An intuitive command-line interface designed for technical users.
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Features](#features)
8
+ - [Prerequisites](#prerequisites)
9
+ - [Deployment Process](#deployment-process)
10
+ - [Installation](#installation)
11
+ - [Configuration](#configuration)
12
+ - [Option 1: Interactive Configuration (Recommended)](#option-1-interactive-configuration-recommended)
13
+ - [Option 2: Environment Variables (.env file)](#option-2-environment-variables-env-file)
14
+ - [Option 3: Config File (Recommended for Automation)](#option-3-config-file-recommended-for-automation)
15
+ - [Creating a GitHub Token](#creating-a-github-token)
16
+ - [Credential Priority](#credential-priority)
17
+ - [Usage](#usage)
18
+ - [Quick Start](#quick-start)
19
+ - [Example: Complete First-Time Setup](#example-complete-first-time-setup)
20
+ - [Commands](#commands)
21
+ - [`sembix configure`](#sembix-configure)
22
+ - [`sembix studio create`](#sembix-studio-create)
23
+ - [`sembix studio update`](#sembix-studio-update)
24
+ - [`sembix studio add-hub`](#sembix-studio-add-hub)
25
+ - [`sembix studio list`](#sembix-studio-list)
26
+ - [Workflow](#workflow)
27
+ - [Configuration Priority](#configuration-priority)
28
+ - [Config File Reference](#config-file-reference)
29
+ - [Use Cases](#use-cases)
30
+ - [Development](#development)
31
+ - [Troubleshooting](#troubleshooting)
32
+ - [Advanced Topics](#advanced-topics)
33
+ - [License](#license)
34
+ - [Support](#support)
35
+ - [See Also](#see-also)
36
+
5
37
  ## Features
6
38
 
7
39
  - 🚀 **Interactive Setup** - Guided prompts for environment configuration with detailed explanations
@@ -85,9 +117,23 @@ npm run dev -- studio create
85
117
 
86
118
  ## Configuration
87
119
 
88
- ### Option 1: Environment Variables (.env file)
120
+ ### Option 1: Interactive Configuration (Recommended)
121
+
122
+ The easiest way to get started is using the interactive configuration command:
123
+
124
+ ```bash
125
+ sembix configure
126
+ ```
127
+
128
+ This will prompt you for:
129
+ - **GitHub Personal Access Token** (required)
130
+ - **Default GitHub Organization** (optional)
89
131
 
90
- Create a `.env` file in the project root directory:
132
+ Your credentials will be securely stored in `~/.sembix/config` with restricted file permissions (0600).
133
+
134
+ ### Option 2: Environment Variables (.env file)
135
+
136
+ Alternatively, create a `.env` file in the project root directory:
91
137
 
92
138
  ```bash
93
139
  cp .env.example .env
@@ -103,7 +149,7 @@ GITHUB_TOKEN=ghp_your_token_here
103
149
  DEFAULT_GITHUB_ORG=your-org
104
150
  ```
105
151
 
106
- ### Option 2: Config File (Recommended for Automation)
152
+ ### Option 3: Config File (Recommended for Automation)
107
153
 
108
154
  Create a YAML config file for your environment:
109
155
 
@@ -136,13 +182,35 @@ See [`config.example.yaml`](./config.example.yaml) for a complete configuration
136
182
  - ✅ `repo` (all sub-scopes)
137
183
  - ✅ `workflow`
138
184
  4. Generate and copy the token
139
- 5. Add to `.env` file or use `--token` flag
185
+ 5. Run `sembix configure` to store it securely, or add to `.env` file, or use `--token` flag
186
+
187
+ ### Credential Priority
188
+
189
+ The CLI checks for credentials in this order (highest to lowest priority):
190
+ 1. `--token` flag
191
+ 2. `GITHUB_TOKEN` environment variable
192
+ 3. `~/.sembix/config` (created by `sembix configure`)
193
+ 4. Project `.env` file
140
194
 
141
195
  ## Usage
142
196
 
143
197
  ### Quick Start
144
198
 
145
- For a complete deployment, follow the **two-phased process** (see [Deployment Process](#deployment-process) section above):
199
+ **Step 1: Configure credentials (first time only)**
200
+
201
+ ```bash
202
+ sembix configure
203
+ ```
204
+
205
+ This interactive command will prompt you for:
206
+ - GitHub Personal Access Token
207
+ - Default GitHub organization (optional)
208
+
209
+ Your credentials are saved securely to `~/.sembix/config`.
210
+
211
+ **Step 2: Create your environment**
212
+
213
+ For a complete deployment, follow the **two-phased process**:
146
214
 
147
215
  ```bash
148
216
  # PHASE 1: Bootstrap deployment
@@ -157,6 +225,8 @@ sembix studio add-hub <environment>
157
225
  # → Studio environment fully operational
158
226
  ```
159
227
 
228
+ See the [Deployment Process](#deployment-process) section above for detailed explanation.
229
+
160
230
  **Alternative workflows:**
161
231
 
162
232
  ```bash
@@ -176,8 +246,85 @@ sembix studio create production \
176
246
  # ... (all other flags)
177
247
  ```
178
248
 
249
+ ### Example: Complete First-Time Setup
250
+
251
+ ```bash
252
+ # 1. Configure credentials
253
+ $ sembix configure
254
+ GitHub Personal Access Token: ****
255
+ Default GitHub Organization (optional): acme-corp
256
+ ✓ Configuration saved successfully!
257
+
258
+ # 2. Create environment interactively
259
+ $ sembix studio create
260
+ ? Select deployment repository: acme-corp/sembix-deployment
261
+ ? Environment name: production
262
+ ? AWS Account ID: 123456789012
263
+ ... [continues with prompts]
264
+ ✓ Environment created successfully!
265
+
266
+ # 3. Deploy via GitHub Actions (in browser)
267
+ # → Go to GitHub Actions
268
+ # → Run workflow for "production" environment
269
+ # → Wait for deployment
270
+ # → Copy Hub role ARNs from output
271
+
272
+ # 4. Add Hub integration
273
+ $ sembix studio add-hub production
274
+ ? Hub Engine Execution Role ARN: arn:aws:iam::999999999999:role/hub-engine
275
+ ... [continues with prompts]
276
+ ✓ Hub integration configured!
277
+
278
+ # 5. Deploy again via GitHub Actions
279
+ # → Run workflow again
280
+ # → Studio is now fully operational!
281
+ ```
282
+
179
283
  ## Commands
180
284
 
285
+ ### `sembix configure`
286
+
287
+ Configure Sembix CLI credentials and settings interactively.
288
+
289
+ **Syntax:**
290
+
291
+ ```bash
292
+ sembix configure
293
+ ```
294
+
295
+ **What it does:**
296
+ 1. Prompts for your GitHub Personal Access Token (with validation)
297
+ 2. Prompts for your default GitHub organization (optional)
298
+ 3. Saves configuration securely to `~/.sembix/config` with file permissions 0600
299
+
300
+ **When to use:**
301
+ - First time setup (recommended for all users)
302
+ - Updating your GitHub token when it expires
303
+ - Changing your default organization
304
+
305
+ **Example:**
306
+
307
+ ```bash
308
+ $ sembix configure
309
+
310
+ Configure Sembix CLI
311
+
312
+ This will store your configuration in:
313
+ ~/.sembix/config
314
+
315
+ ? GitHub Personal Access Token: ****
316
+ ? Default GitHub Organization (optional): acme-corp
317
+
318
+ ✓ Configuration saved successfully!
319
+
320
+ Your credentials are stored securely in:
321
+ ~/.sembix/config
322
+
323
+ You can now run Sembix commands without the --token flag.
324
+ ```
325
+
326
+ ---
327
+
181
328
  ### `sembix studio create`
182
329
 
183
330
  Create a new Sembix Studio environment with complete configuration.
@@ -701,15 +848,21 @@ studio
701
848
 
702
849
  ## Troubleshooting
703
850
 
704
- ### "GITHUB_TOKEN environment variable is required"
851
+ ### "GitHub token is required"
852
+
853
+ If you see this error, you need to configure your GitHub token. The easiest method is:
854
+
855
+ ```bash
856
+ sembix configure
857
+ ```
705
858
 
706
- Make sure you have a `.env` file in the project root directory with your token:
859
+ Alternatively, create a `.env` file:
707
860
 
708
861
  ```env
709
862
  GITHUB_TOKEN=ghp_your_token_here
710
863
  ```
711
864
 
712
- Or pass the token via CLI:
865
+ Or pass the token directly via CLI:
713
866
 
714
867
  ```bash
715
868
  sembix studio create --token ghp_your_token_here
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ // Must mock BEFORE importing config module
3
+ vi.mock('../utils/config-file.js', () => ({
4
+ readConfig: vi.fn().mockResolvedValue({}),
5
+ getConfigPath: vi.fn().mockReturnValue('/home/testuser/.sembix/config'),
6
+ }));
7
+ // Mock dotenv
8
+ vi.mock('dotenv', () => ({
9
+ default: {
10
+ config: vi.fn(),
11
+ },
12
+ }));
13
+ describe('config', () => {
14
+ describe('validateConfig', () => {
15
+ let originalGithubToken;
16
+ beforeEach(() => {
17
+ // Save and clear GITHUB_TOKEN
18
+ originalGithubToken = process.env.GITHUB_TOKEN;
19
+ delete process.env.GITHUB_TOKEN;
20
+ });
21
+ afterEach(() => {
22
+ // Restore GITHUB_TOKEN
23
+ if (originalGithubToken !== undefined) {
24
+ process.env.GITHUB_TOKEN = originalGithubToken;
25
+ }
26
+ });
27
+ it('should throw error when no token is configured', async () => {
28
+ // Re-import to get fresh module with mocked env
29
+ const { validateConfig } = await import('../config.js');
30
+ try {
31
+ validateConfig();
32
+ expect.fail('Should have thrown an error');
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ }
35
+ catch (error) {
36
+ expect(error.message).toContain('GitHub token is required');
37
+ }
38
+ });
39
+ it('should include all configuration methods in error message', async () => {
40
+ const { validateConfig } = await import('../config.js');
41
+ try {
42
+ validateConfig();
43
+ expect.fail('Should have thrown an error');
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ }
46
+ catch (error) {
47
+ expect(error.message).toContain('Run: sembix configure');
48
+ expect(error.message).toContain('Set GITHUB_TOKEN environment variable');
49
+ expect(error.message).toContain('Pass --token flag');
50
+ expect(error.message).toContain('Create a .env file with GITHUB_TOKEN');
51
+ }
52
+ });
53
+ it('should include config file location in error message', async () => {
54
+ const { validateConfig } = await import('../config.js');
55
+ try {
56
+ validateConfig();
57
+ expect.fail('Should have thrown an error');
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ }
60
+ catch (error) {
61
+ expect(error.message).toContain('.sembix/config');
62
+ }
63
+ });
64
+ it('should not throw when token is present', async () => {
65
+ // Set token before importing
66
+ process.env.GITHUB_TOKEN = 'ghp_test_token';
67
+ // Reset modules to force fresh import
68
+ vi.resetModules();
69
+ // Re-import with token set
70
+ const { validateConfig } = await import('../config.js');
71
+ expect(() => validateConfig()).not.toThrow();
72
+ });
73
+ });
74
+ });
75
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configure.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/configure.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,247 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { promises as fs } from 'fs';
3
+ import { existsSync } from 'fs';
4
+ import { configureCommand } from '../../commands/configure.js';
5
+ import * as prompts from '@inquirer/prompts';
6
+ import { join } from 'path';
7
+ // Mock prompts
8
+ vi.mock('@inquirer/prompts');
9
+ // Mock chalk to avoid ANSI codes in tests
10
+ const createChalkMock = () => {
11
+ const mockFn = (str) => str;
12
+ return new Proxy(mockFn, {
13
+ get: () => createChalkMock(),
14
+ apply: (target, thisArg, args) => args[0],
15
+ });
16
+ };
17
+ vi.mock('chalk', () => ({
18
+ default: createChalkMock(),
19
+ }));
20
+ // Mock ui utilities
21
+ vi.mock('../../utils/ui.js', () => ({
22
+ banner: vi.fn(),
23
+ highlight: vi.fn((text) => text),
24
+ dim: vi.fn((text) => text),
25
+ success: vi.fn(),
26
+ spinner: vi.fn(() => ({ stop: vi.fn() })),
27
+ }));
28
+ // Mock os.homedir to use temp directory for tests
29
+ // Use process.cwd() with manual path construction to avoid hoisting issues
30
+ vi.mock('os', () => {
31
+ return {
32
+ homedir: vi.fn(() => `${process.cwd()}/.tmp-test/sembix-test-integration`),
33
+ tmpdir: () => '/tmp',
34
+ };
35
+ });
36
+ const mockPassword = vi.mocked(prompts.password);
37
+ const mockInput = vi.mocked(prompts.input);
38
+ const mockConfirm = vi.mocked(prompts.confirm);
39
+ describe('configure command - Integration Tests', () => {
40
+ const testConfigDir = `${process.cwd()}/.tmp-test/sembix-test-integration`;
41
+ const configPath = join(testConfigDir, '.sembix', 'config');
42
+ beforeEach(async () => {
43
+ vi.clearAllMocks();
44
+ // Clean up test directory
45
+ try {
46
+ await fs.rm(join(testConfigDir, '.sembix'), { recursive: true, force: true });
47
+ }
48
+ catch {
49
+ // Ignore if doesn't exist
50
+ }
51
+ });
52
+ afterEach(async () => {
53
+ // Clean up after tests
54
+ try {
55
+ await fs.rm(join(testConfigDir, '.sembix'), { recursive: true, force: true });
56
+ }
57
+ catch {
58
+ // Ignore cleanup errors
59
+ }
60
+ });
61
+ describe('first-time configuration', () => {
62
+ it('should create config directory and file', async () => {
63
+ mockPassword.mockResolvedValue('ghp_testtoken123');
64
+ mockInput.mockResolvedValue('test-org');
65
+ await configureCommand();
66
+ // Verify directory was created
67
+ expect(existsSync(join(testConfigDir, '.sembix'))).toBe(true);
68
+ // Verify file was created
69
+ expect(existsSync(configPath)).toBe(true);
70
+ // Verify content
71
+ const content = await fs.readFile(configPath, 'utf-8');
72
+ expect(content).toContain('github_token=ghp_testtoken123');
73
+ expect(content).toContain('default_github_org=test-org');
74
+ });
75
+ it('should create config with token only', async () => {
76
+ mockPassword.mockResolvedValue('ghp_testtoken456');
77
+ mockInput.mockResolvedValue('');
78
+ await configureCommand();
79
+ const content = await fs.readFile(configPath, 'utf-8');
80
+ expect(content).toContain('github_token=ghp_testtoken456');
81
+ expect(content).not.toContain('default_github_org=');
82
+ });
83
+ it('should set correct file permissions (0600)', async () => {
84
+ mockPassword.mockResolvedValue('ghp_testtoken789');
85
+ mockInput.mockResolvedValue('');
86
+ await configureCommand();
87
+ const stats = await fs.stat(configPath);
88
+ // Check that file is readable and writable by owner only
89
+ // 0o100600 is the full mode including file type bits
90
+ expect(stats.mode & 0o777).toBe(0o600);
91
+ });
92
+ it('should include header comments in config file', async () => {
93
+ mockPassword.mockResolvedValue('ghp_testtoken');
94
+ mockInput.mockResolvedValue('');
95
+ await configureCommand();
96
+ const content = await fs.readFile(configPath, 'utf-8');
97
+ expect(content).toContain('# Sembix CLI Configuration');
98
+ expect(content).toContain('# Generated by: sembix configure');
99
+ });
100
+ });
101
+ describe('updating existing configuration', () => {
102
+ it('should preserve existing token when user chooses to keep it', async () => {
103
+ // Create initial config
104
+ mockPassword.mockResolvedValue('ghp_initialtoken');
105
+ mockInput.mockResolvedValue('initial-org');
106
+ await configureCommand();
107
+ // Update config, keeping token
108
+ vi.clearAllMocks();
109
+ mockConfirm.mockResolvedValue(true); // Keep existing token
110
+ mockInput.mockResolvedValue('updated-org');
111
+ await configureCommand();
112
+ const content = await fs.readFile(configPath, 'utf-8');
113
+ expect(content).toContain('github_token=ghp_initialtoken');
114
+ expect(content).toContain('default_github_org=updated-org');
115
+ });
116
+ it('should update token when user chooses to replace it', async () => {
117
+ // Create initial config
118
+ mockPassword.mockResolvedValue('ghp_initialtoken');
119
+ mockInput.mockResolvedValue('initial-org');
120
+ await configureCommand();
121
+ // Update config, replacing token
122
+ vi.clearAllMocks();
123
+ mockConfirm.mockResolvedValue(false); // Replace token
124
+ mockPassword.mockResolvedValue('ghp_newtoken');
125
+ mockInput.mockResolvedValue('initial-org');
126
+ await configureCommand();
127
+ const content = await fs.readFile(configPath, 'utf-8');
128
+ expect(content).toContain('github_token=ghp_newtoken');
129
+ expect(content).not.toContain('ghp_initialtoken');
130
+ });
131
+ it('should handle removing org by setting empty value', async () => {
132
+ // Create initial config with org
133
+ mockPassword.mockResolvedValue('ghp_token');
134
+ mockInput.mockResolvedValue('some-org');
135
+ await configureCommand();
136
+ // Update config, removing org
137
+ vi.clearAllMocks();
138
+ mockConfirm.mockResolvedValue(true);
139
+ mockInput.mockResolvedValue('');
140
+ await configureCommand();
141
+ const content = await fs.readFile(configPath, 'utf-8');
142
+ expect(content).toContain('github_token=ghp_token');
143
+ expect(content).not.toContain('default_github_org=');
144
+ });
145
+ });
146
+ describe('config file parsing', () => {
147
+ it('should correctly read back written configuration', async () => {
148
+ const testToken = 'ghp_roundtriptest';
149
+ const testOrg = 'roundtrip-org';
150
+ mockPassword.mockResolvedValue(testToken);
151
+ mockInput.mockResolvedValue(testOrg);
152
+ await configureCommand();
153
+ // Read the config file directly
154
+ const content = await fs.readFile(configPath, 'utf-8');
155
+ const lines = content.split('\n');
156
+ const tokenLine = lines.find((line) => line.startsWith('github_token='));
157
+ const orgLine = lines.find((line) => line.startsWith('default_github_org='));
158
+ expect(tokenLine).toBe(`github_token=${testToken}`);
159
+ expect(orgLine).toBe(`default_github_org=${testOrg}`);
160
+ });
161
+ it('should handle special characters in values', async () => {
162
+ const tokenWithSpecialChars = 'ghp_test-token.with_special/chars123';
163
+ const orgWithSpecialChars = 'org-name_with.special-chars';
164
+ mockPassword.mockResolvedValue(tokenWithSpecialChars);
165
+ mockInput.mockResolvedValue(orgWithSpecialChars);
166
+ await configureCommand();
167
+ const content = await fs.readFile(configPath, 'utf-8');
168
+ expect(content).toContain(`github_token=${tokenWithSpecialChars}`);
169
+ expect(content).toContain(`default_github_org=${orgWithSpecialChars}`);
170
+ });
171
+ });
172
+ describe('error scenarios', () => {
173
+ it('should handle write permission errors', async () => {
174
+ // Create config directory with no write permissions
175
+ await fs.mkdir(join(testConfigDir, '.sembix'), { recursive: true, mode: 0o555 });
176
+ mockPassword.mockResolvedValue('ghp_testtoken');
177
+ mockInput.mockResolvedValue('test-org');
178
+ await expect(configureCommand()).rejects.toThrow(/Failed to save configuration/);
179
+ // Cleanup: restore permissions
180
+ await fs.chmod(join(testConfigDir, '.sembix'), 0o755);
181
+ });
182
+ it('should validate token format', async () => {
183
+ mockPassword.mockResolvedValue('ghp_validtoken');
184
+ mockInput.mockResolvedValue('');
185
+ await configureCommand();
186
+ // Get the validation function that was passed to password()
187
+ const passwordOptions = mockPassword.mock.calls[0][0];
188
+ const validate = passwordOptions.validate;
189
+ expect(validate).toBeDefined();
190
+ if (validate) {
191
+ // Test valid tokens
192
+ expect(validate('ghp_validtoken123')).toBe(true);
193
+ expect(validate('github_pat_validtoken456')).toBe(true);
194
+ // Test invalid tokens
195
+ expect(validate('')).toBe('GitHub token is required');
196
+ expect(validate(' ')).toBe('GitHub token is required');
197
+ expect(validate('invalid_prefix_token')).toBe('Token should start with ghp_ or github_pat_');
198
+ }
199
+ });
200
+ });
201
+ describe('sequential updates', () => {
202
+ it('should handle multiple updates correctly', async () => {
203
+ // First update
204
+ mockPassword.mockResolvedValue('ghp_token1');
205
+ mockInput.mockResolvedValue('org1');
206
+ await configureCommand();
207
+ let content = await fs.readFile(configPath, 'utf-8');
208
+ expect(content).toContain('github_token=ghp_token1');
209
+ expect(content).toContain('default_github_org=org1');
210
+ // Second update - change org, keep token
211
+ vi.clearAllMocks();
212
+ mockConfirm.mockResolvedValue(true); // Keep token
213
+ mockInput.mockResolvedValue('org2');
214
+ await configureCommand();
215
+ content = await fs.readFile(configPath, 'utf-8');
216
+ expect(content).toContain('github_token=ghp_token1');
217
+ expect(content).toContain('default_github_org=org2');
218
+ // Third update - change token
219
+ vi.clearAllMocks();
220
+ mockConfirm.mockResolvedValue(false); // Replace token
221
+ mockPassword.mockResolvedValue('ghp_token3');
222
+ mockInput.mockResolvedValue('org3');
223
+ await configureCommand();
224
+ content = await fs.readFile(configPath, 'utf-8');
225
+ expect(content).toContain('github_token=ghp_token3');
226
+ expect(content).toContain('default_github_org=org3');
227
+ });
228
+ });
229
+ describe('config file format validation', () => {
230
+ it('should maintain INI format with proper structure', async () => {
231
+ mockPassword.mockResolvedValue('ghp_formattest');
232
+ mockInput.mockResolvedValue('format-org');
233
+ await configureCommand();
234
+ const content = await fs.readFile(configPath, 'utf-8');
235
+ const lines = content.split('\n').filter((line) => line.trim() !== '');
236
+ // Check header comments exist
237
+ expect(lines[0]).toMatch(/^#/);
238
+ expect(lines[1]).toMatch(/^#/);
239
+ // Check key=value format
240
+ const configLines = lines.filter((line) => !line.startsWith('#') && !line.startsWith(';'));
241
+ for (const line of configLines) {
242
+ expect(line).toMatch(/^[a-z_]+=.+$/);
243
+ }
244
+ });
245
+ });
246
+ });
247
+ //# sourceMappingURL=configure.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/configure.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configure.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/configure.test.ts"],"names":[],"mappings":""}