ai-devkit 0.2.0 → 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/CHANGELOG.md +11 -1
- package/README.md +20 -87
- 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/commands/init.d.ts +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +54 -73
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/phase.d.ts.map +1 -1
- package/dist/commands/phase.js +1 -5
- 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 -66
- 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 -11
- package/templates/commands/capture-knowledge.md +46 -0
- package/templates/commands/debug.md +45 -0
- package/templates/{env/cursor/commands → commands}/new-requirement.md +1 -1
- 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/claude/commands/code-review.md +0 -81
- package/templates/env/claude/commands/execute-plan.md +0 -71
- package/templates/env/claude/commands/new-requirement.md +0 -127
- package/templates/env/claude/commands/update-planning.md +0 -61
- package/templates/env/cursor/commands/check-implementation.md +0 -21
- package/templates/env/cursor/commands/review-design.md +0 -11
- package/templates/env/cursor/commands/review-requirements.md +0 -9
- package/templates/env/cursor/commands/writing-test.md +0 -44
- package/templates/env/cursor/rules/ai-devkit.md +0 -51
- /package/templates/{env/claude/commands → commands}/check-implementation.md +0 -0
- /package/templates/{env/cursor/commands → commands}/code-review.md +0 -0
- /package/templates/{env/cursor/commands → commands}/execute-plan.md +0 -0
- /package/templates/{env/claude/commands → commands}/review-design.md +0 -0
- /package/templates/{env/claude/commands → commands}/review-requirements.md +0 -0
- /package/templates/{env/cursor/commands → commands}/update-planning.md +0 -0
- /package/templates/{env/claude/commands → commands}/writing-test.md +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.3.0] - 2025-10-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `/debug` - Structured assistant for clarifying issues, analyzing options, and agreeing on a fix plan before coding
|
|
12
|
+
- `/capture-knowledge` - Analyze and explain how code works from any entry point
|
|
13
|
+
- Supports file, folder, function, and API endpoint analysis
|
|
14
|
+
- Recursive dependency analysis with configurable depth (max: 3)
|
|
15
|
+
- Automatic generation of mermaid diagrams (flowcharts, sequence, architecture, class diagrams)
|
|
16
|
+
- Knowledge capture documentation saved to `docs/ai/implementation/knowledge-{feature-name}.md`
|
|
17
|
+
- Visual dependency tree and component relationship mapping
|
|
18
|
+
- Includes error handling, performance considerations, and improvement suggestions
|
|
9
19
|
|
|
10
20
|
## [0.2.0] - 2025-10-14
|
|
11
21
|
|
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A CLI toolkit for AI-assisted software development with structured phase templates and environment setup for Cursor and Claude Code.
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/ai-devkit)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
5
8
|
## Features
|
|
6
9
|
|
|
7
10
|
- 🎯 **Phase-based Development**: Structured templates for each stage of the software development lifecycle
|
|
@@ -40,6 +43,8 @@ This will:
|
|
|
40
43
|
2. Set up your AI development environment (Cursor/Claude Code)
|
|
41
44
|
3. Generate phase templates in `docs/ai/`
|
|
42
45
|
|
|
46
|
+
Detailed user guide can be found [here](https://ai-devkit.com/docs/).
|
|
47
|
+
|
|
43
48
|
## Available Phases
|
|
44
49
|
|
|
45
50
|
- **Requirements**: Problem understanding, requirements gathering, and success criteria
|
|
@@ -113,50 +118,19 @@ your-project/
|
|
|
113
118
|
└── [Environment-specific files]
|
|
114
119
|
```
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
└── review-requirements.md
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### For Claude Code:
|
|
133
|
-
```
|
|
134
|
-
└── .claude/
|
|
135
|
-
├── CLAUDE.md # Workspace configuration
|
|
136
|
-
└── commands/ # Custom commands (Markdown files)
|
|
137
|
-
├── new-requirement.md
|
|
138
|
-
├── code-review.md
|
|
139
|
-
├── execute-plan.md
|
|
140
|
-
├── writing-test.md
|
|
141
|
-
├── update-planning.md
|
|
142
|
-
├── check-implementation.md
|
|
143
|
-
├── review-design.md
|
|
144
|
-
└── review-requirements.md
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Customizing Templates
|
|
148
|
-
|
|
149
|
-
All templates are plain Markdown files with YAML frontmatter. You can customize them to fit your project's needs:
|
|
150
|
-
|
|
151
|
-
```markdown
|
|
152
|
-
---
|
|
153
|
-
phase: requirements
|
|
154
|
-
title: Requirements & Problem Understanding
|
|
155
|
-
description: Clarify the problem space, gather requirements, and define success criteria
|
|
156
|
-
---
|
|
157
|
-
|
|
158
|
-
# Your custom content here
|
|
159
|
-
```
|
|
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/) | ✅ | |
|
|
160
134
|
|
|
161
135
|
Templates are designed to provide structure while remaining concise and AI-friendly.
|
|
162
136
|
|
|
@@ -195,6 +169,7 @@ Available commands:
|
|
|
195
169
|
- `check-implementation` - Compare implementation with design
|
|
196
170
|
- `review-design` - Review system design and architecture
|
|
197
171
|
- `review-requirements` - Review and summarize requirements
|
|
172
|
+
- `capture-knowledge` - Analyze and explain code with recursive dependency analysis and Mermaid diagrams
|
|
198
173
|
|
|
199
174
|
Commands can be referenced in Claude Code chats to guide AI assistance through your development phases.
|
|
200
175
|
|
|
@@ -234,48 +209,6 @@ Commands can be referenced in Claude Code chats to guide AI assistance through y
|
|
|
234
209
|
8. **Monitor and iterate:**
|
|
235
210
|
- Set up monitoring per `docs/ai/monitoring/README.md`
|
|
236
211
|
|
|
237
|
-
### Adding a New Feature
|
|
238
|
-
|
|
239
|
-
**Use the `/new-requirement` command for a guided workflow:**
|
|
240
|
-
|
|
241
|
-
1. **In Cursor or Claude Code**, type `/new-requirement`
|
|
242
|
-
2. The AI will guide you through:
|
|
243
|
-
- 📋 Capturing requirement details
|
|
244
|
-
- 🔍 Creating feature-specific documentation
|
|
245
|
-
- 📐 Designing the solution
|
|
246
|
-
- 📅 Planning tasks and breaking down work
|
|
247
|
-
- 💻 Implementation (task by task)
|
|
248
|
-
- ✅ Testing and verification
|
|
249
|
-
- 🔀 Git commits and PR/MR creation
|
|
250
|
-
|
|
251
|
-
**Review and refine your documentation:**
|
|
252
|
-
- After drafting requirements, run `/review-requirements` to validate completeness
|
|
253
|
-
- After drafting design, run `/review-design` to ensure architecture clarity and mermaid diagrams
|
|
254
|
-
|
|
255
|
-
**Execute your plan:**
|
|
256
|
-
- Run `/execute-plan` to step through tasks interactively:
|
|
257
|
-
- Reads `docs/ai/planning/feature-{name}.md`
|
|
258
|
-
- Presents tasks in order with context
|
|
259
|
-
- Captures status/notes for each task
|
|
260
|
-
- Prompts you to update documentation as you progress
|
|
261
|
-
|
|
262
|
-
**Before pushing your code:**
|
|
263
|
-
- Run `/code-review` to perform a structured local review:
|
|
264
|
-
- Checks alignment with design docs
|
|
265
|
-
- Spots logic/security/performance issues
|
|
266
|
-
- Highlights redundant code and missing tests
|
|
267
|
-
- Suggests documentation updates
|
|
268
|
-
|
|
269
|
-
**Generate comprehensive tests:**
|
|
270
|
-
- Run `/writing-test` to create unit and integration tests targeting 100% coverage
|
|
271
|
-
|
|
272
|
-
This workflow creates feature-specific files:
|
|
273
|
-
- `docs/ai/requirements/feature-{name}.md`
|
|
274
|
-
- `docs/ai/design/feature-{name}.md`
|
|
275
|
-
- `docs/ai/planning/feature-{name}.md`
|
|
276
|
-
- `docs/ai/implementation/feature-{name}.md`
|
|
277
|
-
- `docs/ai/testing/feature-{name}.md`
|
|
278
|
-
|
|
279
212
|
## Use Cases
|
|
280
213
|
|
|
281
214
|
- **New Projects**: Scaffold complete development documentation
|
|
@@ -354,7 +287,7 @@ MIT
|
|
|
354
287
|
| Guided feature workflow | `/new-requirement` (Cursor & Claude) |
|
|
355
288
|
| Execute feature plan | `/execute-plan` (Cursor & Claude) |
|
|
356
289
|
| Generate tests | `/writing-test` (Cursor & Claude) |
|
|
357
|
-
|
|
|
290
|
+
| Local code review | `/code-review` (Cursor & Claude) |
|
|
358
291
|
| Help | `npx ai-devkit --help` |
|
|
359
292
|
|
|
360
293
|
| Quick links | Description |
|
|
@@ -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":""}
|