ai-devkit 0.3.2 → 0.4.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.
- package/README.md +15 -165
- package/dist/__tests__/lib/Config.test.d.ts +2 -0
- package/dist/__tests__/lib/Config.test.d.ts.map +1 -0
- package/dist/__tests__/lib/Config.test.js +281 -0
- package/dist/__tests__/lib/Config.test.js.map +1 -0
- package/dist/__tests__/lib/EnvironmentSelector.test.d.ts +2 -0
- package/dist/__tests__/lib/EnvironmentSelector.test.d.ts.map +1 -0
- package/dist/__tests__/lib/EnvironmentSelector.test.js +117 -0
- package/dist/__tests__/lib/EnvironmentSelector.test.js.map +1 -0
- package/dist/__tests__/lib/PhaseSelector.test.d.ts +2 -0
- package/dist/__tests__/lib/PhaseSelector.test.d.ts.map +1 -0
- package/dist/__tests__/lib/PhaseSelector.test.js +77 -0
- package/dist/__tests__/lib/PhaseSelector.test.js.map +1 -0
- package/dist/__tests__/util/env.test.d.ts +2 -0
- package/dist/__tests__/util/env.test.d.ts.map +1 -0
- package/dist/__tests__/util/env.test.js +166 -0
- package/dist/__tests__/util/env.test.js.map +1 -0
- package/dist/cli.js +0 -0
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +54 -67
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/phase.js +1 -1
- package/dist/commands/phase.js.map +1 -1
- package/dist/lib/Config.d.ts +5 -2
- package/dist/lib/Config.d.ts.map +1 -1
- package/dist/lib/Config.js +18 -3
- package/dist/lib/Config.js.map +1 -1
- package/dist/lib/EnvironmentSelector.d.ts +7 -0
- package/dist/lib/EnvironmentSelector.d.ts.map +1 -0
- package/dist/lib/EnvironmentSelector.js +62 -0
- package/dist/lib/EnvironmentSelector.js.map +1 -0
- package/dist/lib/PhaseSelector.d.ts +8 -0
- package/dist/lib/PhaseSelector.d.ts.map +1 -0
- package/dist/lib/PhaseSelector.js +58 -0
- package/dist/lib/PhaseSelector.js.map +1 -0
- package/dist/lib/TemplateManager.d.ts +5 -5
- package/dist/lib/TemplateManager.d.ts.map +1 -1
- package/dist/lib/TemplateManager.js +73 -60
- package/dist/lib/TemplateManager.js.map +1 -1
- package/dist/types.d.ts +9 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/util/env.d.ts +11 -0
- package/dist/util/env.d.ts.map +1 -0
- package/dist/util/env.js +109 -0
- package/dist/util/env.js.map +1 -0
- package/jest.config.js +22 -0
- package/package.json +16 -10
- package/web/.nojekyll +2 -0
- package/web/CNAME +1 -0
- package/web/README.md +100 -0
- package/web/app/favicon.ico +0 -0
- package/web/app/globals.css +122 -0
- package/web/app/layout.tsx +106 -0
- package/web/app/page.tsx +119 -0
- package/web/app/roadmap/page.tsx +150 -0
- package/web/app/robots.ts +16 -0
- package/web/app/sitemap.ts +46 -0
- package/web/app/vision/page.tsx +49 -0
- package/web/components/Footer.tsx +81 -0
- package/web/components/GitHubButton.tsx +49 -0
- package/web/components/GitHubStars.tsx +27 -0
- package/web/components/Header.tsx +108 -0
- package/web/components/MarkdownContent.tsx +35 -0
- package/web/components/SkipToContent.tsx +11 -0
- package/web/content/pages/vision.md +42 -0
- package/web/content/roadmap/1-web.md +9 -0
- package/web/content/roadmap/2-integrations.md +7 -0
- package/web/content/roadmap/3-cli-enhancements.md +8 -0
- package/web/content/roadmap/4-local-memory.md +8 -0
- package/web/eslint.config.mjs +18 -0
- package/web/lib/GitHubContext.tsx +57 -0
- package/web/lib/content/loader.ts +152 -0
- package/web/lib/content/types.ts +37 -0
- package/web/lib/utils.ts +12 -0
- package/web/next.config.ts +11 -0
- package/web/package-lock.json +8837 -0
- package/web/package.json +34 -0
- package/web/postcss.config.mjs +7 -0
- package/web/public/file.svg +1 -0
- package/web/public/globe.svg +1 -0
- package/web/public/next.svg +1 -0
- package/web/public/vercel.svg +1 -0
- package/web/public/window.svg +1 -0
- package/templates/env/claude/CLAUDE.md +0 -52
- package/templates/env/cursor/AGENTS.md +0 -51
- package/templates/env/cursor/rules/base.md +0 -1
package/README.md
CHANGED
|
@@ -43,6 +43,8 @@ This will:
|
|
|
43
43
|
2. Set up your AI development environment (Cursor/Claude Code)
|
|
44
44
|
3. Generate phase templates in `docs/ai/`
|
|
45
45
|
|
|
46
|
+
Detailed user guide can be found [here](https://ai-devkit.com/docs/).
|
|
47
|
+
|
|
46
48
|
## Available Phases
|
|
47
49
|
|
|
48
50
|
- **Requirements**: Problem understanding, requirements gathering, and success criteria
|
|
@@ -116,52 +118,19 @@ your-project/
|
|
|
116
118
|
└── [Environment-specific files]
|
|
117
119
|
```
|
|
118
120
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
├── review-requirements.md
|
|
133
|
-
└── capture-knowledge.md
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### For Claude Code:
|
|
137
|
-
```
|
|
138
|
-
└── .claude/
|
|
139
|
-
├── CLAUDE.md # Workspace configuration
|
|
140
|
-
└── commands/ # Custom commands (Markdown files)
|
|
141
|
-
├── new-requirement.md
|
|
142
|
-
├── code-review.md
|
|
143
|
-
├── execute-plan.md
|
|
144
|
-
├── writing-test.md
|
|
145
|
-
├── update-planning.md
|
|
146
|
-
├── check-implementation.md
|
|
147
|
-
├── review-design.md
|
|
148
|
-
├── review-requirements.md
|
|
149
|
-
└── capture-knowledge.md
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Customizing Templates
|
|
153
|
-
|
|
154
|
-
All templates are plain Markdown files with YAML frontmatter. You can customize them to fit your project's needs:
|
|
155
|
-
|
|
156
|
-
```markdown
|
|
157
|
-
---
|
|
158
|
-
phase: requirements
|
|
159
|
-
title: Requirements & Problem Understanding
|
|
160
|
-
description: Clarify the problem space, gather requirements, and define success criteria
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
# Your custom content here
|
|
164
|
-
```
|
|
121
|
+
Supported Tools & Agents:
|
|
122
|
+
| Agent | Support | Notes |
|
|
123
|
+
|-----------------------------------------------------------|---------|---------------------------------------------------|
|
|
124
|
+
| [Claude Code](https://www.anthropic.com/claude-code) | ✅ | |
|
|
125
|
+
| [GitHub Copilot](https://code.visualstudio.com/) | ✅ | |
|
|
126
|
+
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | ✅ | |
|
|
127
|
+
| [Cursor](https://cursor.sh/) | ✅ | |
|
|
128
|
+
| [opencode](https://opencode.ai/) | ✅ | |
|
|
129
|
+
| [Windsurf](https://windsurf.com/) | ✅ | |
|
|
130
|
+
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | ✅ | |
|
|
131
|
+
| [Roo Code](https://roocode.com/) | ✅ | |
|
|
132
|
+
| [Codex CLI](https://github.com/openai/codex) | ✅ | |
|
|
133
|
+
| [Amp](https://ampcode.com/) | ✅ | |
|
|
165
134
|
|
|
166
135
|
Templates are designed to provide structure while remaining concise and AI-friendly.
|
|
167
136
|
|
|
@@ -240,125 +209,6 @@ Commands can be referenced in Claude Code chats to guide AI assistance through y
|
|
|
240
209
|
8. **Monitor and iterate:**
|
|
241
210
|
- Set up monitoring per `docs/ai/monitoring/README.md`
|
|
242
211
|
|
|
243
|
-
### Adding a New Feature
|
|
244
|
-
|
|
245
|
-
**Use the `/new-requirement` command for a guided workflow:**
|
|
246
|
-
|
|
247
|
-
1. **In Cursor or Claude Code**, type `/new-requirement`
|
|
248
|
-
2. The AI will guide you through:
|
|
249
|
-
- 📋 Capturing requirement details
|
|
250
|
-
- 🔍 Creating feature-specific documentation
|
|
251
|
-
- 📐 Designing the solution
|
|
252
|
-
- 📅 Planning tasks and breaking down work
|
|
253
|
-
- 💻 Implementation (task by task)
|
|
254
|
-
- ✅ Testing and verification
|
|
255
|
-
- 🔀 Git commits and PR/MR creation
|
|
256
|
-
|
|
257
|
-
**Review and refine your documentation:**
|
|
258
|
-
- After drafting requirements, run `/review-requirements` to validate completeness
|
|
259
|
-
- After drafting design, run `/review-design` to ensure architecture clarity and mermaid diagrams
|
|
260
|
-
|
|
261
|
-
**Execute your plan:**
|
|
262
|
-
- Run `/execute-plan` to step through tasks interactively:
|
|
263
|
-
- Reads `docs/ai/planning/feature-{name}.md`
|
|
264
|
-
- Presents tasks in order with context
|
|
265
|
-
- Captures status/notes for each task
|
|
266
|
-
- Prompts you to update documentation as you progress
|
|
267
|
-
|
|
268
|
-
**Before pushing your code:**
|
|
269
|
-
- Run `/code-review` to perform a structured local review:
|
|
270
|
-
- Checks alignment with design docs
|
|
271
|
-
- Spots logic/security/performance issues
|
|
272
|
-
- Highlights redundant code and missing tests
|
|
273
|
-
- Suggests documentation updates
|
|
274
|
-
|
|
275
|
-
**Generate comprehensive tests:**
|
|
276
|
-
- Run `/writing-test` to create unit and integration tests targeting 100% coverage
|
|
277
|
-
|
|
278
|
-
This workflow creates feature-specific files:
|
|
279
|
-
- `docs/ai/requirements/feature-{name}.md`
|
|
280
|
-
- `docs/ai/design/feature-{name}.md`
|
|
281
|
-
- `docs/ai/planning/feature-{name}.md`
|
|
282
|
-
- `docs/ai/implementation/feature-{name}.md`
|
|
283
|
-
- `docs/ai/testing/feature-{name}.md`
|
|
284
|
-
|
|
285
|
-
### Understanding Existing Code
|
|
286
|
-
|
|
287
|
-
**Use the `/capture-knowledge` command to analyze and document code:**
|
|
288
|
-
|
|
289
|
-
The `capture-knowledge` command helps you understand how existing code works by analyzing it from any entry point and generating comprehensive documentation with visual diagrams.
|
|
290
|
-
|
|
291
|
-
**In Cursor:**
|
|
292
|
-
```
|
|
293
|
-
/capture-knowledge <entry-point> [options]
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
**In Claude Code:**
|
|
297
|
-
```
|
|
298
|
-
Use the capture-knowledge command to analyze <entry-point>
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
**Entry Point Types:**
|
|
302
|
-
- **File**: `/capture-knowledge src/api/users.ts` - Analyzes a specific file
|
|
303
|
-
- **Folder**: `/capture-knowledge src/services/` - Analyzes an entire module
|
|
304
|
-
- **Function**: `/capture-knowledge calculateTotalPrice` - Analyzes a specific function
|
|
305
|
-
- **API Endpoint**: `/capture-knowledge POST:/api/users` - Analyzes an API endpoint flow
|
|
306
|
-
|
|
307
|
-
**Options:**
|
|
308
|
-
- `--depth <n>` - Control recursion depth (default: 3)
|
|
309
|
-
- `--save` - Save output to `docs/ai/knowledge/`
|
|
310
|
-
- `--diagram-only` - Generate only diagrams
|
|
311
|
-
|
|
312
|
-
**What You Get:**
|
|
313
|
-
- 📖 **Detailed Explanation**: Natural language description of how the code works
|
|
314
|
-
- 🔍 **Implementation Details**: Key components, logic flow, and design patterns
|
|
315
|
-
- 🔗 **Recursive Dependency Analysis**: Automatically traces and explains all dependencies
|
|
316
|
-
- 📊 **Mermaid Diagrams**: Visual flowcharts, sequence diagrams, and architecture diagrams
|
|
317
|
-
- 💡 **Insights**: Performance considerations, security notes, potential improvements
|
|
318
|
-
|
|
319
|
-
**Example Outputs:**
|
|
320
|
-
|
|
321
|
-
For functions, you get:
|
|
322
|
-
- Flowchart showing execution path
|
|
323
|
-
- Parameter and return value documentation
|
|
324
|
-
- Called functions and their purposes
|
|
325
|
-
- Error handling strategy
|
|
326
|
-
|
|
327
|
-
For API endpoints, you get:
|
|
328
|
-
- Sequence diagram showing request flow
|
|
329
|
-
- Validation and authentication steps
|
|
330
|
-
- Database operations
|
|
331
|
-
- Response format
|
|
332
|
-
|
|
333
|
-
For modules/folders, you get:
|
|
334
|
-
- Architecture diagram showing component relationships
|
|
335
|
-
- Overview of each file's purpose
|
|
336
|
-
- Module boundaries and dependencies
|
|
337
|
-
|
|
338
|
-
**Use Cases:**
|
|
339
|
-
- 🎯 Onboarding new developers to understand the codebase
|
|
340
|
-
- 📚 Generating documentation for complex systems
|
|
341
|
-
- 🔍 Debugging by understanding complete execution flow
|
|
342
|
-
- 🏗️ Refactoring with full context of dependencies
|
|
343
|
-
- 📖 Creating knowledge base entries
|
|
344
|
-
|
|
345
|
-
**Example Workflow:**
|
|
346
|
-
```bash
|
|
347
|
-
# Understand a payment function
|
|
348
|
-
/capture-knowledge processPayment --depth 4
|
|
349
|
-
|
|
350
|
-
# Document an entire authentication module
|
|
351
|
-
/capture-knowledge src/auth/ --save
|
|
352
|
-
|
|
353
|
-
# Analyze an API endpoint
|
|
354
|
-
/capture-knowledge POST:/api/checkout
|
|
355
|
-
|
|
356
|
-
# Get just the diagrams for a complex function
|
|
357
|
-
/capture-knowledge handleOrderProcessing --diagram-only
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
The analysis is saved to `docs/ai/knowledge/` and can be versioned alongside your code.
|
|
361
|
-
|
|
362
212
|
## Use Cases
|
|
363
213
|
|
|
364
214
|
- **New Projects**: Scaffold complete development documentation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Config.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/lib/Config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("fs-extra"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const Config_1 = require("../../lib/Config");
|
|
39
|
+
jest.mock('fs-extra');
|
|
40
|
+
jest.mock('path');
|
|
41
|
+
jest.mock('../../../package.json', () => ({
|
|
42
|
+
version: '1.0.0'
|
|
43
|
+
}));
|
|
44
|
+
describe('ConfigManager', () => {
|
|
45
|
+
let configManager;
|
|
46
|
+
let mockFs;
|
|
47
|
+
let mockPath;
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
configManager = new Config_1.ConfigManager('/test/dir');
|
|
50
|
+
mockFs = fs;
|
|
51
|
+
mockPath = path;
|
|
52
|
+
mockPath.join.mockImplementation((...args) => args.join('/'));
|
|
53
|
+
});
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
jest.clearAllMocks();
|
|
56
|
+
});
|
|
57
|
+
describe('constructor', () => {
|
|
58
|
+
it('should set correct config path', () => {
|
|
59
|
+
expect(mockPath.join).toHaveBeenCalledWith('/test/dir', '.ai-devkit.json');
|
|
60
|
+
});
|
|
61
|
+
it('should use current directory as default', () => {
|
|
62
|
+
const defaultConfig = new Config_1.ConfigManager();
|
|
63
|
+
expect(mockPath.join).toHaveBeenCalledWith(process.cwd(), '.ai-devkit.json');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('exists', () => {
|
|
67
|
+
it('should return true when config file exists', async () => {
|
|
68
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
69
|
+
const result = await configManager.exists();
|
|
70
|
+
expect(result).toBe(true);
|
|
71
|
+
expect(mockFs.pathExists).toHaveBeenCalledWith('/test/dir/.ai-devkit.json');
|
|
72
|
+
});
|
|
73
|
+
it('should return false when config file does not exist', async () => {
|
|
74
|
+
mockFs.pathExists.mockResolvedValue(false);
|
|
75
|
+
const result = await configManager.exists();
|
|
76
|
+
expect(result).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('read', () => {
|
|
80
|
+
it('should return parsed config when file exists', async () => {
|
|
81
|
+
const mockConfig = {
|
|
82
|
+
version: '1.0.0',
|
|
83
|
+
environments: ['cursor'],
|
|
84
|
+
initializedPhases: ['requirements'],
|
|
85
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
86
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
87
|
+
};
|
|
88
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
89
|
+
mockFs.readJson.mockResolvedValue(mockConfig);
|
|
90
|
+
const result = await configManager.read();
|
|
91
|
+
expect(result).toEqual(mockConfig);
|
|
92
|
+
expect(mockFs.readJson).toHaveBeenCalledWith('/test/dir/.ai-devkit.json');
|
|
93
|
+
});
|
|
94
|
+
it('should return null when file does not exist', async () => {
|
|
95
|
+
mockFs.pathExists.mockResolvedValue(false);
|
|
96
|
+
const result = await configManager.read();
|
|
97
|
+
expect(result).toBeNull();
|
|
98
|
+
expect(mockFs.readJson).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('create', () => {
|
|
102
|
+
it('should create config with default values', async () => {
|
|
103
|
+
const expectedConfig = {
|
|
104
|
+
version: '1.0.0',
|
|
105
|
+
environments: [],
|
|
106
|
+
initializedPhases: [],
|
|
107
|
+
createdAt: expect.any(String),
|
|
108
|
+
updatedAt: expect.any(String)
|
|
109
|
+
};
|
|
110
|
+
mockFs.writeJson.mockResolvedValue(undefined);
|
|
111
|
+
const result = await configManager.create();
|
|
112
|
+
expect(result).toEqual(expectedConfig);
|
|
113
|
+
expect(mockFs.writeJson).toHaveBeenCalledWith('/test/dir/.ai-devkit.json', expectedConfig, { spaces: 2 });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('update', () => {
|
|
117
|
+
it('should update existing config and set updatedAt', async () => {
|
|
118
|
+
const existingConfig = {
|
|
119
|
+
version: '1.0.0',
|
|
120
|
+
environments: ['cursor'],
|
|
121
|
+
initializedPhases: [],
|
|
122
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
123
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
124
|
+
};
|
|
125
|
+
const updates = { environments: ['cursor', 'claude'] };
|
|
126
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
127
|
+
mockFs.readJson.mockResolvedValue(existingConfig);
|
|
128
|
+
mockFs.writeJson.mockResolvedValue(undefined);
|
|
129
|
+
const result = await configManager.update(updates);
|
|
130
|
+
expect(result.environments).toEqual(['cursor', 'claude']);
|
|
131
|
+
expect(result.updatedAt).not.toBe(existingConfig.updatedAt);
|
|
132
|
+
expect(result.createdAt).toBe(existingConfig.createdAt);
|
|
133
|
+
});
|
|
134
|
+
it('should throw error when config file not found', async () => {
|
|
135
|
+
mockFs.readJson.mockResolvedValue(null);
|
|
136
|
+
await expect(configManager.update({})).rejects.toThrow('Config file not found. Run ai-devkit init first.');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe('addPhase', () => {
|
|
140
|
+
it('should add new phase to initializedPhases', async () => {
|
|
141
|
+
const config = {
|
|
142
|
+
version: '1.0.0',
|
|
143
|
+
environments: [],
|
|
144
|
+
initializedPhases: ['requirements'],
|
|
145
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
146
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
147
|
+
};
|
|
148
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
149
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
150
|
+
mockFs.writeJson.mockResolvedValue(undefined);
|
|
151
|
+
const result = await configManager.addPhase('design');
|
|
152
|
+
expect(result.initializedPhases).toEqual(['requirements', 'design']);
|
|
153
|
+
});
|
|
154
|
+
it('should not add duplicate phase', async () => {
|
|
155
|
+
const config = {
|
|
156
|
+
version: '1.0.0',
|
|
157
|
+
environments: [],
|
|
158
|
+
initializedPhases: ['requirements'],
|
|
159
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
160
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
161
|
+
};
|
|
162
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
163
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
164
|
+
const result = await configManager.addPhase('requirements');
|
|
165
|
+
expect(result.initializedPhases).toEqual(['requirements']);
|
|
166
|
+
expect(mockFs.writeJson).not.toHaveBeenCalled();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
describe('hasPhase', () => {
|
|
170
|
+
it('should return true when phase exists', async () => {
|
|
171
|
+
const config = {
|
|
172
|
+
version: '1.0.0',
|
|
173
|
+
environments: [],
|
|
174
|
+
initializedPhases: ['requirements', 'design'],
|
|
175
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
176
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
177
|
+
};
|
|
178
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
179
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
180
|
+
const result = await configManager.hasPhase('design');
|
|
181
|
+
expect(result).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
it('should return false when phase does not exist', async () => {
|
|
184
|
+
const config = {
|
|
185
|
+
version: '1.0.0',
|
|
186
|
+
environments: [],
|
|
187
|
+
initializedPhases: ['requirements'],
|
|
188
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
189
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
190
|
+
};
|
|
191
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
192
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
193
|
+
const result = await configManager.hasPhase('design');
|
|
194
|
+
expect(result).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
it('should return false when config does not exist', async () => {
|
|
197
|
+
mockFs.pathExists.mockResolvedValue(false);
|
|
198
|
+
const result = await configManager.hasPhase('requirements');
|
|
199
|
+
expect(result).toBe(false);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe('getEnvironments', () => {
|
|
203
|
+
it('should return environments array when config exists', async () => {
|
|
204
|
+
const config = {
|
|
205
|
+
version: '1.0.0',
|
|
206
|
+
environments: ['cursor', 'claude'],
|
|
207
|
+
initializedPhases: [],
|
|
208
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
209
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
210
|
+
};
|
|
211
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
212
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
213
|
+
const result = await configManager.getEnvironments();
|
|
214
|
+
expect(result).toEqual(['cursor', 'claude']);
|
|
215
|
+
});
|
|
216
|
+
it('should return empty array when config does not exist', async () => {
|
|
217
|
+
mockFs.pathExists.mockResolvedValue(false);
|
|
218
|
+
const result = await configManager.getEnvironments();
|
|
219
|
+
expect(result).toEqual([]);
|
|
220
|
+
});
|
|
221
|
+
it('should return empty array when environments field is missing', async () => {
|
|
222
|
+
const config = {
|
|
223
|
+
version: '1.0.0',
|
|
224
|
+
environments: [],
|
|
225
|
+
initializedPhases: [],
|
|
226
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
227
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
228
|
+
};
|
|
229
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
230
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
231
|
+
const result = await configManager.getEnvironments();
|
|
232
|
+
expect(result).toEqual([]);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
describe('setEnvironments', () => {
|
|
236
|
+
it('should update environments and return config', async () => {
|
|
237
|
+
const config = {
|
|
238
|
+
version: '1.0.0',
|
|
239
|
+
environments: ['cursor'],
|
|
240
|
+
initializedPhases: [],
|
|
241
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
242
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
243
|
+
};
|
|
244
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
245
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
246
|
+
mockFs.writeJson.mockResolvedValue(undefined);
|
|
247
|
+
const result = await configManager.setEnvironments(['cursor', 'claude']);
|
|
248
|
+
expect(result.environments).toEqual(['cursor', 'claude']);
|
|
249
|
+
expect(mockFs.writeJson).toHaveBeenCalled();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
describe('hasEnvironment', () => {
|
|
253
|
+
it('should return true when environment exists', async () => {
|
|
254
|
+
const config = {
|
|
255
|
+
version: '1.0.0',
|
|
256
|
+
environments: ['cursor', 'claude'],
|
|
257
|
+
initializedPhases: [],
|
|
258
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
259
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
260
|
+
};
|
|
261
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
262
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
263
|
+
const result = await configManager.hasEnvironment('claude');
|
|
264
|
+
expect(result).toBe(true);
|
|
265
|
+
});
|
|
266
|
+
it('should return false when environment does not exist', async () => {
|
|
267
|
+
const config = {
|
|
268
|
+
version: '1.0.0',
|
|
269
|
+
environments: ['cursor'],
|
|
270
|
+
initializedPhases: [],
|
|
271
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
272
|
+
updatedAt: '2024-01-01T00:00:00.000Z'
|
|
273
|
+
};
|
|
274
|
+
mockFs.pathExists.mockResolvedValue(true);
|
|
275
|
+
mockFs.readJson.mockResolvedValue(config);
|
|
276
|
+
const result = await configManager.hasEnvironment('claude');
|
|
277
|
+
expect(result).toBe(false);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
//# sourceMappingURL=Config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Config.test.js","sourceRoot":"","sources":["../../../src/__tests__/lib/Config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentSelector.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/lib/EnvironmentSelector.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const EnvironmentSelector_1 = require("../../lib/EnvironmentSelector");
|
|
4
|
+
const env_1 = require("../../util/env");
|
|
5
|
+
jest.mock('inquirer');
|
|
6
|
+
describe('EnvironmentSelector', () => {
|
|
7
|
+
let selector;
|
|
8
|
+
let mockPrompt;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
selector = new EnvironmentSelector_1.EnvironmentSelector();
|
|
11
|
+
const inquirer = require('inquirer');
|
|
12
|
+
mockPrompt = jest.fn();
|
|
13
|
+
inquirer.prompt = mockPrompt;
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
jest.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
describe('selectEnvironments', () => {
|
|
19
|
+
it('should create choices from all environments', async () => {
|
|
20
|
+
const environments = (0, env_1.getAllEnvironments)();
|
|
21
|
+
mockPrompt.mockResolvedValue({ environments: ['cursor', 'claude'] });
|
|
22
|
+
await selector.selectEnvironments();
|
|
23
|
+
expect(mockPrompt).toHaveBeenCalledWith([
|
|
24
|
+
expect.objectContaining({
|
|
25
|
+
type: 'checkbox',
|
|
26
|
+
name: 'environments',
|
|
27
|
+
message: 'Select AI environments to set up (use space to select, enter to confirm):',
|
|
28
|
+
choices: environments.map(env => ({
|
|
29
|
+
name: env.name,
|
|
30
|
+
value: env.code,
|
|
31
|
+
short: env.name
|
|
32
|
+
})),
|
|
33
|
+
validate: expect.any(Function)
|
|
34
|
+
})
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
it('should return selected environments', async () => {
|
|
38
|
+
const selectedEnvs = ['cursor', 'claude'];
|
|
39
|
+
mockPrompt.mockResolvedValue({ environments: selectedEnvs });
|
|
40
|
+
const result = await selector.selectEnvironments();
|
|
41
|
+
expect(result).toEqual(selectedEnvs);
|
|
42
|
+
});
|
|
43
|
+
it('should validate that at least one environment is selected', async () => {
|
|
44
|
+
mockPrompt.mockResolvedValue({ environments: [] });
|
|
45
|
+
const result = await selector.selectEnvironments();
|
|
46
|
+
expect(result).toEqual([]);
|
|
47
|
+
const callArgs = mockPrompt.mock.calls[0][0];
|
|
48
|
+
const validateFn = callArgs[0].validate;
|
|
49
|
+
expect(validateFn([])).toBe('Please select at least one environment.');
|
|
50
|
+
expect(validateFn(['cursor'])).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
it('should handle prompt rejection', async () => {
|
|
53
|
+
mockPrompt.mockRejectedValue(new Error('User cancelled'));
|
|
54
|
+
await expect(selector.selectEnvironments()).rejects.toThrow('User cancelled');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('confirmOverride', () => {
|
|
58
|
+
it('should return true immediately for empty conflicts', async () => {
|
|
59
|
+
const result = await selector.confirmOverride([]);
|
|
60
|
+
expect(result).toBe(true);
|
|
61
|
+
expect(mockPrompt).not.toHaveBeenCalled();
|
|
62
|
+
});
|
|
63
|
+
it('should prompt user for confirmation with conflict details', async () => {
|
|
64
|
+
mockPrompt.mockResolvedValue({ proceed: true });
|
|
65
|
+
const result = await selector.confirmOverride(['cursor', 'claude']);
|
|
66
|
+
expect(result).toBe(true);
|
|
67
|
+
expect(mockPrompt).toHaveBeenCalledWith([
|
|
68
|
+
{
|
|
69
|
+
type: 'confirm',
|
|
70
|
+
name: 'proceed',
|
|
71
|
+
message: 'The following environments are already set up and will be overwritten:\n Cursor, Claude Code\n\nDo you want to continue?',
|
|
72
|
+
default: false
|
|
73
|
+
}
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
76
|
+
it('should return false when user declines', async () => {
|
|
77
|
+
mockPrompt.mockResolvedValue({ proceed: false });
|
|
78
|
+
const result = await selector.confirmOverride(['cursor']);
|
|
79
|
+
expect(result).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
it('should handle single environment conflict', async () => {
|
|
82
|
+
mockPrompt.mockResolvedValue({ proceed: true });
|
|
83
|
+
const result = await selector.confirmOverride(['cursor']);
|
|
84
|
+
expect(result).toBe(true);
|
|
85
|
+
const message = mockPrompt.mock.calls[0][0][0].message;
|
|
86
|
+
expect(message).toContain('Cursor');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('displaySelectionSummary', () => {
|
|
90
|
+
let consoleSpy;
|
|
91
|
+
beforeEach(() => {
|
|
92
|
+
consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
93
|
+
});
|
|
94
|
+
afterEach(() => {
|
|
95
|
+
consoleSpy.mockRestore();
|
|
96
|
+
});
|
|
97
|
+
it('should display nothing selected message for empty array', () => {
|
|
98
|
+
selector.displaySelectionSummary([]);
|
|
99
|
+
expect(consoleSpy).toHaveBeenCalledWith('No environments selected.');
|
|
100
|
+
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
|
101
|
+
});
|
|
102
|
+
it('should display selected environments with checkmarks', () => {
|
|
103
|
+
selector.displaySelectionSummary(['cursor', 'claude']);
|
|
104
|
+
expect(consoleSpy).toHaveBeenCalledWith('\nSelected environments:');
|
|
105
|
+
expect(consoleSpy).toHaveBeenCalledWith(' [OK] Cursor');
|
|
106
|
+
expect(consoleSpy).toHaveBeenCalledWith(' [OK] Claude Code');
|
|
107
|
+
expect(consoleSpy).toHaveBeenCalledWith('');
|
|
108
|
+
});
|
|
109
|
+
it('should handle single environment selection', () => {
|
|
110
|
+
selector.displaySelectionSummary(['cursor']);
|
|
111
|
+
expect(consoleSpy).toHaveBeenCalledWith('\nSelected environments:');
|
|
112
|
+
expect(consoleSpy).toHaveBeenCalledWith(' [OK] Cursor');
|
|
113
|
+
expect(consoleSpy).toHaveBeenCalledWith('');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=EnvironmentSelector.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentSelector.test.js","sourceRoot":"","sources":["../../../src/__tests__/lib/EnvironmentSelector.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhaseSelector.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/lib/PhaseSelector.test.ts"],"names":[],"mappings":""}
|