@aicgen/aicgen 1.0.0-beta.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.
Files changed (287) hide show
  1. package/.claude/agents/architecture-reviewer.md +88 -0
  2. package/.claude/agents/guideline-checker.md +73 -0
  3. package/.claude/agents/security-auditor.md +108 -0
  4. package/.claude/guidelines/api-design.md +645 -0
  5. package/.claude/guidelines/architecture.md +2503 -0
  6. package/.claude/guidelines/best-practices.md +618 -0
  7. package/.claude/guidelines/code-style.md +304 -0
  8. package/.claude/guidelines/design-patterns.md +573 -0
  9. package/.claude/guidelines/devops.md +226 -0
  10. package/.claude/guidelines/error-handling.md +413 -0
  11. package/.claude/guidelines/language.md +782 -0
  12. package/.claude/guidelines/performance.md +706 -0
  13. package/.claude/guidelines/security.md +583 -0
  14. package/.claude/guidelines/testing.md +568 -0
  15. package/.claude/settings.json +98 -0
  16. package/.claude/settings.local.json +8 -0
  17. package/.env.example +23 -0
  18. package/.eslintrc.json +28 -0
  19. package/.github/workflows/release.yml +180 -0
  20. package/.github/workflows/test.yml +81 -0
  21. package/.gitmodules +3 -0
  22. package/.vs/ProjectSettings.json +3 -0
  23. package/.vs/VSWorkspaceState.json +16 -0
  24. package/.vs/aicgen.slnx/FileContentIndex/5f0ce2a3-fd68-4863-9e23-e428cf1794e3.vsidx +0 -0
  25. package/.vs/aicgen.slnx/v18/.wsuo +0 -0
  26. package/.vs/aicgen.slnx/v18/DocumentLayout.json +54 -0
  27. package/.vs/slnx.sqlite +0 -0
  28. package/AGENTS.md +121 -0
  29. package/CLAUDE.md +36 -0
  30. package/CONTRIBUTING.md +821 -0
  31. package/LICENSE +21 -0
  32. package/README.md +199 -0
  33. package/assets/icon.svg +34 -0
  34. package/assets/logo.svg +41 -0
  35. package/bun.lock +848 -0
  36. package/data/LICENSE +21 -0
  37. package/data/README.md +203 -0
  38. package/data/api/basics.md +292 -0
  39. package/data/api/index.md +8 -0
  40. package/data/api/pagination.md +142 -0
  41. package/data/api/rest.md +137 -0
  42. package/data/api/versioning.md +60 -0
  43. package/data/architecture/clean-architecture/index.md +7 -0
  44. package/data/architecture/clean-architecture/layers.md +111 -0
  45. package/data/architecture/ddd/index.md +8 -0
  46. package/data/architecture/ddd/strategic.md +89 -0
  47. package/data/architecture/ddd/tactical.md +132 -0
  48. package/data/architecture/event-driven/index.md +7 -0
  49. package/data/architecture/event-driven/messaging.md +242 -0
  50. package/data/architecture/event-driven/patterns.md +129 -0
  51. package/data/architecture/feature-toggles/index.md +7 -0
  52. package/data/architecture/feature-toggles/patterns.md +73 -0
  53. package/data/architecture/gui/index.md +7 -0
  54. package/data/architecture/gui/patterns.md +132 -0
  55. package/data/architecture/hexagonal/ports-adapters.md +132 -0
  56. package/data/architecture/index.md +12 -0
  57. package/data/architecture/layered/index.md +7 -0
  58. package/data/architecture/layered/layers.md +100 -0
  59. package/data/architecture/microservices/api-gateway.md +56 -0
  60. package/data/architecture/microservices/boundaries.md +80 -0
  61. package/data/architecture/microservices/communication.md +97 -0
  62. package/data/architecture/microservices/data.md +92 -0
  63. package/data/architecture/microservices/index.md +11 -0
  64. package/data/architecture/microservices/resilience.md +111 -0
  65. package/data/architecture/modular-monolith/boundaries.md +133 -0
  66. package/data/architecture/modular-monolith/structure.md +131 -0
  67. package/data/architecture/serverless/best-practices.md +322 -0
  68. package/data/architecture/serverless/index.md +7 -0
  69. package/data/architecture/serverless/patterns.md +80 -0
  70. package/data/architecture/solid/index.md +7 -0
  71. package/data/architecture/solid/principles.md +187 -0
  72. package/data/database/basics.md +365 -0
  73. package/data/database/design-patterns.md +68 -0
  74. package/data/database/index.md +8 -0
  75. package/data/database/indexing.md +136 -0
  76. package/data/database/nosql.md +223 -0
  77. package/data/database/schema.md +137 -0
  78. package/data/devops/ci-cd.md +66 -0
  79. package/data/devops/index.md +8 -0
  80. package/data/devops/observability.md +73 -0
  81. package/data/devops/practices.md +77 -0
  82. package/data/error-handling/basics.md +222 -0
  83. package/data/error-handling/index.md +7 -0
  84. package/data/error-handling/strategy.md +185 -0
  85. package/data/guideline-mappings.yml +1077 -0
  86. package/data/index.md +3 -0
  87. package/data/language/csharp/basics.md +210 -0
  88. package/data/language/csharp/testing.md +252 -0
  89. package/data/language/go/basics.md +158 -0
  90. package/data/language/go/testing.md +192 -0
  91. package/data/language/index.md +14 -0
  92. package/data/language/java/basics.md +184 -0
  93. package/data/language/java/testing.md +273 -0
  94. package/data/language/javascript/basics.md +217 -0
  95. package/data/language/javascript/testing.md +269 -0
  96. package/data/language/python/async.md +100 -0
  97. package/data/language/python/basics.md +100 -0
  98. package/data/language/python/index.md +10 -0
  99. package/data/language/python/testing.md +125 -0
  100. package/data/language/python/types.md +99 -0
  101. package/data/language/ruby/basics.md +227 -0
  102. package/data/language/ruby/testing.md +267 -0
  103. package/data/language/rust/basics.md +175 -0
  104. package/data/language/rust/testing.md +219 -0
  105. package/data/language/typescript/async.md +103 -0
  106. package/data/language/typescript/basics.md +87 -0
  107. package/data/language/typescript/config.md +95 -0
  108. package/data/language/typescript/error-handling.md +98 -0
  109. package/data/language/typescript/generics.md +85 -0
  110. package/data/language/typescript/index.md +14 -0
  111. package/data/language/typescript/interfaces-types.md +83 -0
  112. package/data/language/typescript/performance.md +103 -0
  113. package/data/language/typescript/testing.md +98 -0
  114. package/data/patterns/base-patterns.md +105 -0
  115. package/data/patterns/concurrency.md +87 -0
  116. package/data/patterns/data-access.md +83 -0
  117. package/data/patterns/distribution.md +86 -0
  118. package/data/patterns/domain-logic.md +81 -0
  119. package/data/patterns/gof.md +109 -0
  120. package/data/patterns/index.md +12 -0
  121. package/data/performance/async.md +148 -0
  122. package/data/performance/basics.md +324 -0
  123. package/data/performance/caching-strategies.md +68 -0
  124. package/data/performance/caching.md +152 -0
  125. package/data/performance/index.md +8 -0
  126. package/data/practices/code-review.md +52 -0
  127. package/data/practices/documentation.md +260 -0
  128. package/data/practices/index.md +11 -0
  129. package/data/practices/planning.md +142 -0
  130. package/data/practices/refactoring.md +91 -0
  131. package/data/practices/version-control.md +55 -0
  132. package/data/security/auth-jwt.md +159 -0
  133. package/data/security/headers.md +143 -0
  134. package/data/security/index.md +10 -0
  135. package/data/security/injection.md +119 -0
  136. package/data/security/secrets.md +148 -0
  137. package/data/style/index.md +8 -0
  138. package/data/style/naming.md +136 -0
  139. package/data/style/organization.md +162 -0
  140. package/data/templates/agents/architecture-reviewer.md +88 -0
  141. package/data/templates/agents/guideline-checker.md +73 -0
  142. package/data/templates/agents/security-auditor.md +108 -0
  143. package/data/templates/antigravity/rules/architecture.md.hbs +5 -0
  144. package/data/templates/antigravity/rules/code-style.md.hbs +5 -0
  145. package/data/templates/antigravity/rules/language.md.hbs +5 -0
  146. package/data/templates/antigravity/rules/performance.md.hbs +5 -0
  147. package/data/templates/antigravity/rules/security.md.hbs +5 -0
  148. package/data/templates/antigravity/rules/testing.md.hbs +5 -0
  149. package/data/templates/antigravity/workflows/add-documentation.md.hbs +23 -0
  150. package/data/templates/antigravity/workflows/generate-integration-tests.md.hbs +17 -0
  151. package/data/templates/antigravity/workflows/generate-unit-tests.md.hbs +20 -0
  152. package/data/templates/antigravity/workflows/performance-audit.md.hbs +24 -0
  153. package/data/templates/antigravity/workflows/refactor-extract-module.md.hbs +17 -0
  154. package/data/templates/antigravity/workflows/security-audit.md.hbs +20 -0
  155. package/data/templates/hooks/formatting.json +26 -0
  156. package/data/templates/hooks/security.json +35 -0
  157. package/data/templates/hooks/testing.json +17 -0
  158. package/data/testing/basics.md +151 -0
  159. package/data/testing/index.md +9 -0
  160. package/data/testing/integration.md +159 -0
  161. package/data/testing/unit-fundamentals.md +128 -0
  162. package/data/testing/unit-mocking.md +116 -0
  163. package/data/version.json +49 -0
  164. package/dist/commands/init.d.ts +8 -0
  165. package/dist/commands/init.d.ts.map +1 -0
  166. package/dist/commands/init.js +46 -0
  167. package/dist/commands/init.js.map +1 -0
  168. package/dist/config/profiles.d.ts +4 -0
  169. package/dist/config/profiles.d.ts.map +1 -0
  170. package/dist/config/profiles.js +30 -0
  171. package/dist/config/profiles.js.map +1 -0
  172. package/dist/config/settings.d.ts +7 -0
  173. package/dist/config/settings.d.ts.map +1 -0
  174. package/dist/config/settings.js +7 -0
  175. package/dist/config/settings.js.map +1 -0
  176. package/dist/index.d.ts +3 -0
  177. package/dist/index.d.ts.map +1 -0
  178. package/dist/index.js +58489 -0
  179. package/dist/index.js.map +1 -0
  180. package/dist/models/guideline.d.ts +15 -0
  181. package/dist/models/guideline.d.ts.map +1 -0
  182. package/dist/models/guideline.js +2 -0
  183. package/dist/models/guideline.js.map +1 -0
  184. package/dist/models/preference.d.ts +9 -0
  185. package/dist/models/preference.d.ts.map +1 -0
  186. package/dist/models/preference.js +2 -0
  187. package/dist/models/preference.js.map +1 -0
  188. package/dist/models/profile.d.ts +9 -0
  189. package/dist/models/profile.d.ts.map +1 -0
  190. package/dist/models/profile.js +2 -0
  191. package/dist/models/profile.js.map +1 -0
  192. package/dist/models/project.d.ts +13 -0
  193. package/dist/models/project.d.ts.map +1 -0
  194. package/dist/models/project.js +2 -0
  195. package/dist/models/project.js.map +1 -0
  196. package/dist/services/ai/anthropic.d.ts +7 -0
  197. package/dist/services/ai/anthropic.d.ts.map +1 -0
  198. package/dist/services/ai/anthropic.js +39 -0
  199. package/dist/services/ai/anthropic.js.map +1 -0
  200. package/dist/services/generator.d.ts +2 -0
  201. package/dist/services/generator.d.ts.map +1 -0
  202. package/dist/services/generator.js +4 -0
  203. package/dist/services/generator.js.map +1 -0
  204. package/dist/services/learner.d.ts +2 -0
  205. package/dist/services/learner.d.ts.map +1 -0
  206. package/dist/services/learner.js +4 -0
  207. package/dist/services/learner.js.map +1 -0
  208. package/dist/services/scanner.d.ts +3 -0
  209. package/dist/services/scanner.d.ts.map +1 -0
  210. package/dist/services/scanner.js +54 -0
  211. package/dist/services/scanner.js.map +1 -0
  212. package/dist/utils/errors.d.ts +15 -0
  213. package/dist/utils/errors.d.ts.map +1 -0
  214. package/dist/utils/errors.js +27 -0
  215. package/dist/utils/errors.js.map +1 -0
  216. package/dist/utils/file.d.ts +7 -0
  217. package/dist/utils/file.d.ts.map +1 -0
  218. package/dist/utils/file.js +32 -0
  219. package/dist/utils/file.js.map +1 -0
  220. package/dist/utils/logger.d.ts +6 -0
  221. package/dist/utils/logger.d.ts.map +1 -0
  222. package/dist/utils/logger.js +17 -0
  223. package/dist/utils/logger.js.map +1 -0
  224. package/dist/utils/path.d.ts +6 -0
  225. package/dist/utils/path.d.ts.map +1 -0
  226. package/dist/utils/path.js +14 -0
  227. package/dist/utils/path.js.map +1 -0
  228. package/docs/planning/memory-lane.md +83 -0
  229. package/package.json +64 -0
  230. package/packaging/linux/aicgen.spec +23 -0
  231. package/packaging/linux/control +9 -0
  232. package/packaging/macos/scripts/postinstall +12 -0
  233. package/packaging/windows/setup.nsi +92 -0
  234. package/planning/BRANDING-SUMMARY.md +194 -0
  235. package/planning/BRANDING.md +174 -0
  236. package/planning/BUILD.md +186 -0
  237. package/planning/CHUNK-IMPLEMENTATION-PLAN.md +87 -0
  238. package/planning/CHUNK-TAXONOMY.md +375 -0
  239. package/planning/CHUNKS-COMPLETE.md +382 -0
  240. package/planning/DESIGN.md +313 -0
  241. package/planning/DYNAMIC-GUIDELINES-DESIGN.md +265 -0
  242. package/planning/ENTERPRISE-UX-COMPLETE.md +281 -0
  243. package/planning/IMPLEMENTATION-PLAN.md +20 -0
  244. package/planning/PHASE1-COMPLETE.md +211 -0
  245. package/planning/PHASE2-COMPLETE.md +350 -0
  246. package/planning/PHASE3-COMPLETE.md +399 -0
  247. package/planning/PHASE4-COMPLETE.md +361 -0
  248. package/planning/PHASE4.5-CHUNKS.md +462 -0
  249. package/planning/STRUCTURE.md +170 -0
  250. package/scripts/add-categories.ts +87 -0
  251. package/scripts/build-binary.ts +46 -0
  252. package/scripts/embed-data.ts +105 -0
  253. package/scripts/generate-version.ts +150 -0
  254. package/scripts/test-decompress.ts +27 -0
  255. package/scripts/test-extract.ts +31 -0
  256. package/src/__tests__/services/assistant-file-writer.test.ts +400 -0
  257. package/src/__tests__/services/guideline-loader.test.ts +281 -0
  258. package/src/__tests__/services/tarball-extraction.test.ts +125 -0
  259. package/src/commands/add-guideline.ts +296 -0
  260. package/src/commands/clear.ts +61 -0
  261. package/src/commands/guideline-selector.ts +123 -0
  262. package/src/commands/init.ts +645 -0
  263. package/src/commands/quick-add.ts +586 -0
  264. package/src/commands/remove-guideline.ts +152 -0
  265. package/src/commands/stats.ts +49 -0
  266. package/src/commands/update.ts +240 -0
  267. package/src/config.ts +82 -0
  268. package/src/embedded-data.ts +1492 -0
  269. package/src/index.ts +67 -0
  270. package/src/models/profile.ts +24 -0
  271. package/src/models/project.ts +43 -0
  272. package/src/services/assistant-file-writer.ts +612 -0
  273. package/src/services/config-generator.ts +150 -0
  274. package/src/services/config-manager.ts +70 -0
  275. package/src/services/data-source.ts +248 -0
  276. package/src/services/first-run-init.ts +148 -0
  277. package/src/services/guideline-loader.ts +311 -0
  278. package/src/services/hook-generator.ts +178 -0
  279. package/src/services/subagent-generator.ts +310 -0
  280. package/src/utils/banner.ts +66 -0
  281. package/src/utils/errors.ts +27 -0
  282. package/src/utils/file.ts +67 -0
  283. package/src/utils/formatting.ts +172 -0
  284. package/src/utils/logger.ts +89 -0
  285. package/src/utils/path.ts +17 -0
  286. package/src/utils/wizard-state.ts +132 -0
  287. package/tsconfig.json +25 -0
