@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,98 @@
1
+ # TypeScript Error Handling
2
+
3
+ ## Custom Error Classes
4
+
5
+ ```typescript
6
+ // ✅ Create structured error hierarchy
7
+ class AppError extends Error {
8
+ constructor(
9
+ message: string,
10
+ public statusCode: number = 500,
11
+ public code: string = 'INTERNAL_ERROR',
12
+ public details?: unknown
13
+ ) {
14
+ super(message);
15
+ this.name = this.constructor.name;
16
+ Error.captureStackTrace(this, this.constructor);
17
+ }
18
+ }
19
+
20
+ class NotFoundError extends AppError {
21
+ constructor(resource: string, id: string) {
22
+ super(`${resource} with id ${id} not found`, 404, 'NOT_FOUND', { resource, id });
23
+ }
24
+ }
25
+
26
+ class ValidationError extends AppError {
27
+ constructor(message: string, details: unknown) {
28
+ super(message, 400, 'VALIDATION_ERROR', details);
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Async Error Handling
34
+
35
+ ```typescript
36
+ // ✅ Always handle promise rejections
37
+ async function fetchUser(id: string): Promise<User> {
38
+ try {
39
+ const response = await api.get(`/users/${id}`);
40
+ return response.data;
41
+ } catch (error) {
42
+ if (error instanceof ApiError && error.status === 404) {
43
+ throw new NotFoundError('User', id);
44
+ }
45
+ throw new AppError('Failed to fetch user', 500, 'FETCH_ERROR', { userId: id });
46
+ }
47
+ }
48
+
49
+ // ✅ Use wrapper for Express async handlers
50
+ const asyncHandler = (fn: RequestHandler) => {
51
+ return (req: Request, res: Response, next: NextFunction) => {
52
+ Promise.resolve(fn(req, res, next)).catch(next);
53
+ };
54
+ };
55
+ ```
56
+
57
+ ## Result Type Pattern
58
+
59
+ ```typescript
60
+ // ✅ Explicit success/failure without exceptions
61
+ type Result<T, E = Error> =
62
+ | { success: true; value: T }
63
+ | { success: false; error: E };
64
+
65
+ function parseJSON<T>(json: string): Result<T, string> {
66
+ try {
67
+ return { success: true, value: JSON.parse(json) };
68
+ } catch {
69
+ return { success: false, error: 'Invalid JSON' };
70
+ }
71
+ }
72
+
73
+ // Usage
74
+ const result = parseJSON<User>(data);
75
+ if (result.success) {
76
+ console.log(result.value.name);
77
+ } else {
78
+ console.error(result.error);
79
+ }
80
+ ```
81
+
82
+ ## Centralized Error Handler
83
+
84
+ ```typescript
85
+ // ✅ Express error middleware
86
+ app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
87
+ if (err instanceof AppError) {
88
+ return res.status(err.statusCode).json({
89
+ error: { message: err.message, code: err.code, details: err.details }
90
+ });
91
+ }
92
+
93
+ console.error('Unexpected error:', err);
94
+ res.status(500).json({
95
+ error: { message: 'Internal server error', code: 'INTERNAL_ERROR' }
96
+ });
97
+ });
98
+ ```
@@ -0,0 +1,85 @@
1
+ # TypeScript Generics
2
+
3
+ ## Basic Generic Functions
4
+
5
+ ```typescript
6
+ // ✅ Generic function for type-safe operations
7
+ function first<T>(array: T[]): T | undefined {
8
+ return array[0];
9
+ }
10
+
11
+ const numbers = [1, 2, 3];
12
+ const firstNumber = first(numbers); // Type: number | undefined
13
+
14
+ const users = [{ name: 'John' }];
15
+ const firstUser = first(users); // Type: { name: string } | undefined
16
+ ```
17
+
18
+ ## Generic Interfaces
19
+
20
+ ```typescript
21
+ // ✅ Generic repository pattern
22
+ interface Repository<T> {
23
+ findById(id: string): Promise<T | null>;
24
+ findAll(): Promise<T[]>;
25
+ create(entity: Omit<T, 'id'>): Promise<T>;
26
+ update(id: string, data: Partial<T>): Promise<T>;
27
+ delete(id: string): Promise<void>;
28
+ }
29
+
30
+ class UserRepository implements Repository<User> {
31
+ async findById(id: string): Promise<User | null> {
32
+ return this.db.users.findUnique({ where: { id } });
33
+ }
34
+ // ... other methods
35
+ }
36
+ ```
37
+
38
+ ## Generic Constraints
39
+
40
+ ```typescript
41
+ // ✅ Constrain generic types
42
+ interface HasId {
43
+ id: string;
44
+ }
45
+
46
+ function getById<T extends HasId>(items: T[], id: string): T | undefined {
47
+ return items.find(item => item.id === id);
48
+ }
49
+
50
+ // Works with any type that has an id
51
+ getById(users, '123');
52
+ getById(products, '456');
53
+ ```
54
+
55
+ ## Mapped Types
56
+
57
+ ```typescript
58
+ // ✅ Create transformed types
59
+ type Nullable<T> = {
60
+ [K in keyof T]: T[K] | null;
61
+ };
62
+
63
+ type NullableUser = Nullable<User>;
64
+ // { id: string | null; name: string | null; ... }
65
+
66
+ // ✅ Conditional types
67
+ type ExtractArrayType<T> = T extends Array<infer U> ? U : never;
68
+
69
+ type StringArrayElement = ExtractArrayType<string[]>; // string
70
+ ```
71
+
72
+ ## Default Generic Parameters
73
+
74
+ ```typescript
75
+ // ✅ Provide defaults for flexibility
76
+ interface ApiResponse<T = unknown, E = Error> {
77
+ data?: T;
78
+ error?: E;
79
+ status: number;
80
+ }
81
+
82
+ // Can use with or without type parameters
83
+ const response1: ApiResponse<User> = { data: user, status: 200 };
84
+ const response2: ApiResponse = { status: 500, error: new Error('Failed') };
85
+ ```
@@ -0,0 +1,14 @@
1
+ # TypeScript Guidelines
2
+
3
+ TypeScript-specific best practices for Claude Code.
4
+
5
+ ## Chunks
6
+
7
+ - `basics.md` - Type system fundamentals and strict mode
8
+ - `interfaces-types.md` - Interfaces vs types, when to use each
9
+ - `generics.md` - Generic programming patterns
10
+ - `async.md` - Async/await and Promise patterns
11
+ - `error-handling.md` - Type-safe error handling
12
+ - `testing.md` - Testing TypeScript code
13
+ - `config.md` - tsconfig.json best practices
14
+ - `performance.md` - Performance optimization
@@ -0,0 +1,83 @@
1
+ # TypeScript Types & Interfaces
2
+
3
+ ## Prefer Interfaces for Public APIs
4
+
5
+ ```typescript
6
+ // ✅ Use interfaces for object shapes
7
+ interface User {
8
+ id: string;
9
+ name: string;
10
+ email: string;
11
+ createdAt: Date;
12
+ }
13
+
14
+ // ✅ Use type aliases for unions and complex types
15
+ type UserRole = 'admin' | 'editor' | 'viewer';
16
+ type ResponseHandler = (response: Response) => void;
17
+ ```
18
+
19
+ ## Discriminated Unions
20
+
21
+ ```typescript
22
+ // ✅ Use discriminated unions for variant types
23
+ type Result<T> =
24
+ | { success: true; data: T }
25
+ | { success: false; error: string };
26
+
27
+ function handleResult(result: Result<User>) {
28
+ if (result.success) {
29
+ console.log(result.data.name); // TypeScript knows data exists
30
+ } else {
31
+ console.error(result.error); // TypeScript knows error exists
32
+ }
33
+ }
34
+ ```
35
+
36
+ ## Utility Types
37
+
38
+ ```typescript
39
+ // Use built-in utility types
40
+ type PartialUser = Partial<User>; // All fields optional
41
+ type RequiredUser = Required<User>; // All fields required
42
+ type ReadonlyUser = Readonly<User>; // All fields readonly
43
+ type UserKeys = keyof User; // 'id' | 'name' | 'email' | 'createdAt'
44
+ type PickedUser = Pick<User, 'id' | 'name'>; // Only id and name
45
+ type OmittedUser = Omit<User, 'createdAt'>; // Everything except createdAt
46
+ ```
47
+
48
+ ## Type Guards
49
+
50
+ ```typescript
51
+ // ✅ Use type guards for runtime checking
52
+ function isUser(value: unknown): value is User {
53
+ return (
54
+ typeof value === 'object' &&
55
+ value !== null &&
56
+ 'id' in value &&
57
+ 'email' in value
58
+ );
59
+ }
60
+
61
+ // Usage
62
+ const data: unknown = fetchData();
63
+ if (isUser(data)) {
64
+ console.log(data.email); // TypeScript knows it's a User
65
+ }
66
+ ```
67
+
68
+ ## Avoid `any`
69
+
70
+ ```typescript
71
+ // ❌ Never use any
72
+ function process(data: any) {
73
+ return data.name; // No type safety
74
+ }
75
+
76
+ // ✅ Use unknown with type guards
77
+ function process(data: unknown) {
78
+ if (isUser(data)) {
79
+ return data.name; // Type-safe
80
+ }
81
+ throw new Error('Invalid data');
82
+ }
83
+ ```
@@ -0,0 +1,103 @@
1
+ # TypeScript Performance
2
+
3
+ ## Choose Right Data Structures
4
+
5
+ ```typescript
6
+ // ❌ Array for lookups (O(n))
7
+ const users: User[] = [];
8
+ const findUser = (id: string) => users.find(u => u.id === id);
9
+
10
+ // ✅ Map for O(1) lookups
11
+ const users = new Map<string, User>();
12
+ const findUser = (id: string) => users.get(id);
13
+
14
+ // ❌ Array for membership checks
15
+ const hasPermission = (perms: string[], perm: string) => perms.includes(perm);
16
+
17
+ // ✅ Set for O(1) membership
18
+ const hasPermission = (perms: Set<string>, perm: string) => perms.has(perm);
19
+ ```
20
+
21
+ ## Avoid N+1 Queries
22
+
23
+ ```typescript
24
+ // ❌ N+1 queries
25
+ const getOrdersWithCustomers = async () => {
26
+ const orders = await db.query('SELECT * FROM orders');
27
+ for (const order of orders) {
28
+ order.customer = await db.query('SELECT * FROM customers WHERE id = ?', [order.customerId]);
29
+ }
30
+ return orders;
31
+ };
32
+
33
+ // ✅ Single JOIN query
34
+ const getOrdersWithCustomers = async () => {
35
+ return db.query(`
36
+ SELECT orders.*, customers.name as customer_name
37
+ FROM orders
38
+ JOIN customers ON orders.customer_id = customers.id
39
+ `);
40
+ };
41
+
42
+ // ✅ Using ORM with eager loading
43
+ const getOrdersWithCustomers = async () => {
44
+ return orderRepository.find({ relations: ['customer'] });
45
+ };
46
+ ```
47
+
48
+ ## Parallel Execution
49
+
50
+ ```typescript
51
+ // ❌ Sequential (slow)
52
+ const getUserData = async (userId: string) => {
53
+ const user = await fetchUser(userId); // 100ms
54
+ const posts = await fetchPosts(userId); // 150ms
55
+ const comments = await fetchComments(userId); // 120ms
56
+ return { user, posts, comments }; // Total: 370ms
57
+ };
58
+
59
+ // ✅ Parallel (fast)
60
+ const getUserData = async (userId: string) => {
61
+ const [user, posts, comments] = await Promise.all([
62
+ fetchUser(userId),
63
+ fetchPosts(userId),
64
+ fetchComments(userId)
65
+ ]);
66
+ return { user, posts, comments }; // Total: 150ms
67
+ };
68
+ ```
69
+
70
+ ## Memoization
71
+
72
+ ```typescript
73
+ const memoize = <T extends (...args: any[]) => any>(fn: T): T => {
74
+ const cache = new Map<string, ReturnType<T>>();
75
+
76
+ return ((...args: any[]) => {
77
+ const key = JSON.stringify(args);
78
+ if (cache.has(key)) return cache.get(key);
79
+ const result = fn(...args);
80
+ cache.set(key, result);
81
+ return result;
82
+ }) as T;
83
+ };
84
+
85
+ const expensiveCalc = memoize((n: number) => {
86
+ // Expensive computation
87
+ return result;
88
+ });
89
+ ```
90
+
91
+ ## Batch Processing
92
+
93
+ ```typescript
94
+ // ✅ Process in batches
95
+ const processUsers = async (userIds: string[]) => {
96
+ const BATCH_SIZE = 50;
97
+
98
+ for (let i = 0; i < userIds.length; i += BATCH_SIZE) {
99
+ const batch = userIds.slice(i, i + BATCH_SIZE);
100
+ await Promise.all(batch.map(id => updateUser(id)));
101
+ }
102
+ };
103
+ ```
@@ -0,0 +1,98 @@
1
+ # TypeScript Testing
2
+
3
+ ## Test Structure: Arrange-Act-Assert
4
+
5
+ ```typescript
6
+ describe('UserService', () => {
7
+ describe('createUser', () => {
8
+ it('should create user with hashed password', async () => {
9
+ // Arrange
10
+ const userData = { email: 'test@example.com', password: 'password123' };
11
+ const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };
12
+ const service = new UserService(mockRepo);
13
+
14
+ // Act
15
+ const result = await service.createUser(userData);
16
+
17
+ // Assert
18
+ expect(result.id).toBe('1');
19
+ expect(mockRepo.save).toHaveBeenCalledWith(
20
+ expect.objectContaining({ email: 'test@example.com' })
21
+ );
22
+ });
23
+ });
24
+ });
25
+ ```
26
+
27
+ ## Test Observable Behavior, Not Implementation
28
+
29
+ ```typescript
30
+ // ❌ Testing implementation details
31
+ it('should call validateEmail method', () => {
32
+ const spy = jest.spyOn(service, 'validateEmail');
33
+ service.createUser({ email: 'test@example.com' });
34
+ expect(spy).toHaveBeenCalled(); // Brittle - breaks if refactored
35
+ });
36
+
37
+ // ✅ Testing observable behavior
38
+ it('should reject invalid email', async () => {
39
+ await expect(
40
+ service.createUser({ email: 'invalid' })
41
+ ).rejects.toThrow('Invalid email');
42
+ });
43
+ ```
44
+
45
+ ## Test Doubles
46
+
47
+ ```typescript
48
+ // Stub: Returns canned responses
49
+ const stubDatabase = {
50
+ findUser: () => ({ id: '1', name: 'Test User' })
51
+ };
52
+
53
+ // Mock: Pre-programmed with expectations
54
+ const mockPayment = {
55
+ charge: jest.fn()
56
+ .mockResolvedValueOnce({ success: true })
57
+ .mockResolvedValueOnce({ success: false })
58
+ };
59
+
60
+ // Fake: Working implementation (not for production)
61
+ class FakeDatabase implements Database {
62
+ private data = new Map<string, any>();
63
+
64
+ async save(id: string, data: any) { this.data.set(id, data); }
65
+ async find(id: string) { return this.data.get(id); }
66
+ }
67
+ ```
68
+
69
+ ## One Test Per Condition
70
+
71
+ ```typescript
72
+ // ❌ Multiple assertions for different scenarios
73
+ it('should validate user input', () => {
74
+ expect(() => validate({ age: -1 })).toThrow();
75
+ expect(() => validate({ age: 200 })).toThrow();
76
+ expect(() => validate({ name: '' })).toThrow();
77
+ });
78
+
79
+ // ✅ One test per condition
80
+ it('should reject negative age', () => {
81
+ expect(() => validate({ age: -1 })).toThrow('Age must be positive');
82
+ });
83
+
84
+ it('should reject age over 150', () => {
85
+ expect(() => validate({ age: 200 })).toThrow('Age must be under 150');
86
+ });
87
+ ```
88
+
89
+ ## Keep Tests Independent
90
+
91
+ ```typescript
92
+ // ✅ Each test is self-contained
93
+ it('should update user', async () => {
94
+ const user = await service.createUser({ name: 'Test' });
95
+ const updated = await service.updateUser(user.id, { name: 'Updated' });
96
+ expect(updated.name).toBe('Updated');
97
+ });
98
+ ```
@@ -0,0 +1,105 @@
1
+ # Base Patterns
2
+
3
+ ## Value Object
4
+
5
+ Immutable object defined by its value, not identity.
6
+
7
+ ```typescript
8
+ class Email {
9
+ private readonly value: string;
10
+
11
+ constructor(email: string) {
12
+ if (!this.isValid(email)) throw new Error('Invalid email');
13
+ this.value = email.toLowerCase();
14
+ }
15
+
16
+ equals(other: Email): boolean {
17
+ return this.value === other.value;
18
+ }
19
+ }
20
+
21
+ class Money {
22
+ constructor(
23
+ public readonly amount: number,
24
+ public readonly currency: Currency
25
+ ) {
26
+ Object.freeze(this);
27
+ }
28
+
29
+ add(other: Money): Money {
30
+ this.assertSameCurrency(other);
31
+ return new Money(this.amount + other.amount, this.currency);
32
+ }
33
+ }
34
+ ```
35
+
36
+ ## Special Case (Null Object)
37
+
38
+ Replace null checks with polymorphism.
39
+
40
+ ```typescript
41
+ abstract class Customer {
42
+ abstract getDiscount(): number;
43
+ }
44
+
45
+ class RealCustomer extends Customer {
46
+ getDiscount(): number { return 0.1; }
47
+ }
48
+
49
+ class GuestCustomer extends Customer {
50
+ getDiscount(): number { return 0; } // No discount
51
+ }
52
+
53
+ // No null checks needed
54
+ const customer = repo.findById(id) || new GuestCustomer();
55
+ const discount = customer.getDiscount();
56
+ ```
57
+
58
+ ## Registry
59
+
60
+ Global access point for services.
61
+
62
+ ```typescript
63
+ class ServiceRegistry {
64
+ private static services = new Map<string, any>();
65
+
66
+ static register<T>(key: string, service: T): void {
67
+ this.services.set(key, service);
68
+ }
69
+
70
+ static get<T>(key: string): T {
71
+ return this.services.get(key);
72
+ }
73
+ }
74
+
75
+ // Prefer dependency injection over registry
76
+ ```
77
+
78
+ ## Plugin
79
+
80
+ Extend behavior without modifying core code.
81
+
82
+ ```typescript
83
+ interface ValidationPlugin {
84
+ validate(user: User): ValidationResult;
85
+ }
86
+
87
+ class UserValidator {
88
+ private plugins: ValidationPlugin[] = [];
89
+
90
+ registerPlugin(plugin: ValidationPlugin): void {
91
+ this.plugins.push(plugin);
92
+ }
93
+
94
+ validate(user: User): ValidationResult[] {
95
+ return this.plugins.map(p => p.validate(user));
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## Best Practices
101
+
102
+ - Use Value Objects to avoid primitive obsession
103
+ - Make Value Objects immutable
104
+ - Use Special Case instead of null checks
105
+ - Prefer dependency injection over Registry
@@ -0,0 +1,87 @@
1
+ # Concurrency Patterns
2
+
3
+ ## Optimistic Locking
4
+
5
+ Detect conflicts on commit using version numbers.
6
+
7
+ ```typescript
8
+ class Product {
9
+ constructor(
10
+ public id: string,
11
+ public name: string,
12
+ public version: number = 1
13
+ ) {}
14
+ }
15
+
16
+ class ProductRepository {
17
+ async save(product: Product): Promise<void> {
18
+ const result = await this.db.execute(
19
+ `UPDATE products SET name = $1, version = version + 1
20
+ WHERE id = $2 AND version = $3`,
21
+ [product.name, product.id, product.version]
22
+ );
23
+
24
+ if (result.rowCount === 0) {
25
+ throw new OptimisticLockException('Product was modified');
26
+ }
27
+ product.version++;
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## Pessimistic Locking
33
+
34
+ Lock resources before editing.
35
+
36
+ ```typescript
37
+ class LockManager {
38
+ async acquireLock(resourceId: string, ownerId: string): Promise<boolean> {
39
+ const existing = await this.db.queryOne(
40
+ 'SELECT * FROM locks WHERE resource_id = $1 AND expires_at > NOW()',
41
+ [resourceId]
42
+ );
43
+
44
+ if (existing) return false;
45
+
46
+ await this.db.execute(
47
+ 'INSERT INTO locks (resource_id, owner_id, expires_at) VALUES ($1, $2, $3)',
48
+ [resourceId, ownerId, new Date(Date.now() + 30000)]
49
+ );
50
+ return true;
51
+ }
52
+
53
+ async releaseLock(resourceId: string, ownerId: string): Promise<void> {
54
+ await this.db.execute(
55
+ 'DELETE FROM locks WHERE resource_id = $1 AND owner_id = $2',
56
+ [resourceId, ownerId]
57
+ );
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Coarse-Grained Lock
63
+
64
+ Lock entire aggregate rather than individual entities.
65
+
66
+ ```typescript
67
+ class OrderRepository {
68
+ async save(order: Order): Promise<void> {
69
+ // Lock aggregate root, all children implicitly locked
70
+ await this.db.execute(
71
+ 'SELECT * FROM orders WHERE id = $1 FOR UPDATE',
72
+ [order.id]
73
+ );
74
+
75
+ // Update order and all items in single transaction
76
+ await this.updateOrder(order);
77
+ await this.updateOrderItems(order.items);
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Best Practices
83
+
84
+ - Use optimistic locking for low-contention scenarios
85
+ - Use pessimistic locking for high-contention or critical data
86
+ - Always set lock timeouts
87
+ - Implement retry logic with exponential backoff