@@ -0,0 +1,151 @@
1
+ # Testing Basics
2
+
3
+ ## Your First Unit Test
4
+
5
+ A unit test verifies that a small piece of code works correctly.
6
+
7
+ ```pseudocode
8
+ // Function to test
9
+ function add(a, b):
10
+ return a + b
11
+
12
+ // Test for the function
13
+ test "add should sum two numbers":
14
+ result = add(2, 3)
15
+ expect result equals 5
16
+ ```
17
+
18
+ ## Test Structure
19
+
20
+ Every test has three parts:
21
+
22
+ 1. **Setup** - Prepare what you need
23
+ 2. **Execute** - Run the code
24
+ 3. **Verify** - Check the result
25
+
26
+ ```pseudocode
27
+ test "should create user with name":
28
+ // 1. Setup
29
+ userName = "Alice"
30
+
31
+ // 2. Execute
32
+ user = createUser(userName)
33
+
34
+ // 3. Verify
35
+ expect user.name equals "Alice"
36
+ ```
37
+
38
+ ## Common Assertions
39
+
40
+ ```pseudocode
41
+ // Equality
42
+ expect value equals 5
43
+ expect value equals { id: 1 }
44
+
45
+ // Truthiness
46
+ expect value is truthy
47
+ expect value is falsy
48
+ expect value is null
49
+ expect value is undefined
50
+
51
+ // Numbers
52
+ expect value > 3
53
+ expect value < 10
54
+
55
+ // Strings
56
+ expect text contains "hello"
57
+
58
+ // Arrays/Lists
59
+ expect array contains item
60
+ expect array length equals 3
61
+ ```
62
+
63
+ ## Testing Expected Errors
64
+
65
+ ```pseudocode
66
+ test "should throw error for invalid input":
67
+ expect error when:
68
+ divide(10, 0)
69
+ with message "Cannot divide by zero"
70
+ ```
71
+
72
+ ## Async Tests
73
+
74
+ ```pseudocode
75
+ test "should fetch user data" async:
76
+ user = await fetchUser(123)
77
+ expect user.id equals 123
78
+ ```
79
+
80
+ ## Test Naming
81
+
82
+ Use clear, descriptive names:
83
+
84
+ ```pseudocode
85
+ // ❌ Bad
86
+ test "test1"
87
+ test "it works"
88
+
89
+ // ✅ Good
90
+ test "should return user when ID exists"
91
+ test "should throw error when ID is invalid"
92
+ ```
93
+
94
+ ## Running Tests
95
+
96
+ ```bash
97
+ # Run all tests
98
+ run-tests
99
+
100
+ # Run specific test file
101
+ run-tests user-test
102
+
103
+ # Watch mode (re-run on changes)
104
+ run-tests --watch
105
+ ```
106
+
107
+ ## Best Practices
108
+
109
+ 1. **One test, one thing** - Test one behavior per test
110
+ 2. **Independent tests** - Tests should not depend on each other
111
+ 3. **Clear names** - Name should describe what is being tested
112
+ 4. **Fast tests** - Tests should run quickly
113
+
114
+ ```pseudocode
115
+ // ❌ Bad: Testing multiple things
116
+ test "user operations":
117
+ expect createUser("Bob").name equals "Bob"
118
+ expect deleteUser(1) equals true
119
+ expect listUsers().length equals 0
120
+
121
+ // ✅ Good: One test per operation
122
+ test "should create user with given name":
123
+ user = createUser("Bob")
124
+ expect user.name equals "Bob"
125
+
126
+ test "should delete user by ID":
127
+ result = deleteUser(1)
128
+ expect result equals true
129
+
130
+ test "should return empty list when no users":
131
+ users = listUsers()
132
+ expect users.length equals 0
133
+ ```
134
+
135
+ ## When to Write Tests
136
+
137
+ - **Before fixing bugs** - Write test that fails, then fix
138
+ - **For new features** - Test expected behavior
139
+ - **For edge cases** - Empty input, null values, large numbers
140
+
141
+ ## What to Test
142
+
143
+ ✅ **Do test:**
144
+ - Public functions and methods
145
+ - Edge cases (empty, null, zero, negative)
146
+ - Error conditions
147
+
148
+ ❌ **Don't test:**
149
+ - Private implementation details
150
+ - Third-party libraries (they're already tested)
151
+ - Getters/setters with no logic
@@ -0,0 +1,9 @@
1
+ # Testing Guidelines
2
+
3
+ This directory contains testing best practices and patterns.
4
+
5
+ ## Available Chunks
6
+
7
+ - **unit-fundamentals.md** - AAA pattern, behavior testing, descriptive names
8
+ - **unit-mocking.md** - Test doubles, when to mock, mock verification
9
+ - **integration.md** - API testing, database testing, test isolation
@@ -0,0 +1,159 @@
1
+ # Integration Testing
2
+
3
+ ## Testing Real Dependencies
4
+
5
+ ```typescript
6
+ describe('UserRepository Integration', () => {
7
+ let db: Database;
8
+ let repository: UserRepository;
9
+
10
+ beforeAll(async () => {
11
+ db = await createTestDatabase();
12
+ repository = new UserRepository(db);
13
+ });
14
+
15
+ afterAll(async () => {
16
+ await db.close();
17
+ });
18
+
19
+ beforeEach(async () => {
20
+ await db.clear('users'); // Clean slate for each test
21
+ });
22
+
23
+ it('should persist and retrieve user', async () => {
24
+ const userData = { email: 'test@example.com', name: 'Test User' };
25
+
26
+ const created = await repository.create(userData);
27
+ const found = await repository.findById(created.id);
28
+
29
+ expect(found).toEqual(expect.objectContaining(userData));
30
+ });
31
+ });
32
+ ```
33
+
34
+ ## API Integration Tests
35
+
36
+ ```typescript
37
+ describe('POST /api/users', () => {
38
+ let app: Express;
39
+ let db: Database;
40
+
41
+ beforeAll(async () => {
42
+ db = await createTestDatabase();
43
+ app = createApp(db);
44
+ });
45
+
46
+ afterEach(async () => {
47
+ await db.clear('users');
48
+ });
49
+
50
+ it('should create user and return 201', async () => {
51
+ const response = await request(app)
52
+ .post('/api/users')
53
+ .send({ email: 'new@example.com', name: 'New User' })
54
+ .expect(201);
55
+
56
+ expect(response.body.data).toEqual(
57
+ expect.objectContaining({
58
+ email: 'new@example.com',
59
+ name: 'New User'
60
+ })
61
+ );
62
+
63
+ // Verify in database
64
+ const user = await db.findOne('users', { email: 'new@example.com' });
65
+ expect(user).toBeTruthy();
66
+ });
67
+
68
+ it('should return 400 for invalid email', async () => {
69
+ const response = await request(app)
70
+ .post('/api/users')
71
+ .send({ email: 'invalid', name: 'Test' })
72
+ .expect(400);
73
+
74
+ expect(response.body.error.code).toBe('VALIDATION_ERROR');
75
+ });
76
+ });
77
+ ```
78
+
79
+ ## Database Transaction Testing
80
+
81
+ ```typescript
82
+ describe('OrderService Integration', () => {
83
+ it('should rollback on payment failure', async () => {
84
+ const order = await orderService.createOrder({ items: [...] });
85
+
86
+ // Mock payment to fail
87
+ paymentGateway.charge.mockRejectedValue(new Error('Declined'));
88
+
89
+ await expect(
90
+ orderService.processOrder(order.id)
91
+ ).rejects.toThrow('Payment failed');
92
+
93
+ // Verify order status unchanged
94
+ const updatedOrder = await orderRepository.findById(order.id);
95
+ expect(updatedOrder.status).toBe('pending');
96
+
97
+ // Verify inventory not deducted
98
+ const inventory = await inventoryRepository.findByProductId(productId);
99
+ expect(inventory.quantity).toBe(originalQuantity);
100
+ });
101
+ });
102
+ ```
103
+
104
+ ## Test Data Builders
105
+
106
+ ```typescript
107
+ class UserBuilder {
108
+ private data: Partial<User> = {
109
+ email: 'default@example.com',
110
+ name: 'Default User',
111
+ role: 'user'
112
+ };
113
+
114
+ withEmail(email: string) { this.data.email = email; return this; }
115
+ withRole(role: string) { this.data.role = role; return this; }
116
+ asAdmin() { this.data.role = 'admin'; return this; }
117
+
118
+ build(): User { return this.data as User; }
119
+
120
+ async save(db: Database): Promise<User> {
121
+ return db.insert('users', this.data);
122
+ }
123
+ }
124
+
125
+ // Usage
126
+ const admin = await new UserBuilder()
127
+ .withEmail('admin@example.com')
128
+ .asAdmin()
129
+ .save(db);
130
+ ```
131
+
132
+ ## Test Isolation
133
+
134
+ ```typescript
135
+ // Use transactions that rollback
136
+ describe('IntegrationTests', () => {
137
+ beforeEach(async () => {
138
+ await db.beginTransaction();
139
+ });
140
+
141
+ afterEach(async () => {
142
+ await db.rollbackTransaction();
143
+ });
144
+ });
145
+
146
+ // Or use test containers
147
+ import { PostgreSqlContainer } from '@testcontainers/postgresql';
148
+
149
+ let container: PostgreSqlContainer;
150
+
151
+ beforeAll(async () => {
152
+ container = await new PostgreSqlContainer().start();
153
+ db = await connect(container.getConnectionUri());
154
+ });
155
+
156
+ afterAll(async () => {
157
+ await container.stop();
158
+ });
159
+ ```
@@ -0,0 +1,128 @@
1
+ # Unit Testing Fundamentals
2
+
3
+ ## Arrange-Act-Assert Pattern
4
+
5
+ ```typescript
6
+ describe('UserService', () => {
7
+ it('should create user with hashed password', async () => {
8
+ // Arrange - Set up test data and dependencies
9
+ const userData = { email: 'test@example.com', password: 'secret123' };
10
+ const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };
11
+ const service = new UserService(mockRepo);
12
+
13
+ // Act - Execute the behavior being tested
14
+ const result = await service.createUser(userData);
15
+
16
+ // Assert - Verify the outcomes
17
+ expect(result.id).toBe('1');
18
+ expect(mockRepo.save).toHaveBeenCalledWith(
19
+ expect.objectContaining({ email: 'test@example.com' })
20
+ );
21
+ });
22
+ });
23
+ ```
24
+
25
+ ## Test Observable Behavior, Not Implementation
26
+
27
+ ```typescript
28
+ // ❌ Bad: Testing implementation details
29
+ it('should call validateEmail method', () => {
30
+ const spy = jest.spyOn(service, 'validateEmail');
31
+ service.createUser({ email: 'test@example.com' });
32
+ expect(spy).toHaveBeenCalled();
33
+ });
34
+
35
+ // ✅ Good: Testing observable behavior
36
+ it('should reject invalid email', async () => {
37
+ await expect(
38
+ service.createUser({ email: 'invalid-email' })
39
+ ).rejects.toThrow('Invalid email format');
40
+ });
41
+
42
+ it('should accept valid email', async () => {
43
+ const result = await service.createUser({ email: 'valid@example.com' });
44
+ expect(result.email).toBe('valid@example.com');
45
+ });
46
+ ```
47
+
48
+ ## One Assertion Per Test Concept
49
+
50
+ ```typescript
51
+ // ❌ Bad: Multiple unrelated assertions
52
+ it('should validate user input', () => {
53
+ expect(() => validate({ age: -1 })).toThrow();
54
+ expect(() => validate({ age: 200 })).toThrow();
55
+ expect(() => validate({ name: '' })).toThrow();
56
+ });
57
+
58
+ // ✅ Good: One test per scenario
59
+ it('should reject negative age', () => {
60
+ expect(() => validate({ age: -1 })).toThrow('Age must be positive');
61
+ });
62
+
63
+ it('should reject age over 150', () => {
64
+ expect(() => validate({ age: 200 })).toThrow('Age must be under 150');
65
+ });
66
+
67
+ it('should reject empty name', () => {
68
+ expect(() => validate({ name: '' })).toThrow('Name is required');
69
+ });
70
+ ```
71
+
72
+ ## Descriptive Test Names
73
+
74
+ ```typescript
75
+ // ❌ Vague names
76
+ it('should work correctly', () => {});
77
+ it('handles edge case', () => {});
78
+
79
+ // ✅ Descriptive names - describe the scenario and expected outcome
80
+ it('should return empty array when no users match filter', () => {});
81
+ it('should throw ValidationError when email is empty', () => {});
82
+ it('should retry failed payment up to 3 times before giving up', () => {});
83
+ ```
84
+
85
+ ## Tests Should Be Independent
86
+
87
+ ```typescript
88
+ // ❌ Bad: Tests depend on each other
89
+ let userId: string;
90
+
91
+ it('should create user', async () => {
92
+ const user = await service.createUser(data);
93
+ userId = user.id; // Shared state!
94
+ });
95
+
96
+ it('should update user', async () => {
97
+ await service.updateUser(userId, newData); // Depends on previous test
98
+ });
99
+
100
+ // ✅ Good: Each test is self-contained
101
+ it('should update user', async () => {
102
+ const user = await service.createUser(data);
103
+ const updated = await service.updateUser(user.id, newData);
104
+ expect(updated.name).toBe(newData.name);
105
+ });
106
+ ```
107
+
108
+ ## Test Edge Cases
109
+
110
+ ```typescript
111
+ describe('divide', () => {
112
+ it('should divide two positive numbers', () => {
113
+ expect(divide(10, 2)).toBe(5);
114
+ });
115
+
116
+ it('should throw when dividing by zero', () => {
117
+ expect(() => divide(10, 0)).toThrow('Division by zero');
118
+ });
119
+
120
+ it('should handle negative numbers', () => {
121
+ expect(divide(-10, 2)).toBe(-5);
122
+ });
123
+
124
+ it('should return zero when numerator is zero', () => {
125
+ expect(divide(0, 5)).toBe(0);
126
+ });
127
+ });
128
+ ```
@@ -0,0 +1,116 @@
1
+ # Test Doubles and Mocking
2
+
3
+ ## Types of Test Doubles
4
+
5
+ ```typescript
6
+ // STUB: Returns canned responses
7
+ const stubUserRepo = {
8
+ findById: () => ({ id: '1', name: 'Test User' })
9
+ };
10
+
11
+ // MOCK: Pre-programmed with expectations
12
+ const mockPaymentGateway = {
13
+ charge: jest.fn()
14
+ .mockResolvedValueOnce({ success: true, transactionId: 'tx1' })
15
+ .mockResolvedValueOnce({ success: false, error: 'Declined' })
16
+ };
17
+
18
+ // SPY: Records calls for verification
19
+ const spy = jest.spyOn(emailService, 'send');
20
+
21
+ // FAKE: Working implementation (not for production)
22
+ class FakeDatabase implements Database {
23
+ private data = new Map<string, any>();
24
+
25
+ async save(id: string, entity: any) { this.data.set(id, entity); }
26
+ async find(id: string) { return this.data.get(id); }
27
+ }
28
+ ```
29
+
30
+ ## When to Mock
31
+
32
+ ```typescript
33
+ // ✅ Mock external services (APIs, databases)
34
+ const mockHttpClient = {
35
+ get: jest.fn().mockResolvedValue({ data: userData })
36
+ };
37
+
38
+ // ✅ Mock time-dependent operations
39
+ jest.useFakeTimers();
40
+ jest.setSystemTime(new Date('2024-01-15'));
41
+
42
+ // ✅ Mock random/non-deterministic functions
43
+ jest.spyOn(Math, 'random').mockReturnValue(0.5);
44
+
45
+ // ❌ Don't mock the code you're testing
46
+ // ❌ Don't mock simple data structures
47
+ ```
48
+
49
+ ## Mock Verification
50
+
51
+ ```typescript
52
+ it('should send welcome email after registration', async () => {
53
+ const mockEmail = { send: jest.fn().mockResolvedValue(true) };
54
+ const service = new UserService({ emailService: mockEmail });
55
+
56
+ await service.register({ email: 'new@example.com' });
57
+
58
+ expect(mockEmail.send).toHaveBeenCalledWith({
59
+ to: 'new@example.com',
60
+ template: 'welcome',
61
+ subject: 'Welcome!'
62
+ });
63
+ expect(mockEmail.send).toHaveBeenCalledTimes(1);
64
+ });
65
+ ```
66
+
67
+ ## Partial Mocks
68
+
69
+ ```typescript
70
+ // Mock only specific methods
71
+ const service = new OrderService();
72
+
73
+ jest.spyOn(service, 'validateOrder').mockReturnValue(true);
74
+ jest.spyOn(service, 'calculateTotal').mockReturnValue(100);
75
+ // Other methods use real implementation
76
+
77
+ const result = await service.processOrder(orderData);
78
+ expect(result.total).toBe(100);
79
+ ```
80
+
81
+ ## Resetting Mocks
82
+
83
+ ```typescript
84
+ describe('PaymentService', () => {
85
+ const mockGateway = { charge: jest.fn() };
86
+ const service = new PaymentService(mockGateway);
87
+
88
+ beforeEach(() => {
89
+ jest.clearAllMocks(); // Clear call history
90
+ // or jest.resetAllMocks() to also reset return values
91
+ });
92
+
93
+ it('should process payment', async () => {
94
+ mockGateway.charge.mockResolvedValue({ success: true });
95
+ await service.charge(100);
96
+ expect(mockGateway.charge).toHaveBeenCalledTimes(1);
97
+ });
98
+ });
99
+ ```
100
+
101
+ ## Mock Modules
102
+
103
+ ```typescript
104
+ // Mock entire module
105
+ jest.mock('./email-service', () => ({
106
+ EmailService: jest.fn().mockImplementation(() => ({
107
+ send: jest.fn().mockResolvedValue(true)
108
+ }))
109
+ }));
110
+
111
+ // Mock with partial implementation
112
+ jest.mock('./config', () => ({
113
+ ...jest.requireActual('./config'),
114
+ API_KEY: 'test-key'
115
+ }));
116
+ ```
@@ -0,0 +1,49 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "lastUpdated": "2025-12-16",
4
+ "totalGuidelines": 82,
5
+ "categories": {
6
+ "Language": 24,
7
+ "Architecture": 19,
8
+ "Testing": 4,
9
+ "Security": 4,
10
+ "Performance": 4,
11
+ "Database": 5,
12
+ "API Design": 4,
13
+ "Code Style": 2,
14
+ "Error Handling": 2,
15
+ "DevOps": 3,
16
+ "Best Practices": 5,
17
+ "Design Patterns": 6
18
+ },
19
+ "languages": {
20
+ "typescript": 8,
21
+ "python": 4,
22
+ "go": 2,
23
+ "rust": 2,
24
+ "java": 2,
25
+ "csharp": 2,
26
+ "ruby": 2,
27
+ "javascript": 2
28
+ },
29
+ "architectures": {
30
+ "microservices": 5,
31
+ "modular-monolith": 2,
32
+ "clean-architecture": 1,
33
+ "ddd": 2,
34
+ "event-driven": 2,
35
+ "layered": 1,
36
+ "serverless": 2,
37
+ "hexagonal": 1
38
+ },
39
+ "levels": {
40
+ "basic": 17,
41
+ "standard": 68,
42
+ "expert": 82,
43
+ "full": 82
44
+ },
45
+ "datasources": {
46
+ "sql": 3,
47
+ "nosql": 1
48
+ }
49
+ }
@@ -0,0 +1,8 @@
1
+ interface InitOptions {
2
+ profile?: string;
3
+ force?: boolean;
4
+ ai?: boolean;
5
+ }
6
+ export declare function initCommand(options: InitOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBAiDrD"}
@@ -0,0 +1,46 @@
1
+ import { select } from '@inquirer/prompts';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { scanProject } from '../services/scanner.js';
5
+ import { getProfile } from '../config/profiles.js';
6
+ import { isAnthropicAvailable } from '../services/ai/anthropic.js';
7
+ export async function initCommand(options) {
8
+ console.log(chalk.blue.bold('\n🤖 aicgen - AI Config Generator\n'));
9
+ const projectPath = process.cwd();
10
+ const spinner = ora('Scanning project...').start();
11
+ const projectInfo = await scanProject(projectPath);
12
+ spinner.succeed(`Project detected: ${chalk.green(projectInfo.type)}`);
13
+ if (projectInfo.hasExistingConfig && !options.force) {
14
+ console.log(chalk.yellow('\n⚠️ Configuration already exists. Use --force to overwrite.'));
15
+ return;
16
+ }
17
+ let profileName = options.profile;
18
+ if (!profileName) {
19
+ profileName = await select({
20
+ message: 'Select a profile:',
21
+ choices: [
22
+ { value: 'basic', name: 'Basic - Minimal guidelines' },
23
+ { value: 'balanced', name: 'Balanced - Comprehensive best practices (recommended)' },
24
+ { value: 'expert', name: 'Expert - Complete setup with all features' }
25
+ ]
26
+ });
27
+ }
28
+ const profile = getProfile(profileName);
29
+ console.log(chalk.cyan(`\n📋 Using profile: ${profile.name}`));
30
+ console.log(chalk.gray(` ${profile.description}\n`));
31
+ const useAI = options.ai !== false && await isAnthropicAvailable();
32
+ if (!useAI) {
33
+ console.log(chalk.yellow('ℹ️ AI not available, using static templates\n'));
34
+ }
35
+ spinner.start('Generating configuration...');
36
+ await new Promise(resolve => setTimeout(resolve, 1000));
37
+ spinner.succeed('Configuration generated successfully!\n');
38
+ console.log(chalk.green('✨ Setup complete!'));
39
+ console.log(chalk.gray('\nGenerated files:'));
40
+ console.log(chalk.gray(' - .aicgen/claude.md'));
41
+ console.log(chalk.gray(' - .aicgen/instructions.md'));
42
+ if (profile.includeADR) {
43
+ console.log(chalk.gray(' - .aicgen/decisions.md'));
44
+ }
45
+ }
46
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Profile } from '../models/profile.js';
2
+ export declare const PROFILES: Record<string, Profile>;
3
+ export declare function getProfile(name: string): Profile;
4
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../src/config/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAyB5C,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD"}