@aicgen/aicgen 1.0.0-beta.1 → 1.0.0-beta.2
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/.vs/ProjectSettings.json +2 -2
- package/.vs/VSWorkspaceState.json +15 -15
- package/.vs/aicgen.slnx/v18/DocumentLayout.json +53 -53
- package/assets/icon.svg +33 -33
- package/bun.lock +0 -43
- package/data/architecture/microservices/api-gateway.md +56 -56
- package/data/devops/observability.md +73 -73
- package/dist/index.js +9299 -9299
- package/package.json +2 -2
- package/.claude/agents/architecture-reviewer.md +0 -88
- package/.claude/agents/guideline-checker.md +0 -73
- package/.claude/agents/security-auditor.md +0 -108
- package/.claude/guidelines/api-design.md +0 -645
- package/.claude/guidelines/architecture.md +0 -2503
- package/.claude/guidelines/best-practices.md +0 -618
- package/.claude/guidelines/code-style.md +0 -304
- package/.claude/guidelines/design-patterns.md +0 -573
- package/.claude/guidelines/devops.md +0 -226
- package/.claude/guidelines/error-handling.md +0 -413
- package/.claude/guidelines/language.md +0 -782
- package/.claude/guidelines/performance.md +0 -706
- package/.claude/guidelines/security.md +0 -583
- package/.claude/guidelines/testing.md +0 -568
- package/.claude/settings.json +0 -98
- package/.claude/settings.local.json +0 -8
- package/.eslintrc.json +0 -28
- package/.github/workflows/release.yml +0 -180
- package/.github/workflows/test.yml +0 -81
- package/CONTRIBUTING.md +0 -821
- package/dist/commands/init.d.ts +0 -8
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -46
- package/dist/commands/init.js.map +0 -1
- package/dist/config/profiles.d.ts +0 -4
- package/dist/config/profiles.d.ts.map +0 -1
- package/dist/config/profiles.js +0 -30
- package/dist/config/profiles.js.map +0 -1
- package/dist/config/settings.d.ts +0 -7
- package/dist/config/settings.d.ts.map +0 -1
- package/dist/config/settings.js +0 -7
- package/dist/config/settings.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/models/guideline.d.ts +0 -15
- package/dist/models/guideline.d.ts.map +0 -1
- package/dist/models/guideline.js +0 -2
- package/dist/models/guideline.js.map +0 -1
- package/dist/models/preference.d.ts +0 -9
- package/dist/models/preference.d.ts.map +0 -1
- package/dist/models/preference.js +0 -2
- package/dist/models/preference.js.map +0 -1
- package/dist/models/profile.d.ts +0 -9
- package/dist/models/profile.d.ts.map +0 -1
- package/dist/models/profile.js +0 -2
- package/dist/models/profile.js.map +0 -1
- package/dist/models/project.d.ts +0 -13
- package/dist/models/project.d.ts.map +0 -1
- package/dist/models/project.js +0 -2
- package/dist/models/project.js.map +0 -1
- package/dist/services/ai/anthropic.d.ts +0 -7
- package/dist/services/ai/anthropic.d.ts.map +0 -1
- package/dist/services/ai/anthropic.js +0 -39
- package/dist/services/ai/anthropic.js.map +0 -1
- package/dist/services/generator.d.ts +0 -2
- package/dist/services/generator.d.ts.map +0 -1
- package/dist/services/generator.js +0 -4
- package/dist/services/generator.js.map +0 -1
- package/dist/services/learner.d.ts +0 -2
- package/dist/services/learner.d.ts.map +0 -1
- package/dist/services/learner.js +0 -4
- package/dist/services/learner.js.map +0 -1
- package/dist/services/scanner.d.ts +0 -3
- package/dist/services/scanner.d.ts.map +0 -1
- package/dist/services/scanner.js +0 -54
- package/dist/services/scanner.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -15
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -27
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/file.d.ts +0 -7
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js +0 -32
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -17
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/path.d.ts +0 -6
- package/dist/utils/path.d.ts.map +0 -1
- package/dist/utils/path.js +0 -14
- package/dist/utils/path.js.map +0 -1
- package/docs/planning/memory-lane.md +0 -83
- package/packaging/linux/aicgen.spec +0 -23
- package/packaging/linux/control +0 -9
- package/packaging/macos/scripts/postinstall +0 -12
- package/packaging/windows/setup.nsi +0 -92
- package/scripts/add-categories.ts +0 -87
- package/scripts/build-binary.ts +0 -46
- package/scripts/embed-data.ts +0 -105
- package/scripts/generate-version.ts +0 -150
- package/scripts/test-decompress.ts +0 -27
- package/scripts/test-extract.ts +0 -31
- package/src/__tests__/services/assistant-file-writer.test.ts +0 -400
- package/src/__tests__/services/guideline-loader.test.ts +0 -281
- package/src/__tests__/services/tarball-extraction.test.ts +0 -125
- package/src/commands/add-guideline.ts +0 -296
- package/src/commands/clear.ts +0 -61
- package/src/commands/guideline-selector.ts +0 -123
- package/src/commands/init.ts +0 -645
- package/src/commands/quick-add.ts +0 -586
- package/src/commands/remove-guideline.ts +0 -152
- package/src/commands/stats.ts +0 -49
- package/src/commands/update.ts +0 -240
- package/src/config.ts +0 -82
- package/src/embedded-data.ts +0 -1492
- package/src/index.ts +0 -67
- package/src/models/profile.ts +0 -24
- package/src/models/project.ts +0 -43
- package/src/services/assistant-file-writer.ts +0 -612
- package/src/services/config-generator.ts +0 -150
- package/src/services/config-manager.ts +0 -70
- package/src/services/data-source.ts +0 -248
- package/src/services/first-run-init.ts +0 -148
- package/src/services/guideline-loader.ts +0 -311
- package/src/services/hook-generator.ts +0 -178
- package/src/services/subagent-generator.ts +0 -310
- package/src/utils/banner.ts +0 -66
- package/src/utils/errors.ts +0 -27
- package/src/utils/file.ts +0 -67
- package/src/utils/formatting.ts +0 -172
- package/src/utils/logger.ts +0 -89
- package/src/utils/path.ts +0 -17
- package/src/utils/wizard-state.ts +0 -132
- package/tsconfig.json +0 -25
- /package/{CLAUDE.md → claude.md} +0 -0
package/src/embedded-data.ts
DELETED
|
@@ -1,1492 +0,0 @@
|
|
|
1
|
-
// AUTO-GENERATED - DO NOT EDIT
|
|
2
|
-
// Generated by scripts/embed-data.ts
|
|
3
|
-
// Contains all guideline mappings and content embedded for binary distribution
|
|
4
|
-
|
|
5
|
-
export interface GuidelineMapping {
|
|
6
|
-
path: string;
|
|
7
|
-
category?: string;
|
|
8
|
-
languages?: string[];
|
|
9
|
-
levels?: string[];
|
|
10
|
-
architectures?: string[];
|
|
11
|
-
datasources?: string[];
|
|
12
|
-
tags?: string[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface EmbeddedData {
|
|
16
|
-
mappings: Record<string, GuidelineMapping>;
|
|
17
|
-
guidelines: Record<string, string>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const EMBEDDED_DATA: EmbeddedData = {
|
|
21
|
-
"mappings": {
|
|
22
|
-
"typescript-basics": {
|
|
23
|
-
"path": "language/typescript/basics.md",
|
|
24
|
-
"languages": [
|
|
25
|
-
"typescript"
|
|
26
|
-
],
|
|
27
|
-
"levels": [
|
|
28
|
-
"basic",
|
|
29
|
-
"standard",
|
|
30
|
-
"expert",
|
|
31
|
-
"full"
|
|
32
|
-
],
|
|
33
|
-
"tags": [
|
|
34
|
-
"typescript",
|
|
35
|
-
"fundamentals",
|
|
36
|
-
"types"
|
|
37
|
-
],
|
|
38
|
-
"category": "Language"
|
|
39
|
-
},
|
|
40
|
-
"typescript-async": {
|
|
41
|
-
"path": "language/typescript/async.md",
|
|
42
|
-
"languages": [
|
|
43
|
-
"typescript"
|
|
44
|
-
],
|
|
45
|
-
"levels": [
|
|
46
|
-
"basic",
|
|
47
|
-
"standard",
|
|
48
|
-
"expert",
|
|
49
|
-
"full"
|
|
50
|
-
],
|
|
51
|
-
"tags": [
|
|
52
|
-
"typescript",
|
|
53
|
-
"async",
|
|
54
|
-
"promises"
|
|
55
|
-
],
|
|
56
|
-
"category": "Language"
|
|
57
|
-
},
|
|
58
|
-
"typescript-interfaces-types": {
|
|
59
|
-
"path": "language/typescript/interfaces-types.md",
|
|
60
|
-
"languages": [
|
|
61
|
-
"typescript"
|
|
62
|
-
],
|
|
63
|
-
"levels": [
|
|
64
|
-
"standard",
|
|
65
|
-
"expert",
|
|
66
|
-
"full"
|
|
67
|
-
],
|
|
68
|
-
"tags": [
|
|
69
|
-
"typescript",
|
|
70
|
-
"interfaces",
|
|
71
|
-
"types",
|
|
72
|
-
"utility-types"
|
|
73
|
-
],
|
|
74
|
-
"category": "Language"
|
|
75
|
-
},
|
|
76
|
-
"typescript-generics": {
|
|
77
|
-
"path": "language/typescript/generics.md",
|
|
78
|
-
"languages": [
|
|
79
|
-
"typescript"
|
|
80
|
-
],
|
|
81
|
-
"levels": [
|
|
82
|
-
"expert",
|
|
83
|
-
"full"
|
|
84
|
-
],
|
|
85
|
-
"tags": [
|
|
86
|
-
"typescript",
|
|
87
|
-
"generics",
|
|
88
|
-
"advanced"
|
|
89
|
-
],
|
|
90
|
-
"category": "Language"
|
|
91
|
-
},
|
|
92
|
-
"typescript-error-handling": {
|
|
93
|
-
"path": "language/typescript/error-handling.md",
|
|
94
|
-
"languages": [
|
|
95
|
-
"typescript"
|
|
96
|
-
],
|
|
97
|
-
"levels": [
|
|
98
|
-
"standard",
|
|
99
|
-
"expert",
|
|
100
|
-
"full"
|
|
101
|
-
],
|
|
102
|
-
"tags": [
|
|
103
|
-
"typescript",
|
|
104
|
-
"errors",
|
|
105
|
-
"exceptions"
|
|
106
|
-
],
|
|
107
|
-
"category": "Language"
|
|
108
|
-
},
|
|
109
|
-
"typescript-testing": {
|
|
110
|
-
"path": "language/typescript/testing.md",
|
|
111
|
-
"languages": [
|
|
112
|
-
"typescript"
|
|
113
|
-
],
|
|
114
|
-
"levels": [
|
|
115
|
-
"standard",
|
|
116
|
-
"expert",
|
|
117
|
-
"full"
|
|
118
|
-
],
|
|
119
|
-
"tags": [
|
|
120
|
-
"typescript",
|
|
121
|
-
"testing",
|
|
122
|
-
"jest"
|
|
123
|
-
],
|
|
124
|
-
"category": "Language"
|
|
125
|
-
},
|
|
126
|
-
"typescript-config": {
|
|
127
|
-
"path": "language/typescript/config.md",
|
|
128
|
-
"languages": [
|
|
129
|
-
"typescript"
|
|
130
|
-
],
|
|
131
|
-
"levels": [
|
|
132
|
-
"standard",
|
|
133
|
-
"expert",
|
|
134
|
-
"full"
|
|
135
|
-
],
|
|
136
|
-
"tags": [
|
|
137
|
-
"typescript",
|
|
138
|
-
"tsconfig",
|
|
139
|
-
"configuration"
|
|
140
|
-
],
|
|
141
|
-
"category": "Language"
|
|
142
|
-
},
|
|
143
|
-
"typescript-performance": {
|
|
144
|
-
"path": "language/typescript/performance.md",
|
|
145
|
-
"languages": [
|
|
146
|
-
"typescript"
|
|
147
|
-
],
|
|
148
|
-
"levels": [
|
|
149
|
-
"expert",
|
|
150
|
-
"full"
|
|
151
|
-
],
|
|
152
|
-
"tags": [
|
|
153
|
-
"typescript",
|
|
154
|
-
"performance",
|
|
155
|
-
"optimization"
|
|
156
|
-
],
|
|
157
|
-
"category": "Language"
|
|
158
|
-
},
|
|
159
|
-
"python-basics": {
|
|
160
|
-
"path": "language/python/basics.md",
|
|
161
|
-
"languages": [
|
|
162
|
-
"python"
|
|
163
|
-
],
|
|
164
|
-
"levels": [
|
|
165
|
-
"basic",
|
|
166
|
-
"standard",
|
|
167
|
-
"expert",
|
|
168
|
-
"full"
|
|
169
|
-
],
|
|
170
|
-
"tags": [
|
|
171
|
-
"python",
|
|
172
|
-
"fundamentals",
|
|
173
|
-
"pep8"
|
|
174
|
-
],
|
|
175
|
-
"category": "Language"
|
|
176
|
-
},
|
|
177
|
-
"python-types": {
|
|
178
|
-
"path": "language/python/types.md",
|
|
179
|
-
"languages": [
|
|
180
|
-
"python"
|
|
181
|
-
],
|
|
182
|
-
"levels": [
|
|
183
|
-
"standard",
|
|
184
|
-
"expert",
|
|
185
|
-
"full"
|
|
186
|
-
],
|
|
187
|
-
"tags": [
|
|
188
|
-
"python",
|
|
189
|
-
"types",
|
|
190
|
-
"type-hints",
|
|
191
|
-
"mypy"
|
|
192
|
-
],
|
|
193
|
-
"category": "Language"
|
|
194
|
-
},
|
|
195
|
-
"python-async": {
|
|
196
|
-
"path": "language/python/async.md",
|
|
197
|
-
"languages": [
|
|
198
|
-
"python"
|
|
199
|
-
],
|
|
200
|
-
"levels": [
|
|
201
|
-
"expert",
|
|
202
|
-
"full"
|
|
203
|
-
],
|
|
204
|
-
"tags": [
|
|
205
|
-
"python",
|
|
206
|
-
"async",
|
|
207
|
-
"asyncio"
|
|
208
|
-
],
|
|
209
|
-
"category": "Language"
|
|
210
|
-
},
|
|
211
|
-
"python-testing": {
|
|
212
|
-
"path": "language/python/testing.md",
|
|
213
|
-
"languages": [
|
|
214
|
-
"python"
|
|
215
|
-
],
|
|
216
|
-
"levels": [
|
|
217
|
-
"standard",
|
|
218
|
-
"expert",
|
|
219
|
-
"full"
|
|
220
|
-
],
|
|
221
|
-
"tags": [
|
|
222
|
-
"python",
|
|
223
|
-
"testing",
|
|
224
|
-
"pytest"
|
|
225
|
-
],
|
|
226
|
-
"category": "Language"
|
|
227
|
-
},
|
|
228
|
-
"go-basics": {
|
|
229
|
-
"path": "language/go/basics.md",
|
|
230
|
-
"languages": [
|
|
231
|
-
"go"
|
|
232
|
-
],
|
|
233
|
-
"levels": [
|
|
234
|
-
"basic",
|
|
235
|
-
"standard",
|
|
236
|
-
"expert",
|
|
237
|
-
"full"
|
|
238
|
-
],
|
|
239
|
-
"tags": [
|
|
240
|
-
"go",
|
|
241
|
-
"golang",
|
|
242
|
-
"fundamentals"
|
|
243
|
-
],
|
|
244
|
-
"category": "Language"
|
|
245
|
-
},
|
|
246
|
-
"rust-basics": {
|
|
247
|
-
"path": "language/rust/basics.md",
|
|
248
|
-
"languages": [
|
|
249
|
-
"rust"
|
|
250
|
-
],
|
|
251
|
-
"levels": [
|
|
252
|
-
"basic",
|
|
253
|
-
"standard",
|
|
254
|
-
"expert",
|
|
255
|
-
"full"
|
|
256
|
-
],
|
|
257
|
-
"tags": [
|
|
258
|
-
"rust",
|
|
259
|
-
"ownership",
|
|
260
|
-
"fundamentals"
|
|
261
|
-
],
|
|
262
|
-
"category": "Language"
|
|
263
|
-
},
|
|
264
|
-
"java-basics": {
|
|
265
|
-
"path": "language/java/basics.md",
|
|
266
|
-
"languages": [
|
|
267
|
-
"java"
|
|
268
|
-
],
|
|
269
|
-
"levels": [
|
|
270
|
-
"basic",
|
|
271
|
-
"standard",
|
|
272
|
-
"expert",
|
|
273
|
-
"full"
|
|
274
|
-
],
|
|
275
|
-
"tags": [
|
|
276
|
-
"java",
|
|
277
|
-
"jvm",
|
|
278
|
-
"fundamentals"
|
|
279
|
-
],
|
|
280
|
-
"category": "Language"
|
|
281
|
-
},
|
|
282
|
-
"csharp-basics": {
|
|
283
|
-
"path": "language/csharp/basics.md",
|
|
284
|
-
"languages": [
|
|
285
|
-
"csharp"
|
|
286
|
-
],
|
|
287
|
-
"levels": [
|
|
288
|
-
"basic",
|
|
289
|
-
"standard",
|
|
290
|
-
"expert",
|
|
291
|
-
"full"
|
|
292
|
-
],
|
|
293
|
-
"tags": [
|
|
294
|
-
"csharp",
|
|
295
|
-
"dotnet",
|
|
296
|
-
"fundamentals"
|
|
297
|
-
],
|
|
298
|
-
"category": "Language"
|
|
299
|
-
},
|
|
300
|
-
"ruby-basics": {
|
|
301
|
-
"path": "language/ruby/basics.md",
|
|
302
|
-
"languages": [
|
|
303
|
-
"ruby"
|
|
304
|
-
],
|
|
305
|
-
"levels": [
|
|
306
|
-
"basic",
|
|
307
|
-
"standard",
|
|
308
|
-
"expert",
|
|
309
|
-
"full"
|
|
310
|
-
],
|
|
311
|
-
"tags": [
|
|
312
|
-
"ruby",
|
|
313
|
-
"rails",
|
|
314
|
-
"fundamentals"
|
|
315
|
-
],
|
|
316
|
-
"category": "Language"
|
|
317
|
-
},
|
|
318
|
-
"javascript-basics": {
|
|
319
|
-
"path": "language/javascript/basics.md",
|
|
320
|
-
"languages": [
|
|
321
|
-
"javascript"
|
|
322
|
-
],
|
|
323
|
-
"levels": [
|
|
324
|
-
"basic",
|
|
325
|
-
"standard",
|
|
326
|
-
"expert",
|
|
327
|
-
"full"
|
|
328
|
-
],
|
|
329
|
-
"tags": [
|
|
330
|
-
"javascript",
|
|
331
|
-
"es6",
|
|
332
|
-
"fundamentals"
|
|
333
|
-
],
|
|
334
|
-
"category": "Language"
|
|
335
|
-
},
|
|
336
|
-
"go-testing": {
|
|
337
|
-
"path": "language/go/testing.md",
|
|
338
|
-
"languages": [
|
|
339
|
-
"go"
|
|
340
|
-
],
|
|
341
|
-
"levels": [
|
|
342
|
-
"standard",
|
|
343
|
-
"expert",
|
|
344
|
-
"full"
|
|
345
|
-
],
|
|
346
|
-
"tags": [
|
|
347
|
-
"go",
|
|
348
|
-
"testing",
|
|
349
|
-
"table-driven"
|
|
350
|
-
],
|
|
351
|
-
"category": "Language"
|
|
352
|
-
},
|
|
353
|
-
"rust-testing": {
|
|
354
|
-
"path": "language/rust/testing.md",
|
|
355
|
-
"languages": [
|
|
356
|
-
"rust"
|
|
357
|
-
],
|
|
358
|
-
"levels": [
|
|
359
|
-
"standard",
|
|
360
|
-
"expert",
|
|
361
|
-
"full"
|
|
362
|
-
],
|
|
363
|
-
"tags": [
|
|
364
|
-
"rust",
|
|
365
|
-
"testing",
|
|
366
|
-
"cargo-test"
|
|
367
|
-
],
|
|
368
|
-
"category": "Language"
|
|
369
|
-
},
|
|
370
|
-
"java-testing": {
|
|
371
|
-
"path": "language/java/testing.md",
|
|
372
|
-
"languages": [
|
|
373
|
-
"java"
|
|
374
|
-
],
|
|
375
|
-
"levels": [
|
|
376
|
-
"standard",
|
|
377
|
-
"expert",
|
|
378
|
-
"full"
|
|
379
|
-
],
|
|
380
|
-
"tags": [
|
|
381
|
-
"java",
|
|
382
|
-
"testing",
|
|
383
|
-
"junit",
|
|
384
|
-
"mockito"
|
|
385
|
-
],
|
|
386
|
-
"category": "Language"
|
|
387
|
-
},
|
|
388
|
-
"csharp-testing": {
|
|
389
|
-
"path": "language/csharp/testing.md",
|
|
390
|
-
"languages": [
|
|
391
|
-
"csharp"
|
|
392
|
-
],
|
|
393
|
-
"levels": [
|
|
394
|
-
"standard",
|
|
395
|
-
"expert",
|
|
396
|
-
"full"
|
|
397
|
-
],
|
|
398
|
-
"tags": [
|
|
399
|
-
"csharp",
|
|
400
|
-
"testing",
|
|
401
|
-
"xunit",
|
|
402
|
-
"moq"
|
|
403
|
-
],
|
|
404
|
-
"category": "Language"
|
|
405
|
-
},
|
|
406
|
-
"ruby-testing": {
|
|
407
|
-
"path": "language/ruby/testing.md",
|
|
408
|
-
"languages": [
|
|
409
|
-
"ruby"
|
|
410
|
-
],
|
|
411
|
-
"levels": [
|
|
412
|
-
"standard",
|
|
413
|
-
"expert",
|
|
414
|
-
"full"
|
|
415
|
-
],
|
|
416
|
-
"tags": [
|
|
417
|
-
"ruby",
|
|
418
|
-
"testing",
|
|
419
|
-
"rspec"
|
|
420
|
-
],
|
|
421
|
-
"category": "Language"
|
|
422
|
-
},
|
|
423
|
-
"javascript-testing": {
|
|
424
|
-
"path": "language/javascript/testing.md",
|
|
425
|
-
"languages": [
|
|
426
|
-
"javascript"
|
|
427
|
-
],
|
|
428
|
-
"levels": [
|
|
429
|
-
"standard",
|
|
430
|
-
"expert",
|
|
431
|
-
"full"
|
|
432
|
-
],
|
|
433
|
-
"tags": [
|
|
434
|
-
"javascript",
|
|
435
|
-
"testing",
|
|
436
|
-
"jest"
|
|
437
|
-
],
|
|
438
|
-
"category": "Language"
|
|
439
|
-
},
|
|
440
|
-
"microservices-boundaries": {
|
|
441
|
-
"path": "architecture/microservices/boundaries.md",
|
|
442
|
-
"architectures": [
|
|
443
|
-
"microservices"
|
|
444
|
-
],
|
|
445
|
-
"levels": [
|
|
446
|
-
"standard",
|
|
447
|
-
"expert",
|
|
448
|
-
"full"
|
|
449
|
-
],
|
|
450
|
-
"tags": [
|
|
451
|
-
"microservices",
|
|
452
|
-
"boundaries",
|
|
453
|
-
"ddd"
|
|
454
|
-
],
|
|
455
|
-
"category": "Architecture"
|
|
456
|
-
},
|
|
457
|
-
"microservices-communication": {
|
|
458
|
-
"path": "architecture/microservices/communication.md",
|
|
459
|
-
"architectures": [
|
|
460
|
-
"microservices"
|
|
461
|
-
],
|
|
462
|
-
"levels": [
|
|
463
|
-
"standard",
|
|
464
|
-
"expert",
|
|
465
|
-
"full"
|
|
466
|
-
],
|
|
467
|
-
"tags": [
|
|
468
|
-
"microservices",
|
|
469
|
-
"communication",
|
|
470
|
-
"messaging",
|
|
471
|
-
"events"
|
|
472
|
-
],
|
|
473
|
-
"category": "Architecture"
|
|
474
|
-
},
|
|
475
|
-
"microservices-data": {
|
|
476
|
-
"path": "architecture/microservices/data.md",
|
|
477
|
-
"architectures": [
|
|
478
|
-
"microservices"
|
|
479
|
-
],
|
|
480
|
-
"levels": [
|
|
481
|
-
"standard",
|
|
482
|
-
"expert",
|
|
483
|
-
"full"
|
|
484
|
-
],
|
|
485
|
-
"tags": [
|
|
486
|
-
"microservices",
|
|
487
|
-
"data",
|
|
488
|
-
"consistency",
|
|
489
|
-
"saga"
|
|
490
|
-
],
|
|
491
|
-
"category": "Architecture"
|
|
492
|
-
},
|
|
493
|
-
"microservices-resilience": {
|
|
494
|
-
"path": "architecture/microservices/resilience.md",
|
|
495
|
-
"architectures": [
|
|
496
|
-
"microservices"
|
|
497
|
-
],
|
|
498
|
-
"levels": [
|
|
499
|
-
"expert",
|
|
500
|
-
"full"
|
|
501
|
-
],
|
|
502
|
-
"tags": [
|
|
503
|
-
"microservices",
|
|
504
|
-
"resilience",
|
|
505
|
-
"circuit-breaker",
|
|
506
|
-
"retry"
|
|
507
|
-
],
|
|
508
|
-
"category": "Architecture"
|
|
509
|
-
},
|
|
510
|
-
"microservices-api-gateway": {
|
|
511
|
-
"path": "architecture/microservices/api-gateway.md",
|
|
512
|
-
"architectures": [
|
|
513
|
-
"microservices"
|
|
514
|
-
],
|
|
515
|
-
"levels": [
|
|
516
|
-
"standard",
|
|
517
|
-
"expert",
|
|
518
|
-
"full"
|
|
519
|
-
],
|
|
520
|
-
"tags": [
|
|
521
|
-
"microservices",
|
|
522
|
-
"api-gateway",
|
|
523
|
-
"bff",
|
|
524
|
-
"routing"
|
|
525
|
-
],
|
|
526
|
-
"category": "Architecture"
|
|
527
|
-
},
|
|
528
|
-
"modular-monolith-structure": {
|
|
529
|
-
"path": "architecture/modular-monolith/structure.md",
|
|
530
|
-
"architectures": [
|
|
531
|
-
"modular-monolith"
|
|
532
|
-
],
|
|
533
|
-
"levels": [
|
|
534
|
-
"standard",
|
|
535
|
-
"expert",
|
|
536
|
-
"full"
|
|
537
|
-
],
|
|
538
|
-
"tags": [
|
|
539
|
-
"modular-monolith",
|
|
540
|
-
"structure",
|
|
541
|
-
"modules"
|
|
542
|
-
],
|
|
543
|
-
"category": "Architecture"
|
|
544
|
-
},
|
|
545
|
-
"modular-monolith-boundaries": {
|
|
546
|
-
"path": "architecture/modular-monolith/boundaries.md",
|
|
547
|
-
"architectures": [
|
|
548
|
-
"modular-monolith"
|
|
549
|
-
],
|
|
550
|
-
"levels": [
|
|
551
|
-
"standard",
|
|
552
|
-
"expert",
|
|
553
|
-
"full"
|
|
554
|
-
],
|
|
555
|
-
"tags": [
|
|
556
|
-
"modular-monolith",
|
|
557
|
-
"boundaries",
|
|
558
|
-
"coupling",
|
|
559
|
-
"events"
|
|
560
|
-
],
|
|
561
|
-
"category": "Architecture"
|
|
562
|
-
},
|
|
563
|
-
"testing-unit-fundamentals": {
|
|
564
|
-
"path": "testing/unit-fundamentals.md",
|
|
565
|
-
"levels": [
|
|
566
|
-
"standard",
|
|
567
|
-
"expert",
|
|
568
|
-
"full"
|
|
569
|
-
],
|
|
570
|
-
"tags": [
|
|
571
|
-
"testing",
|
|
572
|
-
"unit-tests",
|
|
573
|
-
"aaa-pattern"
|
|
574
|
-
],
|
|
575
|
-
"category": "Testing"
|
|
576
|
-
},
|
|
577
|
-
"testing-unit-mocking": {
|
|
578
|
-
"path": "testing/unit-mocking.md",
|
|
579
|
-
"levels": [
|
|
580
|
-
"standard",
|
|
581
|
-
"expert",
|
|
582
|
-
"full"
|
|
583
|
-
],
|
|
584
|
-
"tags": [
|
|
585
|
-
"testing",
|
|
586
|
-
"mocking",
|
|
587
|
-
"test-doubles",
|
|
588
|
-
"stubs"
|
|
589
|
-
],
|
|
590
|
-
"category": "Testing"
|
|
591
|
-
},
|
|
592
|
-
"testing-integration": {
|
|
593
|
-
"path": "testing/integration.md",
|
|
594
|
-
"levels": [
|
|
595
|
-
"expert",
|
|
596
|
-
"full"
|
|
597
|
-
],
|
|
598
|
-
"tags": [
|
|
599
|
-
"testing",
|
|
600
|
-
"integration",
|
|
601
|
-
"database",
|
|
602
|
-
"api"
|
|
603
|
-
],
|
|
604
|
-
"category": "Testing"
|
|
605
|
-
},
|
|
606
|
-
"testing-basics": {
|
|
607
|
-
"path": "testing/basics.md",
|
|
608
|
-
"levels": [
|
|
609
|
-
"basic",
|
|
610
|
-
"standard",
|
|
611
|
-
"expert",
|
|
612
|
-
"full"
|
|
613
|
-
],
|
|
614
|
-
"tags": [
|
|
615
|
-
"testing",
|
|
616
|
-
"unit-tests",
|
|
617
|
-
"assertions",
|
|
618
|
-
"fundamentals"
|
|
619
|
-
],
|
|
620
|
-
"category": "Testing"
|
|
621
|
-
},
|
|
622
|
-
"security-injection": {
|
|
623
|
-
"path": "security/injection.md",
|
|
624
|
-
"levels": [
|
|
625
|
-
"basic",
|
|
626
|
-
"standard",
|
|
627
|
-
"expert",
|
|
628
|
-
"full"
|
|
629
|
-
],
|
|
630
|
-
"tags": [
|
|
631
|
-
"security",
|
|
632
|
-
"owasp",
|
|
633
|
-
"sql-injection",
|
|
634
|
-
"xss"
|
|
635
|
-
],
|
|
636
|
-
"category": "Security"
|
|
637
|
-
},
|
|
638
|
-
"security-auth-jwt": {
|
|
639
|
-
"path": "security/auth-jwt.md",
|
|
640
|
-
"levels": [
|
|
641
|
-
"standard",
|
|
642
|
-
"expert",
|
|
643
|
-
"full"
|
|
644
|
-
],
|
|
645
|
-
"tags": [
|
|
646
|
-
"security",
|
|
647
|
-
"auth",
|
|
648
|
-
"jwt",
|
|
649
|
-
"session",
|
|
650
|
-
"password"
|
|
651
|
-
],
|
|
652
|
-
"category": "Security"
|
|
653
|
-
},
|
|
654
|
-
"security-secrets": {
|
|
655
|
-
"path": "security/secrets.md",
|
|
656
|
-
"levels": [
|
|
657
|
-
"standard",
|
|
658
|
-
"expert",
|
|
659
|
-
"full"
|
|
660
|
-
],
|
|
661
|
-
"tags": [
|
|
662
|
-
"security",
|
|
663
|
-
"secrets",
|
|
664
|
-
"env",
|
|
665
|
-
"configuration"
|
|
666
|
-
],
|
|
667
|
-
"category": "Security"
|
|
668
|
-
},
|
|
669
|
-
"security-headers": {
|
|
670
|
-
"path": "security/headers.md",
|
|
671
|
-
"levels": [
|
|
672
|
-
"expert",
|
|
673
|
-
"full"
|
|
674
|
-
],
|
|
675
|
-
"tags": [
|
|
676
|
-
"security",
|
|
677
|
-
"headers",
|
|
678
|
-
"cors",
|
|
679
|
-
"csp",
|
|
680
|
-
"https"
|
|
681
|
-
],
|
|
682
|
-
"category": "Security"
|
|
683
|
-
},
|
|
684
|
-
"performance-basics": {
|
|
685
|
-
"path": "performance/basics.md",
|
|
686
|
-
"levels": [
|
|
687
|
-
"basic",
|
|
688
|
-
"standard",
|
|
689
|
-
"expert",
|
|
690
|
-
"full"
|
|
691
|
-
],
|
|
692
|
-
"tags": [
|
|
693
|
-
"performance",
|
|
694
|
-
"optimization",
|
|
695
|
-
"data-structures",
|
|
696
|
-
"n-plus-one",
|
|
697
|
-
"fundamentals"
|
|
698
|
-
],
|
|
699
|
-
"category": "Performance"
|
|
700
|
-
},
|
|
701
|
-
"performance-caching": {
|
|
702
|
-
"path": "performance/caching.md",
|
|
703
|
-
"levels": [
|
|
704
|
-
"expert",
|
|
705
|
-
"full"
|
|
706
|
-
],
|
|
707
|
-
"tags": [
|
|
708
|
-
"performance",
|
|
709
|
-
"caching",
|
|
710
|
-
"redis",
|
|
711
|
-
"memoization"
|
|
712
|
-
],
|
|
713
|
-
"category": "Performance"
|
|
714
|
-
},
|
|
715
|
-
"performance-async": {
|
|
716
|
-
"path": "performance/async.md",
|
|
717
|
-
"levels": [
|
|
718
|
-
"standard",
|
|
719
|
-
"expert",
|
|
720
|
-
"full"
|
|
721
|
-
],
|
|
722
|
-
"tags": [
|
|
723
|
-
"performance",
|
|
724
|
-
"async",
|
|
725
|
-
"parallel",
|
|
726
|
-
"batching"
|
|
727
|
-
],
|
|
728
|
-
"category": "Performance"
|
|
729
|
-
},
|
|
730
|
-
"database-basics": {
|
|
731
|
-
"path": "database/basics.md",
|
|
732
|
-
"levels": [
|
|
733
|
-
"basic",
|
|
734
|
-
"standard",
|
|
735
|
-
"expert",
|
|
736
|
-
"full"
|
|
737
|
-
],
|
|
738
|
-
"tags": [
|
|
739
|
-
"database",
|
|
740
|
-
"crud",
|
|
741
|
-
"sql",
|
|
742
|
-
"queries",
|
|
743
|
-
"fundamentals"
|
|
744
|
-
],
|
|
745
|
-
"category": "Database"
|
|
746
|
-
},
|
|
747
|
-
"database-schema": {
|
|
748
|
-
"path": "database/schema.md",
|
|
749
|
-
"levels": [
|
|
750
|
-
"standard",
|
|
751
|
-
"expert",
|
|
752
|
-
"full"
|
|
753
|
-
],
|
|
754
|
-
"datasources": [
|
|
755
|
-
"sql"
|
|
756
|
-
],
|
|
757
|
-
"tags": [
|
|
758
|
-
"database",
|
|
759
|
-
"schema",
|
|
760
|
-
"design",
|
|
761
|
-
"normalization"
|
|
762
|
-
],
|
|
763
|
-
"category": "Database"
|
|
764
|
-
},
|
|
765
|
-
"database-indexing": {
|
|
766
|
-
"path": "database/indexing.md",
|
|
767
|
-
"levels": [
|
|
768
|
-
"expert",
|
|
769
|
-
"full"
|
|
770
|
-
],
|
|
771
|
-
"datasources": [
|
|
772
|
-
"sql"
|
|
773
|
-
],
|
|
774
|
-
"tags": [
|
|
775
|
-
"database",
|
|
776
|
-
"indexing",
|
|
777
|
-
"performance",
|
|
778
|
-
"queries"
|
|
779
|
-
],
|
|
780
|
-
"category": "Database"
|
|
781
|
-
},
|
|
782
|
-
"api-basics": {
|
|
783
|
-
"path": "api/basics.md",
|
|
784
|
-
"levels": [
|
|
785
|
-
"basic",
|
|
786
|
-
"standard",
|
|
787
|
-
"expert",
|
|
788
|
-
"full"
|
|
789
|
-
],
|
|
790
|
-
"tags": [
|
|
791
|
-
"api",
|
|
792
|
-
"http",
|
|
793
|
-
"rest",
|
|
794
|
-
"status-codes",
|
|
795
|
-
"fundamentals"
|
|
796
|
-
],
|
|
797
|
-
"category": "API Design"
|
|
798
|
-
},
|
|
799
|
-
"api-rest": {
|
|
800
|
-
"path": "api/rest.md",
|
|
801
|
-
"levels": [
|
|
802
|
-
"standard",
|
|
803
|
-
"expert",
|
|
804
|
-
"full"
|
|
805
|
-
],
|
|
806
|
-
"tags": [
|
|
807
|
-
"api",
|
|
808
|
-
"rest",
|
|
809
|
-
"http",
|
|
810
|
-
"design"
|
|
811
|
-
],
|
|
812
|
-
"category": "API Design"
|
|
813
|
-
},
|
|
814
|
-
"api-pagination": {
|
|
815
|
-
"path": "api/pagination.md",
|
|
816
|
-
"levels": [
|
|
817
|
-
"standard",
|
|
818
|
-
"expert",
|
|
819
|
-
"full"
|
|
820
|
-
],
|
|
821
|
-
"tags": [
|
|
822
|
-
"api",
|
|
823
|
-
"pagination",
|
|
824
|
-
"cursor",
|
|
825
|
-
"offset"
|
|
826
|
-
],
|
|
827
|
-
"category": "API Design"
|
|
828
|
-
},
|
|
829
|
-
"code-style-naming": {
|
|
830
|
-
"path": "style/naming.md",
|
|
831
|
-
"levels": [
|
|
832
|
-
"basic",
|
|
833
|
-
"standard",
|
|
834
|
-
"expert",
|
|
835
|
-
"full"
|
|
836
|
-
],
|
|
837
|
-
"tags": [
|
|
838
|
-
"style",
|
|
839
|
-
"naming",
|
|
840
|
-
"conventions"
|
|
841
|
-
],
|
|
842
|
-
"category": "Code Style"
|
|
843
|
-
},
|
|
844
|
-
"code-style-organization": {
|
|
845
|
-
"path": "style/organization.md",
|
|
846
|
-
"levels": [
|
|
847
|
-
"standard",
|
|
848
|
-
"expert",
|
|
849
|
-
"full"
|
|
850
|
-
],
|
|
851
|
-
"tags": [
|
|
852
|
-
"style",
|
|
853
|
-
"organization",
|
|
854
|
-
"structure",
|
|
855
|
-
"srp"
|
|
856
|
-
],
|
|
857
|
-
"category": "Code Style"
|
|
858
|
-
},
|
|
859
|
-
"error-handling-strategy": {
|
|
860
|
-
"path": "error-handling/strategy.md",
|
|
861
|
-
"levels": [
|
|
862
|
-
"standard",
|
|
863
|
-
"expert",
|
|
864
|
-
"full"
|
|
865
|
-
],
|
|
866
|
-
"tags": [
|
|
867
|
-
"errors",
|
|
868
|
-
"exceptions",
|
|
869
|
-
"resilience",
|
|
870
|
-
"retry"
|
|
871
|
-
],
|
|
872
|
-
"category": "Error Handling"
|
|
873
|
-
},
|
|
874
|
-
"error-handling-basics": {
|
|
875
|
-
"path": "error-handling/basics.md",
|
|
876
|
-
"levels": [
|
|
877
|
-
"basic",
|
|
878
|
-
"standard",
|
|
879
|
-
"expert",
|
|
880
|
-
"full"
|
|
881
|
-
],
|
|
882
|
-
"tags": [
|
|
883
|
-
"errors",
|
|
884
|
-
"exceptions",
|
|
885
|
-
"try-catch",
|
|
886
|
-
"fundamentals"
|
|
887
|
-
],
|
|
888
|
-
"category": "Error Handling"
|
|
889
|
-
},
|
|
890
|
-
"solid-principles": {
|
|
891
|
-
"path": "architecture/solid/principles.md",
|
|
892
|
-
"levels": [
|
|
893
|
-
"standard",
|
|
894
|
-
"expert",
|
|
895
|
-
"full"
|
|
896
|
-
],
|
|
897
|
-
"tags": [
|
|
898
|
-
"solid",
|
|
899
|
-
"srp",
|
|
900
|
-
"ocp",
|
|
901
|
-
"lsp",
|
|
902
|
-
"isp",
|
|
903
|
-
"dip",
|
|
904
|
-
"design-principles"
|
|
905
|
-
],
|
|
906
|
-
"category": "Architecture"
|
|
907
|
-
},
|
|
908
|
-
"clean-architecture-layers": {
|
|
909
|
-
"path": "architecture/clean-architecture/layers.md",
|
|
910
|
-
"architectures": [
|
|
911
|
-
"clean-architecture"
|
|
912
|
-
],
|
|
913
|
-
"levels": [
|
|
914
|
-
"standard",
|
|
915
|
-
"expert",
|
|
916
|
-
"full"
|
|
917
|
-
],
|
|
918
|
-
"tags": [
|
|
919
|
-
"clean-architecture",
|
|
920
|
-
"layers",
|
|
921
|
-
"dependency-rule",
|
|
922
|
-
"use-cases"
|
|
923
|
-
],
|
|
924
|
-
"category": "Architecture"
|
|
925
|
-
},
|
|
926
|
-
"ddd-tactical": {
|
|
927
|
-
"path": "architecture/ddd/tactical.md",
|
|
928
|
-
"architectures": [
|
|
929
|
-
"ddd"
|
|
930
|
-
],
|
|
931
|
-
"levels": [
|
|
932
|
-
"standard",
|
|
933
|
-
"expert",
|
|
934
|
-
"full"
|
|
935
|
-
],
|
|
936
|
-
"tags": [
|
|
937
|
-
"ddd",
|
|
938
|
-
"entities",
|
|
939
|
-
"value-objects",
|
|
940
|
-
"aggregates",
|
|
941
|
-
"domain-events"
|
|
942
|
-
],
|
|
943
|
-
"category": "Architecture"
|
|
944
|
-
},
|
|
945
|
-
"ddd-strategic": {
|
|
946
|
-
"path": "architecture/ddd/strategic.md",
|
|
947
|
-
"architectures": [
|
|
948
|
-
"ddd"
|
|
949
|
-
],
|
|
950
|
-
"levels": [
|
|
951
|
-
"expert",
|
|
952
|
-
"full"
|
|
953
|
-
],
|
|
954
|
-
"tags": [
|
|
955
|
-
"ddd",
|
|
956
|
-
"bounded-context",
|
|
957
|
-
"ubiquitous-language",
|
|
958
|
-
"context-mapping"
|
|
959
|
-
],
|
|
960
|
-
"category": "Architecture"
|
|
961
|
-
},
|
|
962
|
-
"event-driven-patterns": {
|
|
963
|
-
"path": "architecture/event-driven/patterns.md",
|
|
964
|
-
"architectures": [
|
|
965
|
-
"event-driven"
|
|
966
|
-
],
|
|
967
|
-
"levels": [
|
|
968
|
-
"expert",
|
|
969
|
-
"full"
|
|
970
|
-
],
|
|
971
|
-
"tags": [
|
|
972
|
-
"event-sourcing",
|
|
973
|
-
"cqrs",
|
|
974
|
-
"saga",
|
|
975
|
-
"event-driven"
|
|
976
|
-
],
|
|
977
|
-
"category": "Architecture"
|
|
978
|
-
},
|
|
979
|
-
"event-driven-messaging": {
|
|
980
|
-
"path": "architecture/event-driven/messaging.md",
|
|
981
|
-
"architectures": [
|
|
982
|
-
"event-driven"
|
|
983
|
-
],
|
|
984
|
-
"levels": [
|
|
985
|
-
"standard",
|
|
986
|
-
"expert",
|
|
987
|
-
"full"
|
|
988
|
-
],
|
|
989
|
-
"tags": [
|
|
990
|
-
"messaging",
|
|
991
|
-
"queues",
|
|
992
|
-
"outbox",
|
|
993
|
-
"delivery"
|
|
994
|
-
],
|
|
995
|
-
"category": "Architecture"
|
|
996
|
-
},
|
|
997
|
-
"layered-architecture": {
|
|
998
|
-
"path": "architecture/layered/layers.md",
|
|
999
|
-
"architectures": [
|
|
1000
|
-
"layered"
|
|
1001
|
-
],
|
|
1002
|
-
"levels": [
|
|
1003
|
-
"standard",
|
|
1004
|
-
"expert",
|
|
1005
|
-
"full"
|
|
1006
|
-
],
|
|
1007
|
-
"tags": [
|
|
1008
|
-
"layered",
|
|
1009
|
-
"presentation",
|
|
1010
|
-
"domain",
|
|
1011
|
-
"data-access"
|
|
1012
|
-
],
|
|
1013
|
-
"category": "Architecture"
|
|
1014
|
-
},
|
|
1015
|
-
"serverless-patterns": {
|
|
1016
|
-
"path": "architecture/serverless/patterns.md",
|
|
1017
|
-
"architectures": [
|
|
1018
|
-
"serverless"
|
|
1019
|
-
],
|
|
1020
|
-
"levels": [
|
|
1021
|
-
"standard",
|
|
1022
|
-
"expert",
|
|
1023
|
-
"full"
|
|
1024
|
-
],
|
|
1025
|
-
"tags": [
|
|
1026
|
-
"serverless",
|
|
1027
|
-
"faas",
|
|
1028
|
-
"lambda",
|
|
1029
|
-
"cold-start"
|
|
1030
|
-
],
|
|
1031
|
-
"category": "Architecture"
|
|
1032
|
-
},
|
|
1033
|
-
"serverless-best-practices": {
|
|
1034
|
-
"path": "architecture/serverless/best-practices.md",
|
|
1035
|
-
"architectures": [
|
|
1036
|
-
"serverless"
|
|
1037
|
-
],
|
|
1038
|
-
"levels": [
|
|
1039
|
-
"standard",
|
|
1040
|
-
"expert",
|
|
1041
|
-
"full"
|
|
1042
|
-
],
|
|
1043
|
-
"tags": [
|
|
1044
|
-
"serverless",
|
|
1045
|
-
"optimization",
|
|
1046
|
-
"security",
|
|
1047
|
-
"monitoring"
|
|
1048
|
-
],
|
|
1049
|
-
"category": "Architecture"
|
|
1050
|
-
},
|
|
1051
|
-
"hexagonal-architecture": {
|
|
1052
|
-
"path": "architecture/hexagonal/ports-adapters.md",
|
|
1053
|
-
"architectures": [
|
|
1054
|
-
"hexagonal"
|
|
1055
|
-
],
|
|
1056
|
-
"levels": [
|
|
1057
|
-
"standard",
|
|
1058
|
-
"expert",
|
|
1059
|
-
"full"
|
|
1060
|
-
],
|
|
1061
|
-
"tags": [
|
|
1062
|
-
"hexagonal",
|
|
1063
|
-
"ports-adapters",
|
|
1064
|
-
"dependency-inversion",
|
|
1065
|
-
"clean-code"
|
|
1066
|
-
],
|
|
1067
|
-
"category": "Architecture"
|
|
1068
|
-
},
|
|
1069
|
-
"gui-architecture": {
|
|
1070
|
-
"path": "architecture/gui/patterns.md",
|
|
1071
|
-
"levels": [
|
|
1072
|
-
"standard",
|
|
1073
|
-
"expert",
|
|
1074
|
-
"full"
|
|
1075
|
-
],
|
|
1076
|
-
"tags": [
|
|
1077
|
-
"gui",
|
|
1078
|
-
"mvc",
|
|
1079
|
-
"mvp",
|
|
1080
|
-
"mvvm",
|
|
1081
|
-
"component-architecture"
|
|
1082
|
-
],
|
|
1083
|
-
"category": "Architecture"
|
|
1084
|
-
},
|
|
1085
|
-
"feature-toggles": {
|
|
1086
|
-
"path": "architecture/feature-toggles/patterns.md",
|
|
1087
|
-
"levels": [
|
|
1088
|
-
"standard",
|
|
1089
|
-
"expert",
|
|
1090
|
-
"full"
|
|
1091
|
-
],
|
|
1092
|
-
"tags": [
|
|
1093
|
-
"feature-flags",
|
|
1094
|
-
"release-toggles",
|
|
1095
|
-
"ab-testing"
|
|
1096
|
-
],
|
|
1097
|
-
"category": "Architecture"
|
|
1098
|
-
},
|
|
1099
|
-
"devops-ci-cd": {
|
|
1100
|
-
"path": "devops/ci-cd.md",
|
|
1101
|
-
"levels": [
|
|
1102
|
-
"standard",
|
|
1103
|
-
"expert",
|
|
1104
|
-
"full"
|
|
1105
|
-
],
|
|
1106
|
-
"tags": [
|
|
1107
|
-
"devops",
|
|
1108
|
-
"ci",
|
|
1109
|
-
"cd",
|
|
1110
|
-
"deployment",
|
|
1111
|
-
"pipelines"
|
|
1112
|
-
],
|
|
1113
|
-
"category": "DevOps"
|
|
1114
|
-
},
|
|
1115
|
-
"devops-practices": {
|
|
1116
|
-
"path": "devops/practices.md",
|
|
1117
|
-
"levels": [
|
|
1118
|
-
"expert",
|
|
1119
|
-
"full"
|
|
1120
|
-
],
|
|
1121
|
-
"tags": [
|
|
1122
|
-
"devops",
|
|
1123
|
-
"infrastructure",
|
|
1124
|
-
"observability",
|
|
1125
|
-
"containers"
|
|
1126
|
-
],
|
|
1127
|
-
"category": "DevOps"
|
|
1128
|
-
},
|
|
1129
|
-
"devops-observability": {
|
|
1130
|
-
"path": "devops/observability.md",
|
|
1131
|
-
"levels": [
|
|
1132
|
-
"standard",
|
|
1133
|
-
"expert",
|
|
1134
|
-
"full"
|
|
1135
|
-
],
|
|
1136
|
-
"tags": [
|
|
1137
|
-
"devops",
|
|
1138
|
-
"observability",
|
|
1139
|
-
"logging",
|
|
1140
|
-
"metrics",
|
|
1141
|
-
"tracing"
|
|
1142
|
-
],
|
|
1143
|
-
"category": "DevOps"
|
|
1144
|
-
},
|
|
1145
|
-
"practices-planning": {
|
|
1146
|
-
"path": "practices/planning.md",
|
|
1147
|
-
"levels": [
|
|
1148
|
-
"standard",
|
|
1149
|
-
"expert",
|
|
1150
|
-
"full"
|
|
1151
|
-
],
|
|
1152
|
-
"tags": [
|
|
1153
|
-
"planning",
|
|
1154
|
-
"phases",
|
|
1155
|
-
"communication",
|
|
1156
|
-
"requirements",
|
|
1157
|
-
"approval"
|
|
1158
|
-
],
|
|
1159
|
-
"category": "Best Practices"
|
|
1160
|
-
},
|
|
1161
|
-
"practices-documentation": {
|
|
1162
|
-
"path": "practices/documentation.md",
|
|
1163
|
-
"levels": [
|
|
1164
|
-
"standard",
|
|
1165
|
-
"expert",
|
|
1166
|
-
"full"
|
|
1167
|
-
],
|
|
1168
|
-
"tags": [
|
|
1169
|
-
"documentation",
|
|
1170
|
-
"organization",
|
|
1171
|
-
"memory-lane",
|
|
1172
|
-
"context",
|
|
1173
|
-
"structure"
|
|
1174
|
-
],
|
|
1175
|
-
"category": "Best Practices"
|
|
1176
|
-
},
|
|
1177
|
-
"practices-code-review": {
|
|
1178
|
-
"path": "practices/code-review.md",
|
|
1179
|
-
"levels": [
|
|
1180
|
-
"standard",
|
|
1181
|
-
"expert",
|
|
1182
|
-
"full"
|
|
1183
|
-
],
|
|
1184
|
-
"tags": [
|
|
1185
|
-
"code-review",
|
|
1186
|
-
"pr",
|
|
1187
|
-
"feedback",
|
|
1188
|
-
"collaboration"
|
|
1189
|
-
],
|
|
1190
|
-
"category": "Best Practices"
|
|
1191
|
-
},
|
|
1192
|
-
"practices-refactoring": {
|
|
1193
|
-
"path": "practices/refactoring.md",
|
|
1194
|
-
"levels": [
|
|
1195
|
-
"standard",
|
|
1196
|
-
"expert",
|
|
1197
|
-
"full"
|
|
1198
|
-
],
|
|
1199
|
-
"tags": [
|
|
1200
|
-
"refactoring",
|
|
1201
|
-
"code-smells",
|
|
1202
|
-
"clean-code"
|
|
1203
|
-
],
|
|
1204
|
-
"category": "Best Practices"
|
|
1205
|
-
},
|
|
1206
|
-
"practices-version-control": {
|
|
1207
|
-
"path": "practices/version-control.md",
|
|
1208
|
-
"levels": [
|
|
1209
|
-
"basic",
|
|
1210
|
-
"standard",
|
|
1211
|
-
"expert",
|
|
1212
|
-
"full"
|
|
1213
|
-
],
|
|
1214
|
-
"tags": [
|
|
1215
|
-
"git",
|
|
1216
|
-
"branching",
|
|
1217
|
-
"commits",
|
|
1218
|
-
"version-control"
|
|
1219
|
-
],
|
|
1220
|
-
"category": "Best Practices"
|
|
1221
|
-
},
|
|
1222
|
-
"api-versioning": {
|
|
1223
|
-
"path": "api/versioning.md",
|
|
1224
|
-
"levels": [
|
|
1225
|
-
"standard",
|
|
1226
|
-
"expert",
|
|
1227
|
-
"full"
|
|
1228
|
-
],
|
|
1229
|
-
"tags": [
|
|
1230
|
-
"api",
|
|
1231
|
-
"versioning",
|
|
1232
|
-
"deprecation",
|
|
1233
|
-
"backwards-compatibility"
|
|
1234
|
-
],
|
|
1235
|
-
"category": "API Design"
|
|
1236
|
-
},
|
|
1237
|
-
"performance-caching-strategies": {
|
|
1238
|
-
"path": "performance/caching-strategies.md",
|
|
1239
|
-
"levels": [
|
|
1240
|
-
"expert",
|
|
1241
|
-
"full"
|
|
1242
|
-
],
|
|
1243
|
-
"tags": [
|
|
1244
|
-
"caching",
|
|
1245
|
-
"cache-aside",
|
|
1246
|
-
"write-through",
|
|
1247
|
-
"invalidation"
|
|
1248
|
-
],
|
|
1249
|
-
"category": "Performance"
|
|
1250
|
-
},
|
|
1251
|
-
"database-design-patterns": {
|
|
1252
|
-
"path": "database/design-patterns.md",
|
|
1253
|
-
"levels": [
|
|
1254
|
-
"standard",
|
|
1255
|
-
"expert",
|
|
1256
|
-
"full"
|
|
1257
|
-
],
|
|
1258
|
-
"datasources": [
|
|
1259
|
-
"sql"
|
|
1260
|
-
],
|
|
1261
|
-
"tags": [
|
|
1262
|
-
"database",
|
|
1263
|
-
"normalization",
|
|
1264
|
-
"denormalization",
|
|
1265
|
-
"soft-deletes"
|
|
1266
|
-
],
|
|
1267
|
-
"category": "Database"
|
|
1268
|
-
},
|
|
1269
|
-
"database-nosql": {
|
|
1270
|
-
"path": "database/nosql.md",
|
|
1271
|
-
"levels": [
|
|
1272
|
-
"standard",
|
|
1273
|
-
"expert",
|
|
1274
|
-
"full"
|
|
1275
|
-
],
|
|
1276
|
-
"datasources": [
|
|
1277
|
-
"nosql"
|
|
1278
|
-
],
|
|
1279
|
-
"tags": [
|
|
1280
|
-
"database",
|
|
1281
|
-
"nosql",
|
|
1282
|
-
"mongodb",
|
|
1283
|
-
"dynamodb",
|
|
1284
|
-
"redis"
|
|
1285
|
-
],
|
|
1286
|
-
"category": "Database"
|
|
1287
|
-
},
|
|
1288
|
-
"patterns-base": {
|
|
1289
|
-
"path": "patterns/base-patterns.md",
|
|
1290
|
-
"levels": [
|
|
1291
|
-
"standard",
|
|
1292
|
-
"expert",
|
|
1293
|
-
"full"
|
|
1294
|
-
],
|
|
1295
|
-
"tags": [
|
|
1296
|
-
"value-object",
|
|
1297
|
-
"money",
|
|
1298
|
-
"special-case",
|
|
1299
|
-
"registry",
|
|
1300
|
-
"plugin"
|
|
1301
|
-
],
|
|
1302
|
-
"category": "Design Patterns"
|
|
1303
|
-
},
|
|
1304
|
-
"patterns-concurrency": {
|
|
1305
|
-
"path": "patterns/concurrency.md",
|
|
1306
|
-
"levels": [
|
|
1307
|
-
"expert",
|
|
1308
|
-
"full"
|
|
1309
|
-
],
|
|
1310
|
-
"tags": [
|
|
1311
|
-
"concurrency",
|
|
1312
|
-
"optimistic-lock",
|
|
1313
|
-
"pessimistic-lock",
|
|
1314
|
-
"locking"
|
|
1315
|
-
],
|
|
1316
|
-
"category": "Design Patterns"
|
|
1317
|
-
},
|
|
1318
|
-
"patterns-data-access": {
|
|
1319
|
-
"path": "patterns/data-access.md",
|
|
1320
|
-
"levels": [
|
|
1321
|
-
"standard",
|
|
1322
|
-
"expert",
|
|
1323
|
-
"full"
|
|
1324
|
-
],
|
|
1325
|
-
"tags": [
|
|
1326
|
-
"repository",
|
|
1327
|
-
"data-mapper",
|
|
1328
|
-
"active-record",
|
|
1329
|
-
"unit-of-work"
|
|
1330
|
-
],
|
|
1331
|
-
"category": "Design Patterns"
|
|
1332
|
-
},
|
|
1333
|
-
"patterns-distribution": {
|
|
1334
|
-
"path": "patterns/distribution.md",
|
|
1335
|
-
"levels": [
|
|
1336
|
-
"expert",
|
|
1337
|
-
"full"
|
|
1338
|
-
],
|
|
1339
|
-
"tags": [
|
|
1340
|
-
"remote-facade",
|
|
1341
|
-
"dto",
|
|
1342
|
-
"gateway",
|
|
1343
|
-
"service-stub"
|
|
1344
|
-
],
|
|
1345
|
-
"category": "Design Patterns"
|
|
1346
|
-
},
|
|
1347
|
-
"patterns-domain-logic": {
|
|
1348
|
-
"path": "patterns/domain-logic.md",
|
|
1349
|
-
"levels": [
|
|
1350
|
-
"standard",
|
|
1351
|
-
"expert",
|
|
1352
|
-
"full"
|
|
1353
|
-
],
|
|
1354
|
-
"tags": [
|
|
1355
|
-
"transaction-script",
|
|
1356
|
-
"domain-model",
|
|
1357
|
-
"service-layer"
|
|
1358
|
-
],
|
|
1359
|
-
"category": "Design Patterns"
|
|
1360
|
-
},
|
|
1361
|
-
"patterns-gof": {
|
|
1362
|
-
"path": "patterns/gof.md",
|
|
1363
|
-
"levels": [
|
|
1364
|
-
"standard",
|
|
1365
|
-
"expert",
|
|
1366
|
-
"full"
|
|
1367
|
-
],
|
|
1368
|
-
"tags": [
|
|
1369
|
-
"gang-of-four",
|
|
1370
|
-
"factory",
|
|
1371
|
-
"strategy",
|
|
1372
|
-
"observer",
|
|
1373
|
-
"decorator"
|
|
1374
|
-
],
|
|
1375
|
-
"category": "Design Patterns"
|
|
1376
|
-
}
|
|
1377
|
-
},
|
|
1378
|
-
"guidelines": {
|
|
1379
|
-
"api/basics.md": "# API Basics\n\n## HTTP Methods\n\nUse the right method for each operation:\n\n| Method | Purpose | Example |\n|--------|---------|---------|\n| GET | Read data | Get list of users |\n| POST | Create new resource | Create a new user |\n| PUT | Replace entire resource | Update all user fields |\n| PATCH | Update part of resource | Update user's email only |\n| DELETE | Remove resource | Delete a user |\n\n## GET - Reading Data\n\n```pseudocode\n// Get all items\nroute GET \"/api/users\":\n users = getAllUsers()\n return JSON(users)\n\n// Get single item by ID\nroute GET \"/api/users/:id\":\n user = getUserById(params.id)\n if user is null:\n return status 404, JSON({ error: \"User not found\" })\n return JSON(user)\n```\n\n## POST - Creating Data\n\n```pseudocode\nroute POST \"/api/users\":\n name = request.body.name\n email = request.body.email\n\n // Validate input\n if name is empty or email is empty:\n return status 400, JSON({ error: \"Name and email required\" })\n\n newUser = createUser({ name, email })\n\n // Return 201 Created with new resource\n return status 201, JSON(newUser)\n```\n\n## PUT - Replacing Data\n\n```pseudocode\nroute PUT \"/api/users/:id\":\n id = params.id\n name = request.body.name\n email = request.body.email\n\n user = getUserById(id)\n if user is null:\n return status 404, JSON({ error: \"User not found\" })\n\n updated = replaceUser(id, { name, email })\n return JSON(updated)\n```\n\n## PATCH - Updating Data\n\n```pseudocode\nroute PATCH \"/api/users/:id\":\n id = params.id\n updates = request.body // Only fields to update\n\n user = getUserById(id)\n if user is null:\n return status 404, JSON({ error: \"User not found\" })\n\n updated = updateUser(id, updates)\n return JSON(updated)\n```\n\n## DELETE - Removing Data\n\n```pseudocode\nroute DELETE \"/api/users/:id\":\n id = params.id\n\n user = getUserById(id)\n if user is null:\n return status 404, JSON({ error: \"User not found\" })\n\n deleteUser(id)\n\n // 204 No Content - successful deletion\n return status 204\n```\n\n## HTTP Status Codes\n\n### Success Codes (2xx)\n\n```pseudocode\n// 200 OK - Request succeeded\nreturn status 200, JSON(data)\n\n// 201 Created - New resource created\nreturn status 201, JSON(newResource)\n\n// 204 No Content - Success with no response body\nreturn status 204\n```\n\n### Client Error Codes (4xx)\n\n```pseudocode\n// 400 Bad Request - Invalid input\nreturn status 400, JSON({ error: \"Invalid email format\" })\n\n// 401 Unauthorized - Not authenticated\nreturn status 401, JSON({ error: \"Login required\" })\n\n// 403 Forbidden - Authenticated but not allowed\nreturn status 403, JSON({ error: \"Admin access required\" })\n\n// 404 Not Found - Resource doesn't exist\nreturn status 404, JSON({ error: \"User not found\" })\n\n// 409 Conflict - Resource already exists\nreturn status 409, JSON({ error: \"Email already registered\" })\n```\n\n### Server Error Codes (5xx)\n\n```pseudocode\n// 500 Internal Server Error - Unexpected error\nreturn status 500, JSON({ error: \"Internal server error\" })\n\n// 503 Service Unavailable - Temporary issue\nreturn status 503, JSON({ error: \"Database unavailable\" })\n```\n\n## URL Structure\n\nUse clear, hierarchical URLs:\n\n```\n✅ Good\nGET /api/users # List all users\nGET /api/users/123 # Get user 123\nPOST /api/users # Create user\nGET /api/users/123/posts # Get posts by user 123\n\n❌ Bad\nGET /api/getUsers\nPOST /api/createUser\nGET /api/user?id=123\n```\n\n## Request and Response Format\n\n### JSON Request Body\n\n```\n// Client sends\nPOST /api/users\nContent-Type: application/json\n\n{\n \"name\": \"Alice\",\n \"email\": \"alice@example.com\"\n}\n```\n\n### JSON Response\n\n```\n// Server responds\nHTTP/1.1 201 Created\nContent-Type: application/json\n\n{\n \"id\": 123,\n \"name\": \"Alice\",\n \"email\": \"alice@example.com\",\n \"createdAt\": \"2024-01-15T10:30:00Z\"\n}\n```\n\n## Query Parameters\n\nUse query parameters for filtering, sorting, and pagination:\n\n```pseudocode\n// Filter by status\n// GET /api/orders?status=pending\nroute GET \"/api/orders\":\n status = query.status\n orders = getOrders({ status })\n return JSON(orders)\n\n// Sort by field\n// GET /api/users?sort=name\n\n// Pagination\n// GET /api/users?page=2&limit=20\n```\n\n## Error Responses\n\nAlways return consistent error format:\n\n```pseudocode\n// ✅ Good: Structured error\nreturn status 400, JSON({\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"Invalid input\",\n details: {\n email: \"Email format is invalid\"\n }\n }\n})\n\n// ❌ Bad: Inconsistent\nreturn status 400, \"Bad request\"\nreturn status 400, JSON({ msg: \"Error\" })\n```\n\n## Best Practices\n\n1. **Use correct HTTP methods** - GET for reading, POST for creating, etc.\n2. **Use appropriate status codes** - 200 for success, 404 for not found, etc.\n3. **Return JSON** - Standard format for APIs\n4. **Validate input** - Check data before processing\n5. **Handle errors** - Return clear error messages\n\n```pseudocode\n// Complete example\nroute POST \"/api/products\":\n name = request.body.name\n price = request.body.price\n\n // Validate\n if name is empty or price is empty:\n return status 400, JSON({\n error: \"Name and price are required\"\n })\n\n if price < 0:\n return status 400, JSON({\n error: \"Price cannot be negative\"\n })\n\n // Check for duplicates\n if productExists(name):\n return status 409, JSON({\n error: \"Product already exists\"\n })\n\n // Create\n product = createProduct({ name, price })\n\n // Return success\n return status 201, JSON(product)\n```\n\n## Common Mistakes\n\n```pseudocode\n// ❌ Wrong method for operation\nroute GET \"/api/users/delete/:id\" // Should be DELETE\n\n// ❌ Wrong status code\nroute POST \"/api/users\":\n user = createUser(body)\n return status 200, JSON(user) // Should be 201\n\n// ❌ Not handling missing resources\nroute GET \"/api/users/:id\":\n user = getUserById(params.id)\n return JSON(user) // What if user is null?\n\n// ✅ Correct\nroute DELETE \"/api/users/:id\"\n\nroute POST \"/api/users\":\n user = createUser(body)\n return status 201, JSON(user)\n\nroute GET \"/api/users/:id\":\n user = getUserById(params.id)\n if user is null:\n return status 404, JSON({ error: \"User not found\" })\n return JSON(user)\n```\n",
|
|
1380
|
-
"api/index.md": "# API Design Guidelines\n\nThis directory contains REST API design patterns.\n\n## Available Chunks\n\n- **rest.md** - Resource-oriented design, HTTP methods, status codes\n- **pagination.md** - Offset-based, cursor-based, HATEOAS links\n",
|
|
1381
|
-
"api/pagination.md": "# API Pagination\n\n## Always Paginate Collections\n\n```typescript\n// ✅ Paginated endpoint\napp.get('/api/v1/books', async (req, res) => {\n const page = parseInt(req.query.page as string) || 1;\n const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);\n\n const { data, total } = await bookService.findAll({ page, limit });\n\n res.json({\n data,\n pagination: {\n page,\n limit,\n total,\n totalPages: Math.ceil(total / limit),\n hasNext: page * limit < total,\n hasPrevious: page > 1\n }\n });\n});\n```\n\n## Offset-Based Pagination\n\n```typescript\n// Simple but has issues with large datasets\nGET /api/v1/books?page=1&limit=20\nGET /api/v1/books?page=2&limit=20\n\n// Implementation\nconst getBooks = async (page: number, limit: number) => {\n const offset = (page - 1) * limit;\n\n const [data, total] = await Promise.all([\n db.query('SELECT * FROM books ORDER BY id LIMIT ? OFFSET ?', [limit, offset]),\n db.query('SELECT COUNT(*) FROM books')\n ]);\n\n return { data, total };\n};\n```\n\n## Cursor-Based Pagination\n\n```typescript\n// Better for large datasets and real-time data\nGET /api/v1/books?cursor=eyJpZCI6MTIzfQ&limit=20\n\n// Response includes next cursor\n{\n \"data\": [...],\n \"pagination\": {\n \"nextCursor\": \"eyJpZCI6MTQzfQ\",\n \"hasMore\": true\n }\n}\n\n// Implementation\nconst getBooks = async (cursor: string | null, limit: number) => {\n let query = 'SELECT * FROM books';\n\n if (cursor) {\n const { id } = decodeCursor(cursor);\n query += ` WHERE id > ${id}`;\n }\n\n query += ` ORDER BY id LIMIT ${limit + 1}`;\n const data = await db.query(query);\n\n const hasMore = data.length > limit;\n const items = hasMore ? data.slice(0, limit) : data;\n\n return {\n data: items,\n pagination: {\n nextCursor: hasMore ? encodeCursor({ id: items[items.length - 1].id }) : null,\n hasMore\n }\n };\n};\n```\n\n## Keyset Pagination\n\n```sql\n-- Most efficient for large tables\n-- First page\nSELECT * FROM products\nORDER BY created_at DESC, id DESC\nLIMIT 20;\n\n-- Next page (using last item's values)\nSELECT * FROM products\nWHERE (created_at, id) < ('2024-01-15 10:00:00', 12345)\nORDER BY created_at DESC, id DESC\nLIMIT 20;\n```\n\n## HATEOAS Links\n\n```typescript\n// Include navigation links\n{\n \"data\": [...],\n \"pagination\": {\n \"page\": 2,\n \"limit\": 20,\n \"total\": 150\n },\n \"links\": {\n \"self\": \"/api/v1/books?page=2&limit=20\",\n \"first\": \"/api/v1/books?page=1&limit=20\",\n \"prev\": \"/api/v1/books?page=1&limit=20\",\n \"next\": \"/api/v1/books?page=3&limit=20\",\n \"last\": \"/api/v1/books?page=8&limit=20\"\n }\n}\n```\n\n## Pagination Best Practices\n\n```typescript\n// ✅ Set reasonable defaults and limits\nconst page = parseInt(req.query.page) || 1;\nconst limit = Math.min(parseInt(req.query.limit) || 20, 100);\n\n// ✅ Include total count (when practical)\nconst total = await db.count('books');\n\n// ✅ Use consistent response structure\n{\n \"data\": [],\n \"pagination\": { ... }\n}\n\n// ❌ Don't return unlimited results\n// ❌ Don't allow page < 1 or limit < 1\n```\n",
|
|
1382
|
-
"api/rest.md": "# REST API Design\n\n## Resource-Oriented URLs\n\n```\n✅ Good (nouns, plural)\nGET /api/v1/books # List books\nGET /api/v1/books/123 # Get book\nPOST /api/v1/books # Create book\nPUT /api/v1/books/123 # Replace book\nPATCH /api/v1/books/123 # Update book\nDELETE /api/v1/books/123 # Delete book\n\n❌ Bad (verbs, actions)\nPOST /api/v1/createBook\nGET /api/v1/getBookById/123\nPOST /api/v1/updateBook/123\n```\n\n## HTTP Methods\n\n```typescript\n// GET - Read (safe, idempotent)\napp.get('/api/v1/users/:id', async (req, res) => {\n const user = await userService.findById(req.params.id);\n res.json({ data: user });\n});\n\n// POST - Create (not idempotent)\napp.post('/api/v1/users', async (req, res) => {\n const user = await userService.create(req.body);\n res.status(201)\n .location(`/api/v1/users/${user.id}`)\n .json({ data: user });\n});\n\n// PUT - Replace entire resource (idempotent)\napp.put('/api/v1/users/:id', async (req, res) => {\n const user = await userService.replace(req.params.id, req.body);\n res.json({ data: user });\n});\n\n// PATCH - Partial update (idempotent)\napp.patch('/api/v1/users/:id', async (req, res) => {\n const user = await userService.update(req.params.id, req.body);\n res.json({ data: user });\n});\n\n// DELETE - Remove (idempotent)\napp.delete('/api/v1/users/:id', async (req, res) => {\n await userService.delete(req.params.id);\n res.status(204).end();\n});\n```\n\n## Status Codes\n\n```typescript\n// Success\n200 OK // GET, PUT, PATCH succeeded\n201 Created // POST succeeded\n204 No Content // DELETE succeeded\n\n// Client errors\n400 Bad Request // Validation failed\n401 Unauthorized // Not authenticated\n403 Forbidden // Authenticated but not allowed\n404 Not Found // Resource doesn't exist\n409 Conflict // Duplicate, version conflict\n422 Unprocessable // Business rule violation\n\n// Server errors\n500 Internal Server Error\n```\n\n## Response Format\n\n```typescript\n// Single resource\n{\n \"data\": {\n \"id\": 123,\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}\n\n// Collection with pagination\n{\n \"data\": [\n { \"id\": 1, \"name\": \"Item 1\" },\n { \"id\": 2, \"name\": \"Item 2\" }\n ],\n \"pagination\": {\n \"page\": 1,\n \"limit\": 20,\n \"total\": 150,\n \"totalPages\": 8\n }\n}\n\n// Error response\n{\n \"error\": {\n \"code\": \"VALIDATION_ERROR\",\n \"message\": \"The request contains invalid data\",\n \"details\": [\n { \"field\": \"email\", \"message\": \"Invalid email format\" }\n ]\n }\n}\n```\n\n## Hierarchical Resources\n\n```\n✅ Limit nesting to 2-3 levels\nGET /api/v1/authors/456/books # Books by author\nGET /api/v1/orders/789/items # Items in order\n\n❌ Too deep\nGET /api/v1/publishers/1/authors/2/books/3/reviews/4\n\n✅ Use query parameters instead\nGET /api/v1/reviews?bookId=3\n```\n\n## API Versioning\n\n```\n✅ Always version from the start\n/api/v1/books\n/api/v2/books\n\n❌ No version\n/api/books\n```\n",
|
|
1383
|
-
"api/versioning.md": "# API Versioning\n\n## Versioning Strategies\n\n### URL Path Versioning\n```\nGET /api/v1/users\nGET /api/v2/users\n```\n\n### Header Versioning\n```\nGET /api/users\nAccept: application/vnd.api+json; version=2\n```\n\n### Query Parameter\n```\nGET /api/users?version=2\n```\n\n## Implementation\n\n```typescript\n// URL path versioning\napp.use('/api/v1', v1Router);\napp.use('/api/v2', v2Router);\n\n// Header versioning middleware\nfunction versionMiddleware(req, res, next) {\n const version = req.headers['api-version'] || '1';\n req.apiVersion = parseInt(version);\n next();\n}\n\napp.get('/users', versionMiddleware, (req, res) => {\n if (req.apiVersion >= 2) {\n return handleV2(req, res);\n }\n return handleV1(req, res);\n});\n```\n\n## Deprecation Strategy\n\n```typescript\n// Add deprecation headers\nres.setHeader('Deprecation', 'true');\nres.setHeader('Sunset', 'Sat, 01 Jan 2025 00:00:00 GMT');\nres.setHeader('Link', '</api/v2/users>; rel=\"successor-version\"');\n```\n\n## Best Practices\n\n- Version from the start\n- Support at least N-1 versions\n- Document deprecation timeline\n- Provide migration guides\n- Use semantic versioning for breaking changes\n- Consider backwards-compatible changes first\n",
|
|
1384
|
-
"architecture/clean-architecture/index.md": "# Clean Architecture\n\nThis directory contains Clean Architecture patterns.\n\n## Available Chunks\n\n- **layers.md** - Dependency rule, layers, use cases, adapters\n",
|
|
1385
|
-
"architecture/clean-architecture/layers.md": "# Clean Architecture\n\n## Core Principle\n\nDependencies point inward. Inner layers know nothing about outer layers.\n\n```\n┌─────────────────────────────────────────────┐\n│ Frameworks & Drivers │\n│ ┌─────────────────────────────────────┐ │\n│ │ Interface Adapters │ │\n│ │ ┌─────────────────────────────┐ │ │\n│ │ │ Application Business │ │ │\n│ │ │ ┌─────────────────────┐ │ │ │\n│ │ │ │ Enterprise Business│ │ │ │\n│ │ │ │ (Entities) │ │ │ │\n│ │ │ └─────────────────────┘ │ │ │\n│ │ │ (Use Cases) │ │ │\n│ │ └─────────────────────────────┘ │ │\n│ │ (Controllers, Gateways) │ │\n│ └─────────────────────────────────────┘ │\n│ (Web, DB, External APIs) │\n└─────────────────────────────────────────────┘\n```\n\n## The Dependency Rule\n\nSource code dependencies only point inward.\n\n## Layer Structure\n\n### Entities (Enterprise Business Rules)\n\n```typescript\nclass Order {\n constructor(\n public readonly id: string,\n private items: OrderItem[],\n private status: OrderStatus\n ) {}\n\n calculateTotal(): Money {\n return this.items.reduce(\n (sum, item) => sum.add(item.subtotal()),\n Money.zero()\n );\n }\n\n canBeCancelled(): boolean {\n return this.status === OrderStatus.Pending;\n }\n}\n```\n\n### Use Cases (Application Business Rules)\n\n```typescript\nclass CreateOrderUseCase {\n constructor(\n private orderRepository: OrderRepository,\n private productRepository: ProductRepository\n ) {}\n\n async execute(request: CreateOrderRequest): Promise<CreateOrderResponse> {\n const products = await this.productRepository.findByIds(request.productIds);\n const order = new Order(generateId(), this.createItems(products));\n await this.orderRepository.save(order);\n return { orderId: order.id };\n }\n}\n```\n\n### Interface Adapters\n\n```typescript\n// Controller (adapts HTTP to use case)\nclass OrderController {\n constructor(private createOrder: CreateOrderUseCase) {}\n\n async create(req: Request, res: Response) {\n const result = await this.createOrder.execute(req.body);\n res.json(result);\n }\n}\n\n// Repository Implementation (adapts use case to database)\nclass PostgreSQLOrderRepository implements OrderRepository {\n async save(order: Order): Promise<void> {\n await this.db.query('INSERT INTO orders...');\n }\n}\n```\n\n### Frameworks & Drivers\n\n```typescript\n// Express setup\nconst app = express();\napp.post('/orders', (req, res) => orderController.create(req, res));\n\n// Database connection\nconst db = new Pool({ connectionString: process.env.DATABASE_URL });\n```\n\n## Best Practices\n\n- Keep entities pure with no framework dependencies\n- Use cases orchestrate domain logic\n- Interfaces defined in inner layers, implemented in outer layers\n- Cross boundaries with simple data structures\n- Test use cases independently of frameworks\n",
|
|
1386
|
-
"architecture/ddd/index.md": "# Domain-Driven Design\n\nThis directory contains DDD patterns.\n\n## Available Chunks\n\n- **tactical.md** - Entities, Value Objects, Aggregates, Domain Events\n- **strategic.md** - Bounded Contexts, Ubiquitous Language, Context Mapping\n",
|
|
1387
|
-
"architecture/ddd/strategic.md": "# DDD Strategic Patterns\n\n## Ubiquitous Language\n\nUse the same terminology in code, documentation, and conversations.\n\n```typescript\n// Domain experts say \"place an order\"\nclass Order {\n place(): void { /* not submit(), not create() */ }\n}\n\n// Domain experts say \"items are added to cart\"\nclass ShoppingCart {\n addItem(product: Product): void { /* not insert(), not push() */ }\n}\n```\n\n## Bounded Contexts\n\nExplicit boundaries where a model applies consistently.\n\n```\n┌─────────────────┐ ┌─────────────────┐\n│ Sales │ │ Warehouse │\n│ Context │ │ Context │\n├─────────────────┤ ├─────────────────┤\n│ Order │ │ Order │\n│ - customerId │ │ - shipmentId │\n│ - items[] │ │ - pickingList │\n│ - total │ │ - status │\n└─────────────────┘ └─────────────────┘\n Same term, different model\n```\n\n## Context Mapping Patterns\n\n### Shared Kernel\nTwo contexts share a subset of the model.\n\n### Customer/Supplier\nUpstream context provides what downstream needs.\n\n### Conformist\nDownstream adopts upstream's model entirely.\n\n### Anti-Corruption Layer\nTranslate between contexts to protect domain model.\n\n```typescript\nclass InventoryAntiCorruptionLayer {\n constructor(private legacyInventorySystem: LegacyInventory) {}\n\n checkAvailability(productId: ProductId): Promise<boolean> {\n // Translate from legacy format to domain model\n const legacyResult = await this.legacyInventorySystem.getStock(\n productId.toString()\n );\n return legacyResult.qty > 0;\n }\n}\n```\n\n## Module Organization\n\n```\nsrc/\n├── sales/ # Sales bounded context\n│ ├── domain/\n│ │ ├── order.ts\n│ │ └── customer.ts\n│ ├── application/\n│ │ └── place-order.ts\n│ └── infrastructure/\n│ └── order-repository.ts\n├── warehouse/ # Warehouse bounded context\n│ ├── domain/\n│ │ └── shipment.ts\n│ └── ...\n└── shared/ # Shared kernel\n └── money.ts\n```\n\n## Best Practices\n\n- Define context boundaries based on team structure and business capabilities\n- Use ubiquitous language within each context\n- Communicate between contexts via events or explicit APIs\n- Protect domain model with anti-corruption layers when integrating legacy systems\n",
|
|
1388
|
-
"architecture/ddd/tactical.md": "# DDD Tactical Patterns\n\n## Entities\n\nObjects with identity that persists through state changes.\n\n```typescript\nclass User {\n constructor(\n public readonly id: UserId,\n private email: Email,\n private name: string\n ) {}\n\n changeEmail(newEmail: Email): void {\n this.email = newEmail;\n }\n\n equals(other: User): boolean {\n return this.id.equals(other.id);\n }\n}\n```\n\n## Value Objects\n\nImmutable objects defined by their attributes.\n\n```typescript\nclass Email {\n private readonly value: string;\n\n constructor(email: string) {\n if (!this.isValid(email)) {\n throw new InvalidEmailError(email);\n }\n this.value = email.toLowerCase();\n }\n\n equals(other: Email): boolean {\n return this.value === other.value;\n }\n}\n\nclass Money {\n constructor(\n public readonly amount: number,\n public readonly currency: Currency\n ) {\n Object.freeze(this);\n }\n\n add(other: Money): Money {\n this.assertSameCurrency(other);\n return new Money(this.amount + other.amount, this.currency);\n }\n}\n```\n\n## Aggregates\n\nCluster of entities and value objects with a root entity.\n\n```typescript\nclass Order {\n private items: OrderItem[] = [];\n\n constructor(\n public readonly id: OrderId,\n private customerId: CustomerId\n ) {}\n\n addItem(product: Product, quantity: number): void {\n const item = new OrderItem(product.id, product.price, quantity);\n this.items.push(item);\n }\n\n // All modifications go through aggregate root\n removeItem(productId: ProductId): void {\n this.items = this.items.filter(item => !item.productId.equals(productId));\n }\n}\n```\n\n## Domain Events\n\nCapture something that happened in the domain.\n\n```typescript\nclass OrderPlaced implements DomainEvent {\n constructor(\n public readonly orderId: OrderId,\n public readonly customerId: CustomerId,\n public readonly occurredOn: Date = new Date()\n ) {}\n}\n\nclass Order {\n private events: DomainEvent[] = [];\n\n place(): void {\n this.status = OrderStatus.Placed;\n this.events.push(new OrderPlaced(this.id, this.customerId));\n }\n\n pullEvents(): DomainEvent[] {\n const events = [...this.events];\n this.events = [];\n return events;\n }\n}\n```\n\n## Repositories\n\nAbstract persistence for aggregates.\n\n```typescript\ninterface OrderRepository {\n findById(id: OrderId): Promise<Order | null>;\n save(order: Order): Promise<void>;\n nextId(): OrderId;\n}\n```\n\n## Best Practices\n\n- One repository per aggregate root\n- Aggregates should be small\n- Reference other aggregates by ID\n- Publish domain events for cross-aggregate communication\n- Keep value objects immutable\n",
|
|
1389
|
-
"architecture/event-driven/index.md": "# Event-Driven Architecture\n\nThis directory contains event-driven architecture patterns.\n\n## Available Chunks\n\n- **patterns.md** - Event Sourcing, CQRS, Sagas, Event Versioning\n",
|
|
1390
|
-
"architecture/event-driven/messaging.md": "# Event-Driven Messaging\n\n## Message Types\n\n### Commands\nRequest to perform an action. Directed to a single handler.\n\n```typescript\ninterface CreateOrderCommand {\n type: 'CreateOrder';\n orderId: string;\n customerId: string;\n items: OrderItem[];\n timestamp: Date;\n}\n\n// Single handler processes the command\nclass CreateOrderHandler {\n async handle(command: CreateOrderCommand): Promise<void> {\n const order = Order.create(command);\n await this.repository.save(order);\n await this.eventBus.publish(new OrderCreatedEvent(order));\n }\n}\n```\n\n### Events\nNotification that something happened. Published to multiple subscribers.\n\n```typescript\ninterface OrderCreatedEvent {\n type: 'OrderCreated';\n orderId: string;\n customerId: string;\n totalAmount: number;\n occurredAt: Date;\n}\n\n// Multiple handlers can subscribe\nclass InventoryService {\n @Subscribe('OrderCreated')\n async onOrderCreated(event: OrderCreatedEvent): Promise<void> {\n await this.reserveInventory(event.orderId);\n }\n}\n\nclass NotificationService {\n @Subscribe('OrderCreated')\n async onOrderCreated(event: OrderCreatedEvent): Promise<void> {\n await this.sendConfirmation(event.customerId);\n }\n}\n```\n\n### Queries\nRequest for data. Returns a response.\n\n```typescript\ninterface GetOrderQuery {\n type: 'GetOrder';\n orderId: string;\n}\n\nclass GetOrderHandler {\n async handle(query: GetOrderQuery): Promise<Order> {\n return this.repository.findById(query.orderId);\n }\n}\n```\n\n## Message Bus Patterns\n\n### In-Memory Bus\n\n```typescript\nclass EventBus {\n private handlers = new Map<string, Function[]>();\n\n subscribe(eventType: string, handler: Function): void {\n const handlers = this.handlers.get(eventType) || [];\n handlers.push(handler);\n this.handlers.set(eventType, handlers);\n }\n\n async publish(event: Event): Promise<void> {\n const handlers = this.handlers.get(event.type) || [];\n await Promise.all(handlers.map(h => h(event)));\n }\n}\n```\n\n### Message Queue Integration\n\n```typescript\n// RabbitMQ example\nclass RabbitMQPublisher {\n async publish(event: Event): Promise<void> {\n const message = JSON.stringify({\n type: event.type,\n data: event,\n metadata: {\n correlationId: uuid(),\n timestamp: new Date().toISOString()\n }\n });\n\n await this.channel.publish(\n 'events',\n event.type,\n Buffer.from(message),\n { persistent: true }\n );\n }\n}\n\nclass RabbitMQConsumer {\n async consume(queue: string, handler: EventHandler): Promise<void> {\n await this.channel.consume(queue, async (msg) => {\n if (!msg) return;\n\n try {\n const event = JSON.parse(msg.content.toString());\n await handler.handle(event);\n this.channel.ack(msg);\n } catch (error) {\n this.channel.nack(msg, false, true); // Requeue\n }\n });\n }\n}\n```\n\n## Delivery Guarantees\n\n### At-Least-Once Delivery\n\n```typescript\n// Producer: persist before publish\nasync function publishWithRetry(event: Event): Promise<void> {\n // 1. Save to outbox\n await db.insert('outbox', {\n id: event.id,\n type: event.type,\n payload: JSON.stringify(event),\n status: 'pending'\n });\n\n // 2. Publish (may fail)\n try {\n await messageBus.publish(event);\n await db.update('outbox', event.id, { status: 'sent' });\n } catch {\n // Retry worker will pick it up\n }\n}\n\n// Consumer: idempotent handling\nasync function handleIdempotent(event: Event): Promise<void> {\n const processed = await db.findOne('processed_events', event.id);\n if (processed) return; // Already handled\n\n await handleEvent(event);\n await db.insert('processed_events', { id: event.id });\n}\n```\n\n### Outbox Pattern\n\n```typescript\n// Transaction includes outbox write\nasync function createOrder(data: OrderData): Promise<Order> {\n return await db.transaction(async (tx) => {\n // 1. Business logic\n const order = Order.create(data);\n await tx.insert('orders', order);\n\n // 2. Outbox entry (same transaction)\n await tx.insert('outbox', {\n id: uuid(),\n aggregateId: order.id,\n type: 'OrderCreated',\n payload: JSON.stringify(order)\n });\n\n return order;\n });\n}\n\n// Separate process polls and publishes\nasync function processOutbox(): Promise<void> {\n const pending = await db.query(\n 'SELECT * FROM outbox WHERE status = $1 ORDER BY created_at LIMIT 100',\n ['pending']\n );\n\n for (const entry of pending) {\n await messageBus.publish(JSON.parse(entry.payload));\n await db.update('outbox', entry.id, { status: 'sent' });\n }\n}\n```\n\n## Dead Letter Queues\n\n```typescript\nclass DeadLetterHandler {\n maxRetries = 3;\n\n async handleFailure(message: Message, error: Error): Promise<void> {\n const retryCount = message.metadata.retryCount || 0;\n\n if (retryCount < this.maxRetries) {\n // Retry with backoff\n await this.scheduleRetry(message, retryCount + 1);\n } else {\n // Move to DLQ\n await this.moveToDLQ(message, error);\n }\n }\n\n async moveToDLQ(message: Message, error: Error): Promise<void> {\n await this.dlqChannel.publish('dead-letter', {\n originalMessage: message,\n error: error.message,\n failedAt: new Date()\n });\n\n // Alert operations\n await this.alerting.notify('Message moved to DLQ', { message, error });\n }\n}\n```\n\n## Best Practices\n\n- Use correlation IDs to trace message flows\n- Make consumers idempotent\n- Use dead letter queues for failed messages\n- Monitor queue depths and consumer lag\n- Design for eventual consistency\n- Version your message schemas\n- Include metadata (timestamp, correlationId, causationId)\n",
|
|
1391
|
-
"architecture/event-driven/patterns.md": "# Event-Driven Architecture\n\n## Event Sourcing\n\nStore state as a sequence of events.\n\n```typescript\ninterface Event {\n id: string;\n aggregateId: string;\n type: string;\n data: unknown;\n timestamp: Date;\n version: number;\n}\n\nclass Account {\n private balance = 0;\n private version = 0;\n\n static fromEvents(events: Event[]): Account {\n const account = new Account();\n events.forEach(event => account.apply(event));\n return account;\n }\n\n private apply(event: Event): void {\n switch (event.type) {\n case 'MoneyDeposited':\n this.balance += (event.data as { amount: number }).amount;\n break;\n case 'MoneyWithdrawn':\n this.balance -= (event.data as { amount: number }).amount;\n break;\n }\n this.version = event.version;\n }\n}\n```\n\n## CQRS (Command Query Responsibility Segregation)\n\nSeparate read and write models.\n\n```typescript\n// Write Model (Commands)\nclass OrderCommandHandler {\n async handle(cmd: PlaceOrderCommand): Promise<void> {\n const order = new Order(cmd.orderId, cmd.items);\n await this.eventStore.save(order.changes());\n }\n}\n\n// Read Model (Queries)\nclass OrderQueryService {\n async getOrderSummary(orderId: string): Promise<OrderSummaryDTO> {\n return this.readDb.query('SELECT * FROM order_summaries WHERE id = $1', [orderId]);\n }\n}\n\n// Projection updates read model from events\nclass OrderProjection {\n async handle(event: OrderPlaced): Promise<void> {\n await this.readDb.insert('order_summaries', {\n id: event.orderId,\n status: 'placed',\n total: event.total\n });\n }\n}\n```\n\n## Saga Pattern\n\nManage long-running transactions across services.\n\n```typescript\nclass OrderSaga {\n async execute(orderId: string): Promise<void> {\n try {\n await this.paymentService.charge(orderId);\n await this.inventoryService.reserve(orderId);\n await this.shippingService.schedule(orderId);\n } catch (error) {\n await this.compensate(orderId, error);\n }\n }\n\n private async compensate(orderId: string, error: Error): Promise<void> {\n await this.shippingService.cancel(orderId);\n await this.inventoryService.release(orderId);\n await this.paymentService.refund(orderId);\n }\n}\n```\n\n## Event Versioning\n\nHandle schema changes gracefully.\n\n```typescript\ninterface EventUpgrader {\n upgrade(event: Event): Event;\n}\n\nclass OrderPlacedV1ToV2 implements EventUpgrader {\n upgrade(event: Event): Event {\n const oldData = event.data as OrderPlacedV1Data;\n return {\n ...event,\n type: 'OrderPlaced',\n version: 2,\n data: {\n ...oldData,\n currency: 'USD' // New field with default\n }\n };\n }\n}\n```\n\n## Best Practices\n\n- Events are immutable facts\n- Include enough context in events for consumers\n- Version events from the start\n- Use idempotent event handlers\n- Design for eventual consistency\n- Consider snapshots for aggregates with many events\n",
|
|
1392
|
-
"architecture/feature-toggles/index.md": "# Feature Toggles\n\nThis directory contains feature toggle patterns.\n\n## Available Chunks\n\n- **patterns.md** - Release toggles, experiment toggles, ops toggles\n",
|
|
1393
|
-
"architecture/feature-toggles/patterns.md": "# Feature Toggles\n\n## Toggle Types\n\n### Release Toggles\nHide incomplete features in production.\n\n```typescript\nif (featureFlags.isEnabled('new-checkout')) {\n return <NewCheckout />;\n}\nreturn <LegacyCheckout />;\n```\n\n### Experiment Toggles\nA/B testing and gradual rollouts.\n\n```typescript\nconst variant = featureFlags.getVariant('pricing-experiment', userId);\nif (variant === 'new-pricing') {\n return calculateNewPricing(cart);\n}\nreturn calculateLegacyPricing(cart);\n```\n\n### Ops Toggles\nRuntime operational control.\n\n```typescript\nif (featureFlags.isEnabled('enable-caching')) {\n return cache.get(key) || fetchFromDatabase(key);\n}\nreturn fetchFromDatabase(key);\n```\n\n## Implementation\n\n```typescript\ninterface FeatureFlags {\n isEnabled(flag: string, context?: Context): boolean;\n getVariant(flag: string, userId: string): string;\n}\n\nclass FeatureFlagService implements FeatureFlags {\n constructor(private config: Map<string, FlagConfig>) {}\n\n isEnabled(flag: string, context?: Context): boolean {\n const config = this.config.get(flag);\n if (!config) return false;\n\n if (config.percentage) {\n return this.isInPercentage(context?.userId, config.percentage);\n }\n\n return config.enabled;\n }\n\n private isInPercentage(userId: string | undefined, percentage: number): boolean {\n if (!userId) return false;\n const hash = this.hashUserId(userId);\n return (hash % 100) < percentage;\n }\n}\n```\n\n## Best Practices\n\n- Remove toggles after feature is stable\n- Use clear naming conventions\n- Log toggle decisions for debugging\n- Test both toggle states\n- Limit number of active toggles\n- Document toggle purpose and expiration\n",
|
|
1394
|
-
"architecture/gui/index.md": "# GUI Architecture Patterns\n\nThis directory contains GUI architecture patterns.\n\n## Available Chunks\n\n- **patterns.md** - MVC, MVP, MVVM, Component Architecture\n",
|
|
1395
|
-
"architecture/gui/patterns.md": "# GUI Architecture Patterns\n\n## MVC (Model-View-Controller)\n\n```typescript\n// Model - data and business logic\nclass UserModel {\n private users: User[] = [];\n\n getUsers(): User[] { return this.users; }\n addUser(user: User): void { this.users.push(user); }\n}\n\n// View - presentation\nclass UserView {\n render(users: User[]): void {\n console.log('Users:', users);\n }\n}\n\n// Controller - handles input, coordinates\nclass UserController {\n constructor(\n private model: UserModel,\n private view: UserView\n ) {}\n\n handleAddUser(userData: UserData): void {\n const user = new User(userData);\n this.model.addUser(user);\n this.view.render(this.model.getUsers());\n }\n}\n```\n\n## MVP (Model-View-Presenter)\n\n```typescript\n// View interface - defines what presenter can call\ninterface UserView {\n showUsers(users: User[]): void;\n showError(message: string): void;\n}\n\n// Presenter - all presentation logic\nclass UserPresenter {\n constructor(\n private view: UserView,\n private model: UserModel\n ) {}\n\n loadUsers(): void {\n try {\n const users = this.model.getUsers();\n this.view.showUsers(users);\n } catch (error) {\n this.view.showError('Failed to load users');\n }\n }\n}\n\n// View implementation - passive, no logic\nclass UserListView implements UserView {\n showUsers(users: User[]): void { /* render list */ }\n showError(message: string): void { /* show error */ }\n}\n```\n\n## MVVM (Model-View-ViewModel)\n\n```typescript\n// ViewModel - exposes observable state\nclass UserViewModel {\n users = observable<User[]>([]);\n isLoading = observable(false);\n\n async loadUsers(): Promise<void> {\n this.isLoading.set(true);\n const users = await this.userService.getUsers();\n this.users.set(users);\n this.isLoading.set(false);\n }\n}\n\n// View binds to ViewModel\nconst UserList = observer(({ viewModel }: { viewModel: UserViewModel }) => (\n <div>\n {viewModel.isLoading.get() ? (\n <Spinner />\n ) : (\n viewModel.users.get().map(user => <UserItem key={user.id} user={user} />)\n )}\n </div>\n));\n```\n\n## Component Architecture (React/Vue)\n\n```typescript\n// Presentational component - no state, just props\nconst UserCard = ({ user, onDelete }: UserCardProps) => (\n <div className=\"user-card\">\n <h3>{user.name}</h3>\n <button onClick={() => onDelete(user.id)}>Delete</button>\n </div>\n);\n\n// Container component - manages state\nconst UserListContainer = () => {\n const [users, setUsers] = useState<User[]>([]);\n\n useEffect(() => {\n userService.getUsers().then(setUsers);\n }, []);\n\n const handleDelete = (id: string) => {\n userService.deleteUser(id).then(() => {\n setUsers(users.filter(u => u.id !== id));\n });\n };\n\n return <UserList users={users} onDelete={handleDelete} />;\n};\n```\n\n## Best Practices\n\n- Separate UI logic from business logic\n- Keep views as simple as possible\n- Use unidirectional data flow when possible\n- Make components reusable and testable\n- Choose pattern based on framework and team familiarity\n",
|
|
1396
|
-
"architecture/hexagonal/ports-adapters.md": "# Hexagonal Architecture (Ports & Adapters)\n\n## Core Principle\n\nThe application core (domain logic) is isolated from external concerns through ports (interfaces) and adapters (implementations).\n\n## Structure\n\n```\nsrc/\n├── domain/ # Pure business logic, no external dependencies\n│ ├── models/ # Domain entities and value objects\n│ ├── services/ # Domain services\n│ └── ports/ # Interface definitions (driven & driving)\n├── application/ # Use cases, orchestration\n│ └── services/ # Application services\n├── adapters/\n│ ├── primary/ # Driving adapters (controllers, CLI, events)\n│ │ ├── http/\n│ │ ├── grpc/\n│ │ └── cli/\n│ └── secondary/ # Driven adapters (repositories, clients)\n│ ├── persistence/\n│ ├── messaging/\n│ └── external-apis/\n└── config/ # Dependency injection, configuration\n```\n\n## Port Types\n\n### Driving Ports (Primary)\nInterfaces that the application exposes to the outside world:\n\n```typescript\n// domain/ports/driving/user-service.port.ts\nexport interface UserServicePort {\n createUser(data: CreateUserDTO): Promise<User>;\n getUser(id: string): Promise<User | null>;\n updateUser(id: string, data: UpdateUserDTO): Promise<User>;\n}\n```\n\n### Driven Ports (Secondary)\nInterfaces that the application needs from the outside world:\n\n```typescript\n// domain/ports/driven/user-repository.port.ts\nexport interface UserRepositoryPort {\n save(user: User): Promise<void>;\n findById(id: string): Promise<User | null>;\n findByEmail(email: string): Promise<User | null>;\n}\n\n// domain/ports/driven/email-sender.port.ts\nexport interface EmailSenderPort {\n send(to: string, subject: string, body: string): Promise<void>;\n}\n```\n\n## Adapter Implementation\n\n### Primary Adapter (HTTP Controller)\n\n```typescript\n// adapters/primary/http/user.controller.ts\nexport class UserController {\n constructor(private userService: UserServicePort) {}\n\n async create(req: Request, res: Response) {\n const user = await this.userService.createUser(req.body);\n res.status(201).json(user);\n }\n}\n```\n\n### Secondary Adapter (Repository)\n\n```typescript\n// adapters/secondary/persistence/postgres-user.repository.ts\nexport class PostgresUserRepository implements UserRepositoryPort {\n constructor(private db: DatabaseConnection) {}\n\n async save(user: User): Promise<void> {\n await this.db.query('INSERT INTO users...', user);\n }\n\n async findById(id: string): Promise<User | null> {\n const row = await this.db.query('SELECT * FROM users WHERE id = $1', [id]);\n return row ? this.toDomain(row) : null;\n }\n}\n```\n\n## Dependency Rule\n\nDependencies always point inward:\n- Adapters depend on Ports\n- Application depends on Domain\n- Domain has no external dependencies\n\n```\n[External World] → [Adapters] → [Ports] → [Domain]\n```\n\n## Testing Benefits\n\n```typescript\n// Test with mock adapters\nclass InMemoryUserRepository implements UserRepositoryPort {\n private users = new Map<string, User>();\n\n async save(user: User) { this.users.set(user.id, user); }\n async findById(id: string) { return this.users.get(id) || null; }\n}\n\n// Domain logic tested without infrastructure\ndescribe('UserService', () => {\n it('creates user', async () => {\n const repo = new InMemoryUserRepository();\n const service = new UserService(repo);\n const user = await service.createUser({ name: 'Test' });\n expect(user.name).toBe('Test');\n });\n});\n```\n\n## When to Use\n\n- Applications needing multiple entry points (HTTP, CLI, events)\n- Systems requiring easy infrastructure swapping\n- Projects prioritizing testability\n- Long-lived applications expecting technology changes\n",
|
|
1397
|
-
"architecture/index.md": "# Architecture Patterns\n\nArchitecture-specific guidelines and best practices.\n\n## Available Architectures\n\n- `microservices/` - Microservices architecture\n- `modular-monolith/` - Modular monolith patterns\n- `event-driven/` - Event-driven architecture\n- `layered/` - Layered architecture\n- `hexagonal/` - Hexagonal (Ports & Adapters) architecture\n- `refactor/` - Refactoring strategies\n",
|
|
1398
|
-
"architecture/layered/index.md": "# Layered Architecture\n\nThis directory contains layered architecture patterns.\n\n## Available Chunks\n\n- **layers.md** - Presentation, Domain, Data Access layers\n",
|
|
1399
|
-
"architecture/layered/layers.md": "# Layered Architecture\n\n## Layer Structure\n\n```\n┌─────────────────────────────────────┐\n│ Presentation Layer │\n│ (Controllers, Views, APIs) │\n└───────────────┬─────────────────────┘\n │\n┌───────────────▼─────────────────────┐\n│ Domain Layer │\n│ (Business Logic, Services) │\n└───────────────┬─────────────────────┘\n │\n┌───────────────▼─────────────────────┐\n│ Data Access Layer │\n│ (Repositories, ORM, DAOs) │\n└─────────────────────────────────────┘\n```\n\n## Presentation Layer\n\nHandles user interaction and HTTP requests.\n\n```typescript\nclass OrderController {\n constructor(private orderService: OrderService) {}\n\n async createOrder(req: Request, res: Response): Promise<void> {\n const dto = req.body as CreateOrderDTO;\n const result = await this.orderService.createOrder(dto);\n res.status(201).json(result);\n }\n}\n```\n\n## Domain Layer\n\nContains business logic and rules.\n\n```typescript\nclass OrderService {\n constructor(\n private orderRepository: OrderRepository,\n private productRepository: ProductRepository\n ) {}\n\n async createOrder(dto: CreateOrderDTO): Promise<Order> {\n const products = await this.productRepository.findByIds(dto.productIds);\n\n if (products.length !== dto.productIds.length) {\n throw new ProductNotFoundError();\n }\n\n const order = new Order(dto.customerId, products);\n order.calculateTotal();\n\n await this.orderRepository.save(order);\n return order;\n }\n}\n```\n\n## Data Access Layer\n\nHandles persistence operations.\n\n```typescript\nclass OrderRepository {\n constructor(private db: Database) {}\n\n async save(order: Order): Promise<void> {\n await this.db.query(\n 'INSERT INTO orders (id, customer_id, total) VALUES ($1, $2, $3)',\n [order.id, order.customerId, order.total]\n );\n }\n\n async findById(id: string): Promise<Order | null> {\n const row = await this.db.queryOne('SELECT * FROM orders WHERE id = $1', [id]);\n return row ? this.mapToOrder(row) : null;\n }\n}\n```\n\n## Layer Rules\n\n1. Upper layers depend on lower layers\n2. Never skip layers\n3. Each layer exposes interfaces to the layer above\n4. Domain layer should not depend on data access implementation\n\n## Best Practices\n\n- Keep layers focused on their responsibility\n- Use DTOs to transfer data between layers\n- Define interfaces in domain layer, implement in data access\n- Avoid business logic in presentation or data access layers\n- Consider dependency inversion for testability\n",
|
|
1400
|
-
"architecture/microservices/api-gateway.md": "# API Gateway\r\n\r\n## Overview\r\n\r\nAn API Gateway acts as a single entry point for a group of microservices. It handles cross-cutting concerns and routes requests to the appropriate backend services.\r\n\r\n## Core Responsibilities\r\n\r\n1. **Routing**: Forwarding requests to the correct service (e.g., `/api/users` -> User Service).\r\n2. **Authentication & Authorization**: Verifying identity and permissions at the edge.\r\n3. **Rate Limiting**: Protecting services from abuse.\r\n4. **Protocol Translation**: Converting public HTTP/REST to internal gRPC or AMQP.\r\n5. **Response Aggregation**: Combining data from multiple services into a single response.\r\n\r\n## Patterns\r\n\r\n### Backend for Frontend (BFF)\r\n\r\nCreate separate gateways for different client types (Mobile, Web, 3rd Party) to optimize the API for each consumer.\r\n\r\n```mermaid\r\ngraph TD\r\n Web[Web App] --> WebBFF[Web BFF]\r\n Mobile[Mobile App] --> MobileBFF[Mobile BFF]\r\n \r\n WebBFF --> SvcA[Service A]\r\n WebBFF --> SvcB[Service B]\r\n \r\n MobileBFF --> SvcA\r\n MobileBFF --> SvcC[Service C]\r\n```\r\n\r\n## Implementation\r\n\r\n### Cross-Cutting Concerns\r\n\r\nHandle these at the gateway to keep microservices focused on business logic:\r\n\r\n- **SSL Termination**: Decrypt HTTPS at the gateway.\r\n- **CORS**: Handle Cross-Origin Resource Sharing headers.\r\n- **Request Validation**: Basic schema validation before hitting services.\r\n- **Caching**: Cache common responses.\r\n\r\n### When to Use\r\n\r\n| Use API Gateway When... | Avoid API Gateway When... |\r\n|-------------------------|---------------------------|\r\n| You have multiple microservices | You have a monolithic application |\r\n| You need centralized auth/security | You need ultra-low latency (extra hop) |\r\n| You have diverse clients (Web, Mobile) | Your architecture is very simple |\r\n\r\n## Best Practices\r\n\r\n- **Keep it Logic-Free**: Don't put business logic in the gateway. It should be a router, not a processor.\r\n- **High Availability**: The gateway is a single point of failure; deploy it in a cluster.\r\n- **Observability**: Ensure the gateway generates trace IDs and logs all traffic.\r\n",
|
|
1401
|
-
"architecture/microservices/boundaries.md": "# Service Boundaries\n\n## Defining Service Boundaries\n\nEach service should own a specific business capability:\n\n```\n✅ Good Boundaries:\n- User Service: Authentication, profiles, preferences\n- Order Service: Order processing, fulfillment\n- Payment Service: Payment processing, billing\n- Notification Service: Emails, SMS, push notifications\n\n❌ Bad Boundaries:\n- Data Access Service (technical, not business)\n- Utility Service (too generic)\n- God Service (does everything)\n```\n\n## Bounded Contexts\n\nUse Domain-Driven Design to identify boundaries:\n\n- Each service represents a bounded context\n- Services are organized around business domains\n- Clear ownership of data and logic\n- Services should be independently deployable\n\n## Ownership Rules\n\n**Each service:**\n- Owns its own database (no shared databases)\n- Owns its domain logic\n- Exposes well-defined APIs\n- Can be developed by autonomous teams\n\n## Communication Rules\n\n**Avoid:**\n- Direct database access between services\n- Chatty communication (N+1 service calls)\n- Tight coupling through shared libraries\n\n**Prefer:**\n- API-based communication\n- Event-driven for data synchronization\n- Async messaging where possible\n\n## Data Ownership\n\n```text\n// ✅ Good - Service owns its data\nClass OrderService:\n Method CreateOrder(data):\n # Order service owns order data\n Order = OrderRepository.Save(data)\n\n # Publish event for other services\n EventBus.Publish(\"order.created\", {\n orderId: Order.id,\n userId: Order.userId,\n total: Order.total\n })\n\n Return Order\n\n// ❌ Bad - Direct access to another service's database\nClass OrderService:\n Method CreateOrder(data):\n # Don't do this!\n User = UserDatabase.FindOne({ id: data.userId })\n```\n\n## Sizing Guidelines\n\nKeep services:\n- Small enough to be maintained by a small team (2-3 developers)\n- Large enough to provide business value\n- Focused on a single bounded context\n- Independently deployable and scalable\n",
|
|
1402
|
-
"architecture/microservices/communication.md": "# Microservices Communication\n\n## Synchronous vs Asynchronous\n\n```text\n# ⚠️ Synchronous creates coupling and multiplicative downtime\n# If Service A calls B calls C, any failure breaks the chain\n\n# ✅ Prefer asynchronous messaging for most inter-service communication\n# Limit synchronous calls to one per user request\n\n# Async Message Format Example\nEvent: \"order.created\"\nData: {\n orderId: \"ord_123\",\n userId: \"user_456\",\n items: [...]\n}\n\n# Subscribers process independently\nService Inventory -> ReserveItems(items)\nService Notification -> SendEmail(user)\n```\n\n## API-Based Communication\n\n```text\n# ✅ Well-defined REST APIs between services\nGET /users/{userId}\n\n# ✅ Use circuit breaker for resilience\nFunction getUserSafe(userId):\n Try:\n return UserClient.getUser(userId)\n Catch Error:\n return getCachedUser(userId) # Fallback\n```\n\n## Event-Driven Integration\n\n```text\n# ✅ Publish events for state changes\nFunction CreateOrder(data):\n order = Repository.Save(data)\n \n # Failures here don't block the user\n EventBus.Publish(\"order.created\", {\n orderId: order.id,\n userId: order.userId,\n timestamp: Now()\n })\n\n return order\n\n# ✅ Consumers handle events independently (Decoupled)\nService Notification:\n On(\"order.created\"): SendConfirmation(event)\n\nService Inventory:\n On(\"order.created\"): ReserveInventory(event)\n```\n\n## Tolerant Reader Pattern\n\n```text\n# ✅ Don't fail on unknown fields - enables independent evolution\nStructure UserResponse:\n id: string\n name: string\n ...ignore other fields...\n\n# ✅ Use sensible defaults for missing optional fields\nFunction ParseUser(data):\n return User {\n id: data.id,\n name: data.name,\n role: data.role OR 'user', # Default\n avatar: data.avatar OR null\n }\n```\n\n## Anti-Patterns\n\n```text\n# ❌ Chatty communication (N+1 service calls)\nFor each orderId in orderIds:\n GetOrder(orderId) # N network calls!\n\n# ✅ Batch requests\nGetOrders(orderIds) # 1 network call\n\n# ❌ Tight coupling via shared databases\n# Service A directly queries Service B's tables\n\n# ✅ API-based communication\nUserClient.GetUsers(userIds)\n```\n",
|
|
1403
|
-
"architecture/microservices/data.md": "# Microservices Data Management\n\n## Database Per Service\n\n```\nEach service owns its database:\n\n✅ Order Service → order_db (PostgreSQL)\n✅ User Service → user_db (PostgreSQL)\n✅ Catalog Service → catalog_db (MongoDB)\n✅ Search Service → search_index (Elasticsearch)\n\n❌ Never share databases between services\n❌ Never query another service's tables directly\n```\n\n## Polyglot Persistence\n\n```text\n# Each service uses the best database for its needs\n\n# User Service -> Relational (ACID, relationships)\nRepository UserRepository:\n Method Create(user):\n SQL \"INSERT INTO users...\"\n\n# Catalog Service -> Document (Flexible schema)\nRepository ProductRepository:\n Method Create(product):\n Collection(\"products\").Insert(product)\n\n# Analytics Service -> Time-Series (High write volume)\nRepository MetricsRepository:\n Method Record(metric):\n InfluxDB.Write(metric)\n```\n\n## Eventual Consistency\n\n```text\n# ✅ Embrace eventual consistency for cross-service data\n\n1. Order Service: Save Order -> Publish \"order.created\"\n2. Inventory Service: Listen \"order.created\" -> Reserve Inventory\n\n# Data may be temporarily inconsistent - that's OK\n\n# ✅ Use compensating actions for failures\nFunction ProcessOrder(order):\n Try:\n InventoryService.Reserve(order.items)\n PaymentService.Charge(order.total)\n Catch Error:\n # Compensate: undo previous actions\n InventoryService.Release(order.items)\n Throw Error\n```\n\n## Data Synchronization Patterns\n\n```text\n# Pattern: Event Sourcing / CQRS\nService OrderQuery:\n On(\"product.updated\"):\n # Update local read-optimized copy\n Cache.Set(event.productId, { name: event.name, price: event.price })\n\n# Pattern: Saga for distributed transactions\nSaga CreateOrder:\n Step 1:\n Action: Inventory.Reserve()\n Compensate: Inventory.Release()\n Step 2:\n Action: Payment.Charge()\n Compensate: Payment.Refund()\n```\n\n## Data Ownership\n\n```text\n# ✅ Each service is the source of truth for its data\nService User:\n Function UpdateEmail(userId, email):\n Database.Update(userId, email)\n EventBus.Publish(\"user.email.changed\", { userId, email })\n\n# Other services maintain their own copies (projections)\nService Order:\n On(\"user.email.changed\"):\n # Update local cache, never query User DB directly\n LocalUserCache.Update(event.userId, event.email)\n```\n",
|
|
1404
|
-
"architecture/microservices/index.md": "# Microservices Architecture\n\nGuidelines for building microservices.\n\n## Chunks\n\n- `boundaries.md` - Defining service boundaries\n- `communication.md` - Inter-service communication\n- `data.md` - Data management and consistency\n- `deployment.md` - Deployment strategies\n- `resilience.md` - Resilience patterns\n",
|
|
1405
|
-
"architecture/microservices/resilience.md": "# Microservices Resilience\n\n## Circuit Breaker Pattern\n\n```text\nClass CircuitBreaker:\n State: CLOSED | OPEN | HALF_OPEN\n \n Method Execute(operation):\n If State is OPEN:\n If TimeoutExpired:\n State = HALF_OPEN\n Else:\n Throw Error(\"Circuit Open\")\n \n Try:\n Result = operation()\n OnSuccess()\n Return Result\n Catch Error:\n OnFailure()\n Throw Error\n```\n\n## Retry with Exponential Backoff\n\n```text\nFunction Retry(operation, maxAttempts, baseDelay):\n For attempt in 1..maxAttempts:\n Try:\n return operation()\n Catch Error:\n If attempt == maxAttempts: Throw Error\n \n # Exponential Backoff + Jitter\n delay = baseDelay * (2 ^ attempt) + RandomJitter()\n Sleep(delay)\n```\n\n## Bulkhead Pattern\n\n```text\n# Isolate resources to prevent cascading failures\nClass Bulkhead:\n MaxConcurrent = 5\n Active = 0\n \n Method Execute(operation):\n If Active >= MaxConcurrent:\n Throw Error(\"Bulkhead Full\")\n \n Active++\n Try:\n return operation()\n Finally:\n Active--\n\n# Usage: Separate bulkheads per dependency\nPaymentBulkhead = New Bulkhead(5)\nEmailBulkhead = New Bulkhead(10)\n```\n\n## Timeouts\n\n```text\nFunction WithTimeout(operation, timeoutMs):\n Race:\n 1. Result = operation()\n 2. Sleep(timeoutMs) -> Throw Error(\"Timeout\")\n\n# Always set timeouts for external calls\nResult = WithTimeout(UserService.GetUser(id), 5000)\n```\n\n## Graceful Degradation\n\n```text\nFunction GetProductRecommendations(userId):\n Try:\n return RecommendationService.GetPersonalized(userId)\n Catch Error:\n # Fallback to cached popular items\n Log(\"Recommendation service unavailable\")\n return GetPopularProducts()\n\n# Partial responses instead of complete failure\nFunction GetDashboard(userId):\n User = GetUser(userId) OR null\n Orders = GetOrders(userId) OR []\n Stats = GetStats(userId) OR null\n\n return { User, Orders, Stats }\n```\n\n## Health Checks\n\n```text\nEndpoint GET /health:\n Checks = [\n CheckDatabase(),\n CheckRedis(),\n CheckExternalAPI()\n ]\n \n Healthy = All(Checks) passed\n \n Return HTTP 200/503 {\n status: Healthy ? \"healthy\" : \"degraded\",\n checks: { ...details... }\n }\n```\n",
|
|
1406
|
-
"architecture/modular-monolith/boundaries.md": "# Modular Monolith Boundaries\n\n## High Cohesion, Low Coupling\n\n```typescript\n// ❌ Bad: Tight coupling - direct repository access\n@Injectable()\nexport class OrderService {\n constructor(private userRepo: UserRepository) {} // Crosses module boundary\n\n async createOrder(userId: string) {\n const user = await this.userRepo.findById(userId); // Direct access\n }\n}\n\n// ✅ Good: Loose coupling via service\n@Injectable()\nexport class OrderService {\n constructor(private userService: UserService) {} // Service dependency\n\n async createOrder(userId: string) {\n const user = await this.userService.findById(userId); // Through public API\n }\n}\n```\n\n## No Direct Cross-Module Database Access\n\n```typescript\n// ❌ Never query another module's tables directly\nclass BookingService {\n async createBooking(data: CreateBookingDto) {\n const user = await this.prisma.user.findUnique({ where: { id: data.userId } });\n // This bypasses the User module!\n }\n}\n\n// ✅ Use the module's public service API\nclass BookingService {\n constructor(private userService: UserService) {}\n\n async createBooking(data: CreateBookingDto) {\n const user = await this.userService.findById(data.userId);\n // Properly goes through User module\n }\n}\n```\n\n## Separated Interface Pattern\n\n```typescript\n// Define interface in consuming module\n// modules/order/interfaces/user-provider.interface.ts\nexport interface UserProvider {\n findById(id: string): Promise<User>;\n validateUser(id: string): Promise<boolean>;\n}\n\n// Implement in providing module\n// modules/user/user.service.ts\n@Injectable()\nexport class UserService implements UserProvider {\n async findById(id: string): Promise<User> {\n return this.userRepo.findById(id);\n }\n\n async validateUser(id: string): Promise<boolean> {\n const user = await this.findById(id);\n return user && user.isActive;\n }\n}\n```\n\n## Domain Events for Loose Coupling\n\n```typescript\n// ✅ Publish events instead of direct calls\n@Injectable()\nexport class UserService {\n constructor(private eventEmitter: EventEmitter2) {}\n\n async createUser(dto: CreateUserDto): Promise<User> {\n const user = await this.userRepo.create(dto);\n\n this.eventEmitter.emit('user.created', new UserCreatedEvent(user.id, user.email));\n\n return user;\n }\n}\n\n// Other modules subscribe to events\n@Injectable()\nexport class NotificationListener {\n @OnEvent('user.created')\n async handleUserCreated(event: UserCreatedEvent) {\n await this.notificationService.sendWelcomeEmail(event.email);\n }\n}\n```\n\n## Handling Circular Dependencies\n\n```typescript\n// Use forwardRef() when modules depend on each other\n@Module({\n imports: [\n forwardRef(() => AuthModule), // Break circular dependency\n UserModule,\n ],\n})\nexport class UserModule {}\n\n@Module({\n imports: [\n forwardRef(() => UserModule),\n ],\n})\nexport class AuthModule {}\n```\n\n## Export Only What's Necessary\n\n```typescript\n@Module({\n providers: [\n UserService, // Public service\n UserRepository, // Internal\n PasswordHasher, // Internal\n ],\n exports: [UserService], // Only export the service, not internals\n})\nexport class UserModule {}\n```\n",
|
|
1407
|
-
"architecture/modular-monolith/structure.md": "# Modular Monolith Structure\n\n## Project Organization\n\n```\nproject-root/\n├── apps/\n│ └── api/\n│ ├── src/\n│ │ ├── app/ # Application bootstrap\n│ │ ├── modules/ # Business modules\n│ │ │ ├── auth/\n│ │ │ ├── user/\n│ │ │ ├── booking/\n│ │ │ ├── payment/\n│ │ │ └── notification/\n│ │ ├── common/ # Shared infrastructure\n│ │ │ ├── decorators/\n│ │ │ ├── guards/\n│ │ │ └── interceptors/\n│ │ └── prisma/ # Database service\n│ └── main.ts\n├── libs/ # Shared libraries\n│ └── shared-types/\n└── package.json\n```\n\n## Module Structure\n\n```\nmodules/booking/\n├── entities/ # Domain models and DTOs\n│ ├── booking.entity.ts\n│ ├── create-booking.dto.ts\n│ └── booking-response.dto.ts\n├── repositories/ # Data access layer\n│ └── booking.repository.ts\n├── services/ # Business logic\n│ ├── booking.service.ts\n│ └── availability.service.ts\n├── controllers/ # HTTP/API layer\n│ └── bookings.controller.ts\n└── booking.module.ts # Module definition\n```\n\n## Module Definition\n\n```typescript\n@Module({\n imports: [\n PrismaModule,\n forwardRef(() => AuthModule),\n NotificationsModule,\n ],\n controllers: [BookingsController],\n providers: [\n BookingService,\n AvailabilityService,\n BookingRepository,\n ],\n exports: [BookingService], // Only export public API\n})\nexport class BookingsModule {}\n```\n\n## Layered Architecture Within Modules\n\n```typescript\n// Controller - HTTP layer\n@Controller('api/v1/bookings')\nexport class BookingsController {\n constructor(private bookingService: BookingService) {}\n\n @Get('calendar')\n async getCalendarBookings(@Query() dto: GetBookingsDto) {\n return this.bookingService.getBookingsForCalendar(dto);\n }\n}\n\n// Service - Business logic\n@Injectable()\nexport class BookingService {\n constructor(\n private bookingRepository: BookingRepository,\n private availabilityService: AvailabilityService,\n ) {}\n\n async getBookingsForCalendar(dto: GetBookingsDto) {\n const bookings = await this.bookingRepository.findByDateRange(\n dto.startDate,\n dto.endDate\n );\n return bookings.map(this.mapToCalendarDto);\n }\n}\n\n// Repository - Data access\n@Injectable()\nexport class BookingRepository {\n constructor(private prisma: PrismaService) {}\n\n async findByDateRange(start: Date, end: Date) {\n return this.prisma.booking.findMany({\n where: {\n startTime: { gte: start },\n endTime: { lte: end }\n }\n });\n }\n}\n```\n\n## Shared Infrastructure\n\n```typescript\n// common/guards/jwt-auth.guard.ts\n@Injectable()\nexport class JwtAuthGuard extends AuthGuard('jwt') {\n canActivate(context: ExecutionContext) {\n const isPublic = this.reflector.get<boolean>('isPublic', context.getHandler());\n return isPublic ? true : super.canActivate(context);\n }\n}\n\n// common/decorators/current-user.decorator.ts\nexport const CurrentUser = createParamDecorator(\n (data: unknown, ctx: ExecutionContext) => {\n return ctx.switchToHttp().getRequest().user;\n }\n);\n```\n",
|
|
1408
|
-
"architecture/serverless/best-practices.md": "# Serverless Best Practices\n\n## Function Design\n\n### Single Responsibility\n\n```typescript\n// ❌ Bad: Multiple responsibilities\nexport const handler = async (event: APIGatewayEvent) => {\n if (event.path === '/users') {\n // Handle users\n } else if (event.path === '/orders') {\n // Handle orders\n } else if (event.path === '/products') {\n // Handle products\n }\n};\n\n// ✅ Good: One function per responsibility\n// createUser.ts\nexport const handler = async (event: APIGatewayEvent) => {\n const userData = JSON.parse(event.body);\n const user = await userService.create(userData);\n return { statusCode: 201, body: JSON.stringify(user) };\n};\n```\n\n### Keep Functions Small\n\n```typescript\n// ✅ Good: Small, focused function\nexport const handler = async (event: SNSEvent) => {\n for (const record of event.Records) {\n const message = JSON.parse(record.Sns.Message);\n await processMessage(message);\n }\n};\n\n// Extract business logic to separate module\nasync function processMessage(message: OrderMessage): Promise<void> {\n const order = await orderService.process(message);\n await notificationService.sendConfirmation(order);\n}\n```\n\n## Cold Start Optimization\n\n### Minimize Dependencies\n\n```typescript\n// ❌ Bad: Heavy imports at top level\nimport * as AWS from 'aws-sdk';\nimport moment from 'moment';\nimport _ from 'lodash';\n\n// ✅ Good: Import only what you need\nimport { DynamoDB } from '@aws-sdk/client-dynamodb';\n\n// ✅ Good: Lazy load optional dependencies\nlet heavyLib: typeof import('heavy-lib') | undefined;\n\nasync function useHeavyFeature() {\n if (!heavyLib) {\n heavyLib = await import('heavy-lib');\n }\n return heavyLib.process();\n}\n```\n\n### Initialize Outside Handler\n\n```typescript\n// ✅ Good: Reuse connections across invocations\nimport { DynamoDB } from '@aws-sdk/client-dynamodb';\n\n// Created once, reused\nconst dynamodb = new DynamoDB({});\nlet cachedConnection: Connection | undefined;\n\nexport const handler = async (event: Event) => {\n // Reuse existing connection\n if (!cachedConnection) {\n cachedConnection = await createConnection();\n }\n\n return process(event, cachedConnection);\n};\n```\n\n### Provisioned Concurrency\n\n```yaml\n# serverless.yml\nfunctions:\n api:\n handler: handler.api\n provisionedConcurrency: 5 # Keep 5 instances warm\n```\n\n## Error Handling\n\n### Structured Error Responses\n\n```typescript\nclass LambdaError extends Error {\n constructor(\n message: string,\n public statusCode: number,\n public code: string\n ) {\n super(message);\n }\n}\n\nexport const handler = async (event: APIGatewayEvent) => {\n try {\n const result = await processRequest(event);\n return {\n statusCode: 200,\n body: JSON.stringify(result)\n };\n } catch (error) {\n if (error instanceof LambdaError) {\n return {\n statusCode: error.statusCode,\n body: JSON.stringify({\n error: { code: error.code, message: error.message }\n })\n };\n }\n\n console.error('Unexpected error:', error);\n return {\n statusCode: 500,\n body: JSON.stringify({\n error: { code: 'INTERNAL_ERROR', message: 'Internal server error' }\n })\n };\n }\n};\n```\n\n### Retry and Dead Letter Queues\n\n```yaml\n# CloudFormation\nResources:\n MyFunction:\n Type: AWS::Lambda::Function\n Properties:\n DeadLetterConfig:\n TargetArn: !GetAtt DeadLetterQueue.Arn\n\n DeadLetterQueue:\n Type: AWS::SQS::Queue\n Properties:\n QueueName: my-function-dlq\n```\n\n## State Management\n\n### Use External State Stores\n\n```typescript\n// ❌ Bad: In-memory state (lost between invocations)\nlet requestCount = 0;\n\nexport const handler = async () => {\n requestCount++; // Unreliable!\n};\n\n// ✅ Good: External state store\nimport { DynamoDB } from '@aws-sdk/client-dynamodb';\n\nconst dynamodb = new DynamoDB({});\n\nexport const handler = async (event: Event) => {\n // Atomic counter in DynamoDB\n await dynamodb.updateItem({\n TableName: 'Counters',\n Key: { id: { S: 'requests' } },\n UpdateExpression: 'ADD #count :inc',\n ExpressionAttributeNames: { '#count': 'count' },\n ExpressionAttributeValues: { ':inc': { N: '1' } }\n });\n};\n```\n\n### Step Functions for Workflows\n\n```yaml\n# Step Functions state machine\nStartAt: ValidateOrder\nStates:\n ValidateOrder:\n Type: Task\n Resource: arn:aws:lambda:...:validateOrder\n Next: ProcessPayment\n\n ProcessPayment:\n Type: Task\n Resource: arn:aws:lambda:...:processPayment\n Catch:\n - ErrorEquals: [PaymentFailed]\n Next: NotifyFailure\n Next: FulfillOrder\n\n FulfillOrder:\n Type: Task\n Resource: arn:aws:lambda:...:fulfillOrder\n End: true\n\n NotifyFailure:\n Type: Task\n Resource: arn:aws:lambda:...:notifyFailure\n End: true\n```\n\n## Security\n\n### Least Privilege IAM\n\n```yaml\n# serverless.yml\nprovider:\n iam:\n role:\n statements:\n # Only the permissions needed\n - Effect: Allow\n Action:\n - dynamodb:GetItem\n - dynamodb:PutItem\n Resource: arn:aws:dynamodb:*:*:table/Users\n\n - Effect: Allow\n Action:\n - s3:GetObject\n Resource: arn:aws:s3:::my-bucket/*\n```\n\n### Secrets Management\n\n```typescript\nimport { SecretsManager } from '@aws-sdk/client-secrets-manager';\n\nconst secretsManager = new SecretsManager({});\nlet cachedSecret: string | undefined;\n\nasync function getSecret(): Promise<string> {\n if (!cachedSecret) {\n const response = await secretsManager.getSecretValue({\n SecretId: 'my-api-key'\n });\n cachedSecret = response.SecretString;\n }\n return cachedSecret!;\n}\n```\n\n## Monitoring and Observability\n\n### Structured Logging\n\n```typescript\nimport { Logger } from '@aws-lambda-powertools/logger';\n\nconst logger = new Logger({\n serviceName: 'order-service',\n logLevel: 'INFO'\n});\n\nexport const handler = async (event: Event, context: Context) => {\n logger.addContext(context);\n\n logger.info('Processing order', {\n orderId: event.orderId,\n customerId: event.customerId\n });\n\n try {\n const result = await processOrder(event);\n logger.info('Order processed', { orderId: event.orderId });\n return result;\n } catch (error) {\n logger.error('Order processing failed', { error, event });\n throw error;\n }\n};\n```\n\n### Tracing\n\n```typescript\nimport { Tracer } from '@aws-lambda-powertools/tracer';\n\nconst tracer = new Tracer({ serviceName: 'order-service' });\n\nexport const handler = async (event: Event) => {\n const segment = tracer.getSegment();\n const subsegment = segment.addNewSubsegment('ProcessOrder');\n\n try {\n const result = await processOrder(event);\n subsegment.close();\n return result;\n } catch (error) {\n subsegment.addError(error);\n subsegment.close();\n throw error;\n }\n};\n```\n\n## Cost Optimization\n\n- Set appropriate memory (more memory = faster CPU)\n- Use ARM architecture when possible (cheaper)\n- Batch operations to reduce invocations\n- Use reserved concurrency to limit costs\n- Monitor and alert on spending\n- Clean up unused functions and versions\n",
|
|
1409
|
-
"architecture/serverless/index.md": "# Serverless Architecture\n\nThis directory contains serverless architecture patterns.\n\n## Available Chunks\n\n- **patterns.md** - FaaS, BaaS, cold starts, best practices\n",
|
|
1410
|
-
"architecture/serverless/patterns.md": "# Serverless Architecture\n\n## Key Principles\n\n- **Stateless functions**: Each invocation is independent\n- **Event-driven**: Functions triggered by events\n- **Auto-scaling**: Platform handles scaling\n- **Pay-per-use**: Billed by execution\n\n## Function Design\n\n```typescript\n// Handler pattern\nexport async function handler(\n event: APIGatewayEvent,\n context: Context\n): Promise<APIGatewayProxyResult> {\n try {\n const body = JSON.parse(event.body || '{}');\n const result = await processOrder(body);\n\n return {\n statusCode: 200,\n body: JSON.stringify(result)\n };\n } catch (error) {\n return {\n statusCode: 500,\n body: JSON.stringify({ error: 'Internal error' })\n };\n }\n}\n```\n\n## Cold Start Optimization\n\n```typescript\n// Initialize outside handler (reused across invocations)\nconst dbPool = createPool(process.env.DATABASE_URL);\n\nexport async function handler(event: Event): Promise<Response> {\n // Use cached connection\n const result = await dbPool.query('SELECT * FROM orders');\n return { statusCode: 200, body: JSON.stringify(result) };\n}\n```\n\n## State Management\n\n```typescript\n// Use external state stores\nclass OrderService {\n constructor(\n private dynamodb: DynamoDB,\n private redis: Redis\n ) {}\n\n async getOrder(id: string): Promise<Order> {\n // Check cache first\n const cached = await this.redis.get(`order:${id}`);\n if (cached) return JSON.parse(cached);\n\n // Fall back to database\n const result = await this.dynamodb.get({ Key: { id } });\n await this.redis.set(`order:${id}`, JSON.stringify(result));\n return result;\n }\n}\n```\n\n## Best Practices\n\n- Keep functions small and focused\n- Use environment variables for configuration\n- Minimize dependencies to reduce cold start time\n- Handle timeouts gracefully\n- Use async/await for all I/O operations\n- Implement idempotency for event handlers\n- Log structured data for observability\n- Set appropriate memory and timeout limits\n",
|
|
1411
|
-
"architecture/solid/index.md": "# SOLID Principles\n\nThis directory contains SOLID design principles.\n\n## Available Chunks\n\n- **principles.md** - SRP, OCP, LSP, ISP, DIP with TypeScript examples\n",
|
|
1412
|
-
"architecture/solid/principles.md": "# SOLID Principles\n\n## Single Responsibility Principle (SRP)\n\nA class should have only one reason to change.\n\n**Bad:**\n```typescript\nclass UserService {\n createUser(data: UserData): User { /* ... */ }\n sendWelcomeEmail(user: User): void { /* ... */ }\n generateReport(users: User[]): Report { /* ... */ }\n}\n```\n\n**Good:**\n```typescript\nclass UserService {\n createUser(data: UserData): User { /* ... */ }\n}\n\nclass EmailService {\n sendWelcomeEmail(user: User): void { /* ... */ }\n}\n\nclass ReportService {\n generateUserReport(users: User[]): Report { /* ... */ }\n}\n```\n\n## Open/Closed Principle (OCP)\n\nOpen for extension, closed for modification.\n\n**Bad:**\n```typescript\nclass PaymentProcessor {\n process(payment: Payment): void {\n if (payment.type === 'credit') { /* credit logic */ }\n else if (payment.type === 'paypal') { /* paypal logic */ }\n // Must modify class to add new payment types\n }\n}\n```\n\n**Good:**\n```typescript\ninterface PaymentHandler {\n process(payment: Payment): void;\n}\n\nclass CreditCardHandler implements PaymentHandler {\n process(payment: Payment): void { /* credit logic */ }\n}\n\nclass PayPalHandler implements PaymentHandler {\n process(payment: Payment): void { /* paypal logic */ }\n}\n\nclass PaymentProcessor {\n constructor(private handlers: Map<string, PaymentHandler>) {}\n\n process(payment: Payment): void {\n this.handlers.get(payment.type)?.process(payment);\n }\n}\n```\n\n## Liskov Substitution Principle (LSP)\n\nSubtypes must be substitutable for their base types.\n\n**Bad:**\n```typescript\nclass Bird {\n fly(): void { /* flying logic */ }\n}\n\nclass Penguin extends Bird {\n fly(): void {\n throw new Error(\"Penguins can't fly!\"); // Violates LSP\n }\n}\n```\n\n**Good:**\n```typescript\ninterface Bird {\n move(): void;\n}\n\nclass FlyingBird implements Bird {\n move(): void { this.fly(); }\n private fly(): void { /* flying logic */ }\n}\n\nclass Penguin implements Bird {\n move(): void { this.swim(); }\n private swim(): void { /* swimming logic */ }\n}\n```\n\n## Interface Segregation Principle (ISP)\n\nClients shouldn't depend on interfaces they don't use.\n\n**Bad:**\n```typescript\ninterface Worker {\n work(): void;\n eat(): void;\n sleep(): void;\n}\n\nclass Robot implements Worker {\n work(): void { /* ... */ }\n eat(): void { throw new Error(\"Robots don't eat\"); }\n sleep(): void { throw new Error(\"Robots don't sleep\"); }\n}\n```\n\n**Good:**\n```typescript\ninterface Workable {\n work(): void;\n}\n\ninterface Eatable {\n eat(): void;\n}\n\ninterface Sleepable {\n sleep(): void;\n}\n\nclass Human implements Workable, Eatable, Sleepable {\n work(): void { /* ... */ }\n eat(): void { /* ... */ }\n sleep(): void { /* ... */ }\n}\n\nclass Robot implements Workable {\n work(): void { /* ... */ }\n}\n```\n\n## Dependency Inversion Principle (DIP)\n\nDepend on abstractions, not concretions.\n\n**Bad:**\n```typescript\nclass UserService {\n private database = new MySQLDatabase();\n\n getUser(id: string): User {\n return this.database.query(`SELECT * FROM users WHERE id = '${id}'`);\n }\n}\n```\n\n**Good:**\n```typescript\ninterface Database {\n query(sql: string): any;\n}\n\nclass UserService {\n constructor(private database: Database) {}\n\n getUser(id: string): User {\n return this.database.query(`SELECT * FROM users WHERE id = '${id}'`);\n }\n}\n\n// Can inject any database implementation\nconst userService = new UserService(new MySQLDatabase());\nconst testService = new UserService(new InMemoryDatabase());\n```\n\n## Best Practices\n\n- Apply SRP at class, method, and module levels\n- Use interfaces and dependency injection for flexibility\n- Prefer composition over inheritance\n- Design small, focused interfaces\n- Inject dependencies rather than creating them internally\n",
|
|
1413
|
-
"database/basics.md": "# Database Basics\n\n## CRUD Operations\n\nCRUD = Create, Read, Update, Delete\n\nThese are the four basic operations for working with data.\n\n## CREATE - Inserting Data\n\n### SQL\n\n```sql\n-- Insert single record\nINSERT INTO users (name, email)\nVALUES ('Alice', 'alice@example.com');\n\n-- Insert multiple records\nINSERT INTO users (name, email)\nVALUES\n ('Bob', 'bob@example.com'),\n ('Carol', 'carol@example.com');\n```\n\n### With Code\n\n```pseudocode\n// Using SQL directly\ndatabase.execute(\n \"INSERT INTO users (name, email) VALUES (?, ?)\",\n ['Alice', 'alice@example.com']\n)\n\n// Using ORM/Model\nuser = User.create({\n name: 'Alice',\n email: 'alice@example.com'\n})\n```\n\n## READ - Querying Data\n\n### Select All\n\n```sql\n-- Get all records\nSELECT * FROM users;\n\n-- Get specific columns\nSELECT id, name FROM users;\n```\n\n### Filter with WHERE\n\n```sql\n-- Find by ID\nSELECT * FROM users WHERE id = 123;\n\n-- Find by condition\nSELECT * FROM users WHERE age > 18;\n\n-- Multiple conditions\nSELECT * FROM users\nWHERE age > 18 AND status = 'active';\n```\n\n### With Code\n\n```pseudocode\n// Get all\nusers = database.query(\"SELECT * FROM users\")\n\n// Get by ID\nuser = database.query(\n \"SELECT * FROM users WHERE id = ?\",\n [userId]\n)\n\n// Using ORM/Model\nuser = User.findById(123)\nactiveUsers = User.findAll({\n where: { status: 'active' }\n})\n```\n\n## UPDATE - Modifying Data\n\n### SQL\n\n```sql\n-- Update single field\nUPDATE users\nSET email = 'newemail@example.com'\nWHERE id = 123;\n\n-- Update multiple fields\nUPDATE users\nSET name = 'Alice Smith',\n email = 'alice.smith@example.com'\nWHERE id = 123;\n\n-- Update with condition\nUPDATE users\nSET status = 'inactive'\nWHERE last_login < '2023-01-01';\n```\n\n### With Code\n\n```pseudocode\n// Using SQL\ndatabase.execute(\n \"UPDATE users SET email = ? WHERE id = ?\",\n ['newemail@example.com', 123]\n)\n\n// Using ORM/Model\nUser.update(\n { email: 'newemail@example.com' },\n { where: { id: 123 } }\n)\n```\n\n## DELETE - Removing Data\n\n### SQL\n\n```sql\n-- Delete by ID\nDELETE FROM users WHERE id = 123;\n\n-- Delete with condition\nDELETE FROM users WHERE status = 'banned';\n\n-- Delete all (be careful!)\nDELETE FROM users;\n```\n\n### With Code\n\n```pseudocode\n// Using SQL\ndatabase.execute(\"DELETE FROM users WHERE id = ?\", [userId])\n\n// Using ORM/Model\nUser.destroy({ where: { id: userId } })\n```\n\n## Sorting Results\n\n```sql\n-- Sort ascending (A-Z, 0-9)\nSELECT * FROM users ORDER BY name ASC;\n\n-- Sort descending (Z-A, 9-0)\nSELECT * FROM users ORDER BY created_at DESC;\n\n-- Sort by multiple columns\nSELECT * FROM users\nORDER BY status ASC, name ASC;\n```\n\n## Limiting Results\n\n```sql\n-- Get first 10 records\nSELECT * FROM users LIMIT 10;\n\n-- Skip first 20, get next 10\nSELECT * FROM users LIMIT 10 OFFSET 20;\n\n-- Most recent 5 users\nSELECT * FROM users\nORDER BY created_at DESC\nLIMIT 5;\n```\n\n## Counting Records\n\n```sql\n-- Count all users\nSELECT COUNT(*) FROM users;\n\n-- Count by condition\nSELECT COUNT(*) FROM users WHERE status = 'active';\n```\n\n## Common Patterns\n\n### Check if Record Exists\n\n```pseudocode\nuser = database.query(\n \"SELECT * FROM users WHERE email = ?\",\n [email]\n)\n\nif user is empty:\n print(\"User not found\")\nelse:\n print(\"User exists\")\n```\n\n### Get One or Return Default\n\n```pseudocode\nuser = database.query(\n \"SELECT * FROM users WHERE id = ?\",\n [userId]\n)\n\nreturn user[0] or null\n```\n\n### Update if Exists, Create if Not\n\n```pseudocode\nexisting = database.query(\n \"SELECT * FROM users WHERE email = ?\",\n [email]\n)\n\nif existing.length > 0:\n // Update\n database.execute(\n \"UPDATE users SET name = ? WHERE email = ?\",\n [name, email]\n )\nelse:\n // Create\n database.execute(\n \"INSERT INTO users (name, email) VALUES (?, ?)\",\n [name, email]\n )\n```\n\n## Always Use Parameterized Queries\n\n```pseudocode\n// ❌ DANGEROUS: SQL Injection risk\nemail = userInput\ndatabase.query(\"SELECT * FROM users WHERE email = '\" + email + \"'\")\n// If email = \"'; DROP TABLE users; --\" 😱\n\n// ✅ SAFE: Parameterized query\ndatabase.query(\n \"SELECT * FROM users WHERE email = ?\",\n [email]\n)\n```\n\n## Basic WHERE Conditions\n\n```sql\n-- Equals\nWHERE status = 'active'\n\n-- Not equals\nWHERE status != 'banned'\n\n-- Greater than / Less than\nWHERE age > 18\nWHERE price < 100\n\n-- NULL checks\nWHERE deleted_at IS NULL\nWHERE email IS NOT NULL\n\n-- IN list\nWHERE status IN ('active', 'pending')\n\n-- Pattern matching\nWHERE email LIKE '%@gmail.com'\n\n-- Multiple conditions\nWHERE age > 18 AND status = 'active'\nWHERE role = 'admin' OR role = 'moderator'\n```\n\n## Basic Data Types\n\n```sql\n-- Text\nname VARCHAR(255)\ndescription TEXT\n\n-- Numbers\nage INTEGER\nprice DECIMAL(10, 2)\n\n-- Dates\ncreated_at TIMESTAMP\nbirth_date DATE\n\n-- Boolean\nis_active BOOLEAN\n```\n\n## Best Practices\n\n1. **Always use parameterized queries** - Prevents SQL injection\n2. **Add WHERE to UPDATE/DELETE** - Avoid accidentally modifying all records\n3. **Use LIMIT for testing** - Prevent fetching too much data\n4. **Check query results** - Handle empty results gracefully\n\n```pseudocode\n// ✅ Good practices\nasync function getUser(id):\n result = database.query(\n \"SELECT * FROM users WHERE id = ? LIMIT 1\",\n [id]\n )\n\n if result.length == 0:\n return null // Handle not found\n\n return result[0]\n\nasync function updateUserEmail(id, email):\n // Validate first\n if not email.contains('@'):\n throw Error(\"Invalid email\")\n\n // Update with WHERE\n database.execute(\n \"UPDATE users SET email = ? WHERE id = ?\",\n [email, id]\n )\n```\n\n## Common Mistakes\n\n```pseudocode\n// ❌ String concatenation (SQL injection!)\ndatabase.query(\"SELECT * FROM users WHERE id = \" + userId)\n\n// ❌ No WHERE clause (updates everything!)\ndatabase.query(\"UPDATE users SET status = 'banned'\")\n\n// ❌ Not handling empty results\nuser = result[0] // Crashes if empty\nprint(user.name) // undefined error\n\n// ✅ Correct\ndatabase.query(\"SELECT * FROM users WHERE id = ?\", [userId])\ndatabase.query(\"UPDATE users SET status = ? WHERE id = ?\", ['banned', userId])\nuser = result[0] or null\nif user is not null:\n print(user.name)\n```\n\n## Testing Queries\n\n```pseudocode\n// Start with SELECT to verify\nusersToDelete = database.query(\n \"SELECT * FROM users WHERE status = ?\",\n ['inactive']\n)\n\nprint(\"Would delete \" + usersToDelete.length + \" users\")\n\n// If correct, change to DELETE\n// database.execute(\"DELETE FROM users WHERE status = ?\", ['inactive'])\n```\n",
|
|
1414
|
-
"database/design-patterns.md": "# Database Design Patterns\n\n## Schema Design\n\n### Normalization\nReduce redundancy, maintain integrity.\n\n```sql\n-- Normalized\nCREATE TABLE users (id, name, email);\nCREATE TABLE orders (id, user_id REFERENCES users(id), total);\nCREATE TABLE order_items (id, order_id REFERENCES orders(id), product_id, qty);\n```\n\n### Denormalization\nTrade redundancy for read performance.\n\n```sql\n-- Denormalized for read performance\nCREATE TABLE order_summary (\n id, user_id, user_name, user_email,\n total, item_count, created_at\n);\n```\n\n## Common Patterns\n\n### Soft Deletes\n```sql\nALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL;\n\n-- Query active users\nSELECT * FROM users WHERE deleted_at IS NULL;\n```\n\n### Audit Trail\n```sql\nCREATE TABLE audit_log (\n id SERIAL PRIMARY KEY,\n table_name VARCHAR(100),\n record_id VARCHAR(100),\n action VARCHAR(20),\n old_values JSONB,\n new_values JSONB,\n changed_by VARCHAR(100),\n changed_at TIMESTAMP DEFAULT NOW()\n);\n```\n\n### Polymorphic Associations\n```sql\nCREATE TABLE comments (\n id SERIAL PRIMARY KEY,\n body TEXT,\n commentable_type VARCHAR(50), -- 'post', 'image', 'video'\n commentable_id INTEGER,\n created_at TIMESTAMP\n);\n```\n\n## Best Practices\n\n- Use appropriate data types\n- Add indexes for frequently queried columns\n- Use foreign keys for referential integrity\n- Consider partitioning for large tables\n- Plan for schema migrations\n- Document schema decisions\n",
|
|
1415
|
-
"database/index.md": "# Database Guidelines\n\nThis directory contains database design and optimization patterns.\n\n## Available Chunks\n\n- **schema.md** - Naming conventions, data types, constraints, normalization\n- **indexing.md** - When to index, composite indexes, query optimization\n",
|
|
1416
|
-
"database/indexing.md": "# Database Indexing\n\n## When to Add Indexes\n\n```sql\n-- ✅ Columns in WHERE clauses\nCREATE INDEX idx_users_email ON users(email);\n\n-- ✅ Foreign key columns\nCREATE INDEX idx_orders_user_id ON orders(user_id);\n\n-- ✅ Columns used in ORDER BY\nCREATE INDEX idx_products_created_at ON products(created_at DESC);\n\n-- ✅ Columns used in JOIN conditions\nCREATE INDEX idx_order_items_product_id ON order_items(product_id);\n```\n\n## Composite Indexes\n\n```sql\n-- Order matters! Put most selective column first\nCREATE INDEX idx_orders_user_status ON orders(user_id, status);\n\n-- This index helps with:\nSELECT * FROM orders WHERE user_id = 123;\nSELECT * FROM orders WHERE user_id = 123 AND status = 'pending';\n\n-- But NOT with:\nSELECT * FROM orders WHERE status = 'pending'; -- Can't use index\n```\n\n## Partial Indexes\n\n```sql\n-- Index only rows matching condition\nCREATE INDEX idx_active_users ON users(email) WHERE is_active = true;\n\n-- Smaller index, faster queries on active users\nSELECT * FROM users WHERE email = 'x@y.com' AND is_active = true;\n```\n\n## Unique Indexes\n\n```sql\n-- Enforces uniqueness and improves lookup\nCREATE UNIQUE INDEX idx_users_email ON users(email);\n\n-- Multi-column unique\nCREATE UNIQUE INDEX idx_unique_order_item ON order_items(order_id, product_id);\n```\n\n## Index Types\n\n```sql\n-- B-tree (default): =, <, >, <=, >=, BETWEEN\nCREATE INDEX idx_products_price ON products(price);\n\n-- Hash: Only equality (=)\nCREATE INDEX idx_users_id_hash ON users USING hash (id);\n\n-- GIN: Arrays, JSONB, full-text search\nCREATE INDEX idx_products_tags ON products USING gin (tags);\n\n-- GiST: Geometric data, range queries\nCREATE INDEX idx_locations ON places USING gist (location);\n```\n\n## Analyze Query Performance\n\n```sql\n-- EXPLAIN ANALYZE shows actual execution\nEXPLAIN ANALYZE\nSELECT * FROM users WHERE email = 'test@example.com';\n\n-- Look for:\n-- ✅ Index Scan / Index Only Scan (good)\n-- ❌ Seq Scan on large tables (bad)\n-- ❌ High \"actual time\" values (slow)\n```\n\n## Index Maintenance\n\n```sql\n-- Monitor index usage (PostgreSQL)\nSELECT\n schemaname, tablename, indexname, idx_scan, idx_tup_read\nFROM pg_stat_user_indexes\nORDER BY idx_scan ASC;\n\n-- Remove unused indexes (0 scans)\nDROP INDEX IF EXISTS unused_index_name;\n\n-- Rebuild bloated indexes\nREINDEX INDEX index_name;\n```\n\n## Anti-Patterns\n\n```sql\n-- ❌ Indexing every column\n-- Slows down INSERT/UPDATE, wastes space\n\n-- ❌ Indexes on low-cardinality columns\n-- Boolean columns rarely benefit from indexes\n\n-- ❌ Functions on indexed columns\n-- SELECT * FROM users WHERE LOWER(email) = 'x'; -- Can't use index!\n\n-- ✅ Use expression index instead\nCREATE INDEX idx_users_email_lower ON users(LOWER(email));\n```\n\n## Connection Pooling\n\n```typescript\n// ❌ New connection per query\nconst getUser = async (id: string) => {\n const conn = await createConnection(); // Expensive!\n const user = await conn.query('SELECT * FROM users WHERE id = ?', [id]);\n await conn.close();\n return user;\n};\n\n// ✅ Use connection pool\nconst pool = new Pool({ max: 20, idleTimeoutMillis: 30000 });\n\nconst getUser = async (id: string) => {\n const client = await pool.connect();\n try {\n return await client.query('SELECT * FROM users WHERE id = $1', [id]);\n } finally {\n client.release(); // Return to pool\n }\n};\n```\n",
|
|
1417
|
-
"database/nosql.md": "# NoSQL Database Patterns\n\n## Document Databases (MongoDB, CouchDB)\n\n### Schema Design\n\n```typescript\n// Embed vs Reference\n\n// ✅ Embed: Data accessed together, 1:few relationship\ninterface Order {\n _id: ObjectId;\n customerId: ObjectId;\n items: Array<{ // Embedded\n productId: ObjectId;\n name: string;\n quantity: number;\n price: number;\n }>;\n shippingAddress: { // Embedded\n street: string;\n city: string;\n country: string;\n };\n}\n\n// ✅ Reference: Data accessed separately, 1:many relationship\ninterface Post {\n _id: ObjectId;\n title: string;\n content: string;\n authorId: ObjectId; // Reference to User\n}\n\ninterface Comment {\n _id: ObjectId;\n postId: ObjectId; // Reference to Post\n authorId: ObjectId; // Reference to User\n content: string;\n}\n```\n\n### Indexing\n\n```typescript\n// Single field index\ndb.users.createIndex({ email: 1 });\n\n// Compound index (order matters!)\ndb.orders.createIndex({ customerId: 1, createdAt: -1 });\n\n// Partial index\ndb.users.createIndex(\n { email: 1 },\n { partialFilterExpression: { status: \"active\" } }\n);\n\n// Text search index\ndb.products.createIndex({ name: \"text\", description: \"text\" });\n```\n\n### Query Patterns\n\n```typescript\n// Avoid N+1 queries - use $lookup for joins\nconst ordersWithCustomers = await db.orders.aggregate([\n {\n $lookup: {\n from: \"customers\",\n localField: \"customerId\",\n foreignField: \"_id\",\n as: \"customer\"\n }\n },\n { $unwind: \"$customer\" }\n]).toArray();\n\n// Use projections to limit returned fields\nconst userNames = await db.users.find(\n { status: \"active\" },\n { projection: { name: 1, email: 1 } }\n).toArray();\n```\n\n## Key-Value Stores (Redis, DynamoDB)\n\n### Redis Patterns\n\n```typescript\n// Caching with TTL\nawait redis.setex(`user:${userId}`, 3600, JSON.stringify(user));\n\n// Rate limiting\nasync function isRateLimited(userId: string): Promise<boolean> {\n const key = `rate:${userId}`;\n const count = await redis.incr(key);\n if (count === 1) {\n await redis.expire(key, 60); // 60 second window\n }\n return count > 100; // 100 requests per minute\n}\n\n// Distributed locks\nasync function acquireLock(key: string, ttl: number): Promise<boolean> {\n const result = await redis.set(`lock:${key}`, \"1\", \"NX\", \"EX\", ttl);\n return result === \"OK\";\n}\n\n// Pub/Sub\nawait redis.publish(\"events\", JSON.stringify({ type: \"user.created\", data: user }));\n```\n\n### DynamoDB Patterns\n\n```typescript\n// Single table design - access patterns first\ninterface Item {\n PK: string; // Partition key: USER#<userId>\n SK: string; // Sort key: ORDER#<orderId>\n GSI1PK?: string; // Global Secondary Index\n GSI1SK?: string;\n // ... attributes\n}\n\n// Write with condition\nawait dynamodb.put({\n TableName: \"orders\",\n Item: order,\n ConditionExpression: \"attribute_not_exists(PK)\" // Prevent duplicates\n});\n\n// Query with begins_with\nconst userOrders = await dynamodb.query({\n TableName: \"orders\",\n KeyConditionExpression: \"PK = :pk AND begins_with(SK, :sk)\",\n ExpressionAttributeValues: {\n \":pk\": `USER#${userId}`,\n \":sk\": \"ORDER#\"\n }\n});\n```\n\n## Wide Column Stores (Cassandra)\n\n### Data Modeling\n\n```sql\n-- Design for queries, not relationships\n-- One table per query pattern\n\nCREATE TABLE orders_by_customer (\n customer_id UUID,\n order_date TIMESTAMP,\n order_id UUID,\n total DECIMAL,\n PRIMARY KEY ((customer_id), order_date, order_id)\n) WITH CLUSTERING ORDER BY (order_date DESC);\n\nCREATE TABLE orders_by_date (\n order_date DATE,\n order_id UUID,\n customer_id UUID,\n total DECIMAL,\n PRIMARY KEY ((order_date), order_id)\n);\n```\n\n## Best Practices\n\n### Denormalization\n- Duplicate data for read performance\n- Design for query patterns, not normalization\n- Accept eventual consistency\n\n### Data Modeling\n- Start with access patterns\n- One table per query (or single-table design for DynamoDB)\n- Embed related data that's always accessed together\n- Reference data that's accessed independently\n\n### Performance\n- Use indexes strategically\n- Batch operations when possible\n- Use TTL for temporary data\n- Consider sharding/partitioning for scale\n\n### Consistency\n- Understand your consistency model (eventual vs strong)\n- Use transactions when available and necessary\n- Design for idempotency\n\n```typescript\n// Idempotent writes with version/timestamp\nasync function updateUser(user: User): Promise<void> {\n await db.users.updateOne(\n { _id: user._id, version: user.version },\n { $set: { ...user, version: user.version + 1 } }\n );\n}\n```\n\n### Error Handling\n\n```typescript\n// Retry with exponential backoff\nasync function withRetry<T>(\n operation: () => Promise<T>,\n maxRetries = 3\n): Promise<T> {\n let lastError: Error;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error as Error;\n await sleep(Math.pow(2, i) * 100);\n }\n }\n\n throw lastError!;\n}\n```\n",
|
|
1418
|
-
"database/schema.md": "# Database Schema Design\n\n## Naming Conventions\n\n```sql\n-- Tables: plural, snake_case\nCREATE TABLE users (...);\nCREATE TABLE order_items (...);\n\n-- Columns: singular, snake_case\nuser_id, created_at, is_active\n\n-- Primary keys: id\nid SERIAL PRIMARY KEY\n\n-- Foreign keys: singular_table_id\nuser_id REFERENCES users(id)\n```\n\n## Primary Keys\n\n```sql\n-- ✅ Auto-incrementing integer (simple cases)\nid SERIAL PRIMARY KEY\n\n-- ✅ UUID for distributed systems\nid UUID PRIMARY KEY DEFAULT gen_random_uuid()\n\n-- ❌ Avoid composite primary keys when possible\n-- They complicate joins and foreign keys\n```\n\n## Essential Columns\n\n```sql\n-- ✅ Standard audit columns\nCREATE TABLE products (\n id SERIAL PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n price DECIMAL(10,2) NOT NULL,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n deleted_at TIMESTAMP NULL -- Soft delete\n);\n\n-- ✅ Version column for optimistic locking\nversion INTEGER DEFAULT 1\n```\n\n## Relationships\n\n```sql\n-- One-to-Many: Foreign key on \"many\" side\nCREATE TABLE orders (\n id SERIAL PRIMARY KEY,\n user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,\n total DECIMAL(10,2)\n);\n\n-- Many-to-Many: Junction table\nCREATE TABLE order_items (\n order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE,\n product_id INTEGER REFERENCES products(id),\n quantity INTEGER NOT NULL,\n PRIMARY KEY (order_id, product_id)\n);\n```\n\n## Constraints\n\n```sql\n-- ✅ NOT NULL for required fields\nemail VARCHAR(255) NOT NULL\n\n-- ✅ UNIQUE constraints\nemail VARCHAR(255) UNIQUE NOT NULL\n\n-- ✅ CHECK constraints for validation\nage INTEGER CHECK (age >= 0 AND age <= 150)\nstatus VARCHAR(20) CHECK (status IN ('pending', 'active', 'cancelled'))\n\n-- ✅ DEFAULT values\nis_active BOOLEAN DEFAULT true\nrole VARCHAR(20) DEFAULT 'user'\n```\n\n## Data Types\n\n```sql\n-- Strings\nVARCHAR(255) -- Variable length, max 255\nTEXT -- Unlimited length\n\n-- Numbers\nINTEGER -- Whole numbers\nBIGINT -- Large whole numbers\nDECIMAL(10,2) -- Exact decimals (money)\nREAL/DOUBLE -- Approximate decimals (scientific)\n\n-- Dates/Times\nTIMESTAMP -- Date and time\nDATE -- Date only\nINTERVAL -- Duration\n\n-- Other\nBOOLEAN -- true/false\nUUID -- Unique identifier\nJSONB -- JSON with indexing (PostgreSQL)\n```\n\n## Normalization Guidelines\n\n```sql\n-- ✅ 1NF: Atomic values, no repeating groups\n-- ❌ Bad: tags VARCHAR = 'tag1,tag2,tag3'\n-- ✅ Good: Separate tags table\n\n-- ✅ 2NF: No partial dependencies\n-- All non-key columns depend on entire primary key\n\n-- ✅ 3NF: No transitive dependencies\n-- Non-key columns don't depend on other non-key columns\n```\n\n## Denormalization (When Appropriate)\n\n```sql\n-- Cache computed values for read performance\nCREATE TABLE orders (\n id SERIAL PRIMARY KEY,\n user_id INTEGER REFERENCES users(id),\n items_count INTEGER DEFAULT 0, -- Denormalized\n total DECIMAL(10,2) DEFAULT 0 -- Denormalized\n);\n\n-- Update via triggers or application logic\n```\n",
|
|
1419
|
-
"devops/ci-cd.md": "# CI/CD Practices\n\n## Continuous Integration\n\nRun on every commit:\n\n```yaml\n# .github/workflows/ci.yml\nname: CI\non: [push, pull_request]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: '20'\n cache: 'npm'\n - run: npm ci\n - run: npm run lint\n - run: npm run typecheck\n - run: npm test\n - run: npm run build\n```\n\n## Continuous Deployment\n\nDeploy automatically after CI passes:\n\n```yaml\ndeploy:\n needs: build\n if: github.ref == 'refs/heads/main'\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - run: npm ci\n - run: npm run build\n - run: npm run deploy\n env:\n DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}\n```\n\n## Deployment Strategies\n\n### Blue-Green Deployment\nRun two identical environments, switch traffic instantly.\n\n### Canary Releases\nRoute small percentage of traffic to new version first.\n\n### Rolling Updates\nGradually replace instances with new version.\n\n## Best Practices\n\n- Run fast tests first, slow tests later\n- Cache dependencies between runs\n- Use matrix builds for multiple versions/platforms\n- Keep secrets in secure storage\n- Automate database migrations\n- Include rollback procedures\n- Monitor deployments with health checks\n- Use feature flags for safer releases\n",
|
|
1420
|
-
"devops/index.md": "# DevOps Guidelines\n\nThis directory contains DevOps and CI/CD patterns.\n\n## Available Chunks\n\n- **ci-cd.md** - Continuous Integration and Deployment pipelines\n- **practices.md** - Infrastructure as Code, monitoring, observability\n",
|
|
1421
|
-
"devops/observability.md": "# Observability\r\n\r\n## Overview\r\n\r\nObservability is the ability to understand the internal state of a system by examining its outputs. In modern distributed systems, it goes beyond simple monitoring to include logging, metrics, and tracing.\r\n\r\n## Three Pillars\r\n\r\n### 1. Structured Logging\r\n\r\nLogs should be machine-readable (JSON) and contain context.\r\n\r\n```json\r\n// ✅ Good: Structured JSON logging\r\n{\r\n \"level\": \"info\",\r\n \"message\": \"Order processed\",\r\n \"orderId\": \"ord_123\",\r\n \"userId\": \"user_456\",\r\n \"amount\": 99.99,\r\n \"durationMs\": 145,\r\n \"status\": \"success\"\r\n}\r\n```\r\n```text\r\n// ❌ Bad: Unstructured text\r\n\"Order processed: ord_123 for user_456\"\r\n```\r\n\r\n### 2. Metrics\r\n\r\nAggregatable data points for identifying trends and health.\r\n\r\n- **Counters**: Total requests, error counts (`http_requests_total`)\r\n- **Gauges**: Queue depth, memory usage (`memory_usage_bytes`)\r\n- **Histograms**: Request latency distribution (`http_request_duration_seconds`)\r\n\r\n### 3. Distributed Tracing\r\n\r\nTracking requests as they propagate through services.\r\n\r\n- **Trace ID**: Unique ID for the entire request chain\r\n- **Span ID**: Unique ID for a specific operation\r\n- **Context Propagation**: Passing IDs between services (e.g., W3C Trace Context)\r\n\r\n## Implementation Strategy\r\n\r\n### OpenTelemetry (OTel)\r\n\r\nUse OpenTelemetry as the vendor-neutral standard for collecting telemetry data.\r\n\r\n```text\r\n# Initialize OpenTelemetry SDK\r\nSDK.Configure({\r\n TraceExporter: Console/OTLP,\r\n Instrumentations: [Http, Database, Grpc]\r\n})\r\nSDK.Start()\r\n```\r\n\r\n### Health Checks\r\n\r\nExpose standard health endpoints:\r\n\r\n- `/health/live`: Is the process running? (Liveness)\r\n- `/health/ready`: Can it accept traffic? (Readiness)\r\n- `/health/startup`: Has it finished initializing? (Startup)\r\n\r\n## Alerting Best Practices\r\n\r\n- **Alert on Symptoms, not Causes**: \"High Error Rate\" (Symptom) vs \"CPU High\" (Cause).\r\n- **Golden Signals**: Latency, Traffic, Errors, Saturation.\r\n- **Actionable**: Every alert should require a specific human action.\r\n",
|
|
1422
|
-
"devops/practices.md": "# DevOps Practices\n\n## Infrastructure as Code\n\n```text\n# Define infrastructure as code (e.g., Terraform, Pulumi)\n\nResource S3Bucket \"app-bucket\":\n Access: Private\n Versioning: Enabled\n\nResource LambdaFunction \"api\":\n Runtime: Node.js / Python / Go\n Handler: index.handler\n Code: ./dist\n```\n\n## Containerization\n\n```dockerfile\n# Build Stage\nFROM base-image AS builder\nWORKDIR /app\nCOPY dependency-files ./\nRUN install-dependencies\nCOPY source-code .\nRUN build-application\n\n# Runtime Stage\nFROM runtime-image\nWORKDIR /app\nCOPY --from=builder /app/dist ./dist\nEXPOSE 8080\nCMD [\"run\", \"application\"]\n```\n\n## Observability\n\n### Logging\n```json\n{\n \"level\": \"info\",\n \"message\": \"Order created\",\n \"orderId\": \"ord_123\",\n \"customerId\": \"cust_456\",\n \"total\": 99.99,\n \"timestamp\": \"2023-10-27T10:00:00Z\"\n}\n```\n\n### Metrics\n```text\nMetrics.Increment(\"orders.created\")\nMetrics.Histogram(\"order.value\", total)\nMetrics.Timing(\"order.processing_time\", duration)\n```\n\n### Health Checks\n```text\nGET /health\nResponse 200 OK:\n{\n \"status\": \"healthy\",\n \"version\": \"1.2.3\",\n \"uptime\": 3600\n}\n```\n\n## Best Practices\n\n- Version control all infrastructure\n- Use immutable infrastructure\n- Implement proper secret management\n- Set up alerting for critical metrics\n- Use structured logging (JSON)\n- Include correlation IDs for tracing\n- Document runbooks for incidents\n",
|
|
1423
|
-
"error-handling/basics.md": "# Error Handling Basics\n\n## Throwing Errors\n\nUse `throw` to signal when something goes wrong.\n\n```pseudocode\nfunction divide(a, b):\n if b == 0:\n throw Error(\"Cannot divide by zero\")\n return a / b\n```\n\n## Try-Catch\n\nUse `try-catch` to handle errors gracefully.\n\n```pseudocode\ntry:\n result = divide(10, 0)\n print(result)\ncatch error:\n print(\"Error:\", error.message)\n // Continue with fallback behavior\n```\n\n## Always Provide Error Messages\n\nMake error messages clear and actionable.\n\n```pseudocode\n// ❌ Bad: Vague error\nthrow Error(\"Invalid\")\n\n// ✅ Good: Specific error\nthrow Error(\"Email must be a valid email address\")\n\n// ✅ Good: Include context\nthrow Error(\"User with ID \" + userId + \" not found\")\n```\n\n## Async Error Handling\n\nAlways use try-catch with async operations.\n\n```pseudocode\nasync function loadUser(id):\n try:\n user = await fetchUser(id)\n return user\n catch error:\n log(\"Failed to load user:\", error)\n throw error // Re-throw if caller should know\n```\n\n## When to Catch Errors\n\n### Catch When You Can Handle It\n\n```pseudocode\n// ✅ Good: Can provide fallback\nasync function getUserName(id):\n try:\n user = await fetchUser(id)\n return user.name\n catch error:\n return \"Unknown User\" // Fallback value\n```\n\n### Don't Catch If You Can't Handle\n\n```pseudocode\n// ❌ Bad: Catching but doing nothing\ntry:\n await criticalOperation()\ncatch error:\n // Empty catch - error lost!\n\n// ✅ Good: Let it propagate\nawait criticalOperation() // Caller will handle\n```\n\n## Validate Input Early\n\nCheck for problems before they cause errors.\n\n```pseudocode\nfunction createUser(email, age):\n // Validate inputs first\n if email is empty:\n throw Error(\"Email is required\")\n\n if not email.contains(\"@\"):\n throw Error(\"Email must be valid\")\n\n if age < 0:\n throw Error(\"Age cannot be negative\")\n\n // Now proceed with creation\n return { email: email, age: age }\n```\n\n## Logging Errors\n\nAlways log errors for debugging.\n\n```pseudocode\ntry:\n await processPayment(orderId)\ncatch error:\n // Log with context\n log(\"Payment processing failed:\", {\n orderId: orderId,\n error: error.message,\n timestamp: currentTime()\n })\n throw error\n```\n\n## Error Handling Patterns\n\n### Return Error Status\n\n```pseudocode\nfunction parseNumber(input):\n num = parseInt(input)\n if isNaN(num):\n return null // Indicate failure without throwing\n return num\n\n// Usage\nresult = parseNumber(userInput)\nif result is null:\n print(\"Invalid number\")\nelse:\n print(\"Number:\", result)\n```\n\n### Return Success/Error Object\n\n```pseudocode\nfunction safeDivide(a, b):\n if b == 0:\n return { success: false, error: \"Cannot divide by zero\" }\n return { success: true, data: a / b }\n\n// Usage\nresult = safeDivide(10, 2)\nif result.success:\n print(\"Result:\", result.data)\nelse:\n print(\"Error:\", result.error)\n```\n\n## Common Mistakes\n\n### Don't Swallow Errors\n\n```pseudocode\n// ❌ Bad: Error disappears\ntry:\n await importantOperation()\ncatch error:\n // Nothing here - error lost!\n\n// ✅ Good: Log at minimum\ntry:\n await importantOperation()\ncatch error:\n log(\"Operation failed:\", error)\n throw error // Or handle appropriately\n```\n\n### Don't Use Errors for Flow Control\n\n```pseudocode\n// ❌ Bad: Using errors for normal logic\ntry:\n user = findUser(id)\n // ...\ncatch error:\n // User not found - this is expected, not an error!\n\n// ✅ Good: Return null for expected cases\nuser = findUser(id)\nif user is null:\n print(\"User not found\")\n return\n```\n\n### Don't Throw Non-Error Objects\n\n```pseudocode\n// ❌ Bad\nthrow \"Something went wrong\" // String\nthrow { code: 500 } // Plain object\n\n// ✅ Good\nthrow Error(\"Something went wrong\")\n```\n\n## Best Practices\n\n1. **Fail fast** - Validate input early and throw immediately\n2. **Be specific** - Provide detailed, actionable error messages\n3. **Log errors** - Always log for debugging\n4. **Don't hide errors** - Let them propagate if you can't handle them\n5. **Clean up resources** - Close connections, files in finally blocks\n\n```pseudocode\nfile = null\ntry:\n file = await openFile(\"data.txt\")\n await processFile(file)\ncatch error:\n log(\"File processing failed:\", error)\n throw error\nfinally:\n // Always runs, even if error thrown\n if file is not null:\n await file.close()\n```\n",
|
|
1424
|
-
"error-handling/index.md": "# Error Handling Guidelines\n\nThis directory contains error handling patterns and strategies.\n\n## Available Chunks\n\n- **strategy.md** - Custom errors, centralized handling, Result type, retry patterns\n",
|
|
1425
|
-
"error-handling/strategy.md": "# Error Handling Strategy\n\n## Custom Error Classes\n\n```typescript\nclass AppError extends Error {\n constructor(\n message: string,\n public statusCode: number = 500,\n public code: string = 'INTERNAL_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nclass NotFoundError extends AppError {\n constructor(resource: string, id: string) {\n super(`${resource} with id ${id} not found`, 404, 'NOT_FOUND', { resource, id });\n }\n}\n\nclass ValidationError extends AppError {\n constructor(message: string, details: unknown) {\n super(message, 400, 'VALIDATION_ERROR', details);\n }\n}\n\n// Usage\nif (!user) {\n throw new NotFoundError('User', userId);\n}\n```\n\n## Never Swallow Errors\n\n```typescript\n// ❌ Silent failure - dangerous!\ntry {\n await criticalOperation();\n} catch (error) {\n // Error ignored\n}\n\n// ✅ Log and handle appropriately\ntry {\n await criticalOperation();\n} catch (error) {\n logger.error('Critical operation failed', { error });\n throw error; // Or handle gracefully\n}\n```\n\n## Specific Error Messages\n\n```typescript\n// ❌ Not actionable\nthrow new Error('Something went wrong');\n\n// ✅ Specific and actionable\nthrow new ValidationError('Email must be a valid email address', {\n field: 'email',\n value: userInput.email\n});\n```\n\n## Centralized Error Handler\n\n```typescript\n// Express error middleware\napp.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n if (err instanceof AppError) {\n return res.status(err.statusCode).json({\n error: {\n message: err.message,\n code: err.code,\n details: err.details\n }\n });\n }\n\n // Log unexpected errors\n console.error('Unexpected error:', err);\n\n // Don't expose internal details\n res.status(500).json({\n error: {\n message: 'Internal server error',\n code: 'INTERNAL_ERROR'\n }\n });\n});\n```\n\n## Async Error Wrapper\n\n```typescript\n// Wrap async handlers to catch errors automatically\nconst asyncHandler = (fn: RequestHandler) => {\n return (req: Request, res: Response, next: NextFunction) => {\n Promise.resolve(fn(req, res, next)).catch(next);\n };\n};\n\n// Usage\napp.get('/users/:id', asyncHandler(async (req, res) => {\n const user = await getUser(req.params.id);\n res.json(user);\n}));\n```\n\n## Result Type Pattern\n\n```typescript\ntype Result<T, E = Error> =\n | { success: true; value: T }\n | { success: false; error: E };\n\nfunction parseJSON<T>(json: string): Result<T, string> {\n try {\n return { success: true, value: JSON.parse(json) };\n } catch {\n return { success: false, error: 'Invalid JSON' };\n }\n}\n\n// Usage - forces explicit error handling\nconst result = parseJSON<User>(data);\nif (result.success) {\n console.log(result.value.name);\n} else {\n console.error(result.error);\n}\n```\n\n## Error Boundaries (React)\n\n```typescript\nclass ErrorBoundary extends React.Component {\n state = { hasError: false };\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n logger.error('UI Error', { error, errorInfo });\n }\n\n render() {\n if (this.state.hasError) {\n return <FallbackUI />;\n }\n return this.props.children;\n }\n}\n```\n\n## Retry with Limits\n\n```typescript\n// ❌ Infinite retries\nwhile (true) {\n try {\n await operation();\n break;\n } catch (error) {\n // Retry forever - exhausts resources\n }\n}\n\n// ✅ Limited retries with backoff\nconst maxRetries = 3;\nfor (let i = 0; i < maxRetries; i++) {\n try {\n await operation();\n break;\n } catch (error) {\n if (i === maxRetries - 1) throw error;\n await sleep(Math.pow(2, i) * 1000); // Exponential backoff\n }\n}\n```\n",
|
|
1426
|
-
"language/csharp/basics.md": "# C# Fundamentals\n\n## Project Structure\n\n```\nMyProject/\n├── src/\n│ ├── MyProject.Api/\n│ │ ├── Controllers/\n│ │ ├── Program.cs\n│ │ └── MyProject.Api.csproj\n│ ├── MyProject.Core/\n│ │ ├── Entities/\n│ │ ├── Interfaces/\n│ │ └── Services/\n│ └── MyProject.Infrastructure/\n│ ├── Data/\n│ └── Services/\n├── tests/\n│ └── MyProject.Tests/\n└── MyProject.sln\n```\n\n## Naming Conventions\n\n```csharp\n// Classes, interfaces, methods: PascalCase\npublic class UserService { }\npublic interface IUserRepository { }\npublic void CreateUser() { }\n\n// Interface prefix: I\npublic interface IRepository { }\n\n// Private fields: _camelCase\nprivate readonly IUserRepository _repository;\n\n// Parameters, local variables: camelCase\npublic User GetUser(string userId) { }\n\n// Constants: PascalCase\npublic const int MaxRetries = 3;\n```\n\n## Modern C# Features (10+)\n\n```csharp\n// Records for immutable data\npublic record User(string Id, string Email, string Name);\n\n// Pattern matching\nvar result = obj switch\n{\n User u when u.IsActive => \"Active user\",\n User u => \"Inactive user\",\n null => \"No user\",\n _ => \"Unknown\"\n};\n\n// Null handling\nstring? nullableString = GetValue();\nstring nonNull = nullableString ?? \"default\";\nint length = nullableString?.Length ?? 0;\n\n// Target-typed new\nList<User> users = new();\nDictionary<string, int> counts = new();\n\n// File-scoped namespaces\nnamespace MyProject.Services;\n\npublic class UserService { }\n```\n\n## Async/Await\n\n```csharp\n// Async methods return Task\npublic async Task<User> GetUserAsync(string id)\n{\n var user = await _repository.FindByIdAsync(id);\n return user ?? throw new NotFoundException(id);\n}\n\n// Async enumerable\npublic async IAsyncEnumerable<User> GetUsersAsync()\n{\n await foreach (var user in _repository.StreamAsync())\n {\n yield return user;\n }\n}\n\n// Cancellation\npublic async Task ProcessAsync(CancellationToken ct)\n{\n ct.ThrowIfCancellationRequested();\n await _service.DoWorkAsync(ct);\n}\n```\n\n## LINQ\n\n```csharp\n// Query syntax\nvar activeUsers = from u in users\n where u.IsActive\n orderby u.Name\n select u;\n\n// Method syntax (preferred)\nvar emails = users\n .Where(u => u.IsActive)\n .OrderBy(u => u.Name)\n .Select(u => u.Email)\n .ToList();\n\n// Grouping\nvar byDepartment = users\n .GroupBy(u => u.Department)\n .ToDictionary(g => g.Key, g => g.ToList());\n```\n\n## Exception Handling\n\n```csharp\n// Custom exceptions\npublic class NotFoundException : Exception\n{\n public NotFoundException(string id)\n : base($\"Entity not found: {id}\") { }\n}\n\n// Try-catch-finally\ntry\n{\n await ProcessAsync();\n}\ncatch (NotFoundException ex) when (ex.Message.Contains(\"user\"))\n{\n _logger.LogWarning(ex, \"User not found\");\n throw;\n}\ncatch (Exception ex)\n{\n _logger.LogError(ex, \"Unexpected error\");\n throw;\n}\n```\n\n## Dependency Injection\n\n```csharp\n// Service registration\nbuilder.Services.AddScoped<IUserRepository, UserRepository>();\nbuilder.Services.AddScoped<IUserService, UserService>();\n\n// Constructor injection\npublic class UserService : IUserService\n{\n private readonly IUserRepository _repository;\n private readonly ILogger<UserService> _logger;\n\n public UserService(IUserRepository repository, ILogger<UserService> logger)\n {\n _repository = repository;\n _logger = logger;\n }\n}\n```\n\n## Testing (xUnit)\n\n```csharp\npublic class UserServiceTests\n{\n private readonly Mock<IUserRepository> _repositoryMock;\n private readonly UserService _sut;\n\n public UserServiceTests()\n {\n _repositoryMock = new Mock<IUserRepository>();\n _sut = new UserService(_repositoryMock.Object);\n }\n\n [Fact]\n public async Task GetUser_WhenExists_ReturnsUser()\n {\n // Arrange\n var user = new User(\"1\", \"test@example.com\", \"Test\");\n _repositoryMock.Setup(r => r.FindByIdAsync(\"1\"))\n .ReturnsAsync(user);\n\n // Act\n var result = await _sut.GetUserAsync(\"1\");\n\n // Assert\n Assert.Equal(\"test@example.com\", result.Email);\n }\n\n [Theory]\n [InlineData(\"\")]\n [InlineData(null)]\n public async Task GetUser_WhenInvalidId_ThrowsArgumentException(string id)\n {\n await Assert.ThrowsAsync<ArgumentException>(\n () => _sut.GetUserAsync(id));\n }\n}\n```\n",
|
|
1427
|
-
"language/csharp/testing.md": "# C# Testing (xUnit)\n\n## Test Structure\n\n```\nMyProject/\n├── src/\n│ └── MyProject/\n│ └── Services/UserService.cs\n└── tests/\n └── MyProject.Tests/\n └── Services/UserServiceTests.cs\n```\n\n## Basic Tests\n\n```csharp\nusing Xunit;\n\npublic class UserServiceTests\n{\n private readonly UserService _sut; // System Under Test\n\n public UserServiceTests()\n {\n _sut = new UserService();\n }\n\n [Fact]\n public void Create_WithValidEmail_ReturnsUser()\n {\n var user = _sut.Create(\"test@example.com\");\n\n Assert.NotNull(user);\n Assert.Equal(\"test@example.com\", user.Email);\n }\n\n [Fact]\n public void Create_WithInvalidEmail_ThrowsValidationException()\n {\n Assert.Throws<ValidationException>(() => _sut.Create(\"invalid\"));\n }\n}\n```\n\n## Assertions\n\n```csharp\n// Equality\nAssert.Equal(expected, actual);\nAssert.NotEqual(unexpected, actual);\n\n// Boolean\nAssert.True(condition);\nAssert.False(condition);\n\n// Null\nAssert.Null(value);\nAssert.NotNull(value);\n\n// Collections\nAssert.Empty(collection);\nAssert.NotEmpty(collection);\nAssert.Contains(item, collection);\nAssert.DoesNotContain(item, collection);\nAssert.All(collection, item => Assert.NotNull(item.Name));\n\n// Type\nAssert.IsType<User>(result);\nAssert.IsAssignableFrom<IEntity>(result);\n\n// Exceptions\nvar ex = Assert.Throws<NotFoundException>(() => service.Find(\"invalid\"));\nAssert.Equal(\"User not found\", ex.Message);\n```\n\n## Theory Tests (Parameterized)\n\n```csharp\n[Theory]\n[InlineData(\"test@example.com\", true)]\n[InlineData(\"invalid\", false)]\n[InlineData(\"\", false)]\npublic void IsValidEmail_WithVariousInputs_ReturnsExpected(string email, bool expected)\n{\n var result = _validator.IsValid(email);\n Assert.Equal(expected, result);\n}\n\n[Theory]\n[MemberData(nameof(GetTestUsers))]\npublic void ProcessUser_WithVariousUsers_ReturnsExpected(User user, string expectedStatus)\n{\n var result = _processor.Process(user);\n Assert.Equal(expectedStatus, result);\n}\n\npublic static IEnumerable<object[]> GetTestUsers()\n{\n yield return new object[] { new User(\"active@example.com\") { IsActive = true }, \"processed\" };\n yield return new object[] { new User(\"inactive@example.com\") { IsActive = false }, \"skipped\" };\n}\n```\n\n## Test Classes and Collections\n\n```csharp\n// Shared context across tests in a class\npublic class UserServiceTests : IClassFixture<DatabaseFixture>\n{\n private readonly DatabaseFixture _fixture;\n\n public UserServiceTests(DatabaseFixture fixture)\n {\n _fixture = fixture;\n }\n\n [Fact]\n public void Test1() { /* uses _fixture */ }\n}\n\n// Shared context across multiple test classes\n[CollectionDefinition(\"Database\")]\npublic class DatabaseCollection : ICollectionFixture<DatabaseFixture> { }\n\n[Collection(\"Database\")]\npublic class UserServiceTests { }\n\n[Collection(\"Database\")]\npublic class OrderServiceTests { }\n```\n\n## Mocking with Moq\n\n```csharp\nusing Moq;\n\npublic class UserServiceTests\n{\n private readonly Mock<IUserRepository> _repositoryMock;\n private readonly Mock<ILogger<UserService>> _loggerMock;\n private readonly UserService _sut;\n\n public UserServiceTests()\n {\n _repositoryMock = new Mock<IUserRepository>();\n _loggerMock = new Mock<ILogger<UserService>>();\n _sut = new UserService(_repositoryMock.Object, _loggerMock.Object);\n }\n\n [Fact]\n public async Task GetUser_WhenExists_ReturnsUser()\n {\n // Arrange\n var user = new User(\"1\", \"test@example.com\");\n _repositoryMock.Setup(r => r.FindByIdAsync(\"1\"))\n .ReturnsAsync(user);\n\n // Act\n var result = await _sut.GetUserAsync(\"1\");\n\n // Assert\n Assert.Equal(\"test@example.com\", result.Email);\n _repositoryMock.Verify(r => r.FindByIdAsync(\"1\"), Times.Once);\n }\n\n [Fact]\n public async Task GetUser_WhenNotFound_ThrowsNotFoundException()\n {\n _repositoryMock.Setup(r => r.FindByIdAsync(It.IsAny<string>()))\n .ReturnsAsync((User?)null);\n\n await Assert.ThrowsAsync<NotFoundException>(\n () => _sut.GetUserAsync(\"invalid\"));\n }\n}\n```\n\n## Async Testing\n\n```csharp\n[Fact]\npublic async Task CreateAsync_WithValidData_ReturnsUser()\n{\n var user = await _sut.CreateAsync(\"test@example.com\");\n\n Assert.NotNull(user);\n Assert.Equal(\"test@example.com\", user.Email);\n}\n\n[Fact]\npublic async Task CreateAsync_WithTimeout_CompletesInTime()\n{\n var task = _sut.CreateAsync(\"test@example.com\");\n var completed = await Task.WhenAny(task, Task.Delay(5000)) == task;\n\n Assert.True(completed, \"Operation timed out\");\n}\n```\n\n## Test Output\n\n```csharp\npublic class UserServiceTests\n{\n private readonly ITestOutputHelper _output;\n\n public UserServiceTests(ITestOutputHelper output)\n {\n _output = output;\n }\n\n [Fact]\n public void Test_WithLogging()\n {\n _output.WriteLine(\"Starting test...\");\n // test logic\n _output.WriteLine($\"Result: {result}\");\n }\n}\n```\n\n## Integration Testing with WebApplicationFactory\n\n```csharp\npublic class UserApiTests : IClassFixture<WebApplicationFactory<Program>>\n{\n private readonly HttpClient _client;\n\n public UserApiTests(WebApplicationFactory<Program> factory)\n {\n _client = factory.WithWebHostBuilder(builder =>\n {\n builder.ConfigureServices(services =>\n {\n // Replace real services with test doubles\n services.AddScoped<IUserRepository, InMemoryUserRepository>();\n });\n }).CreateClient();\n }\n\n [Fact]\n public async Task GetUser_ReturnsUser()\n {\n var response = await _client.GetAsync(\"/api/users/1\");\n\n response.EnsureSuccessStatusCode();\n var user = await response.Content.ReadFromJsonAsync<User>();\n Assert.Equal(\"test@example.com\", user?.Email);\n }\n}\n```\n",
|
|
1428
|
-
"language/go/basics.md": "# Go Fundamentals\n\n## Project Structure\n\n```\nmyproject/\n├── cmd/\n│ └── myapp/\n│ └── main.go # Application entry point\n├── internal/ # Private application code\n│ ├── handler/\n│ ├── service/\n│ └── repository/\n├── pkg/ # Public library code\n├── go.mod\n└── go.sum\n```\n\n## Naming Conventions\n\n```go\n// Package names: lowercase, single word\npackage user\n\n// Exported (public): PascalCase\nfunc CreateUser() {}\ntype UserService struct {}\n\n// Unexported (private): camelCase\nfunc validateEmail() {}\ntype userCache struct {}\n\n// Interfaces: -er suffix when possible\ntype Reader interface {}\ntype UserRepository interface {}\n\n// Constants: PascalCase for exported\nconst MaxRetries = 3\nconst defaultTimeout = 30\n```\n\n## Error Handling\n\n```go\n// Always check errors\nresult, err := doSomething()\nif err != nil {\n return fmt.Errorf(\"failed to do something: %w\", err)\n}\n\n// Custom errors\nvar ErrNotFound = errors.New(\"not found\")\nvar ErrInvalidInput = errors.New(\"invalid input\")\n\n// Error wrapping for context\nif err != nil {\n return fmt.Errorf(\"creating user %s: %w\", name, err)\n}\n\n// Errors.Is and errors.As for checking\nif errors.Is(err, ErrNotFound) {\n // Handle not found\n}\n```\n\n## Concurrency\n\n```go\n// Goroutines for concurrent work\ngo func() {\n // Concurrent task\n}()\n\n// Channels for communication\nch := make(chan int)\nch <- value // Send\nvalue := <-ch // Receive\n\n// Context for cancellation\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\n\n// sync.WaitGroup for coordination\nvar wg sync.WaitGroup\nwg.Add(1)\ngo func() {\n defer wg.Done()\n // Work\n}()\nwg.Wait()\n```\n\n## Testing\n\n```go\n// Test file: user_test.go\nfunc TestCreateUser(t *testing.T) {\n // Arrange\n svc := NewUserService()\n\n // Act\n user, err := svc.Create(\"test@example.com\")\n\n // Assert\n if err != nil {\n t.Fatalf(\"unexpected error: %v\", err)\n }\n if user.Email != \"test@example.com\" {\n t.Errorf(\"got %s, want test@example.com\", user.Email)\n }\n}\n\n// Table-driven tests\nfunc TestValidateEmail(t *testing.T) {\n tests := []struct {\n name string\n email string\n valid bool\n }{\n {\"valid\", \"test@example.com\", true},\n {\"no at\", \"invalid\", false},\n }\n\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n got := ValidateEmail(tt.email)\n if got != tt.valid {\n t.Errorf(\"ValidateEmail(%q) = %v, want %v\", tt.email, got, tt.valid)\n }\n })\n }\n}\n```\n\n## Common Patterns\n\n```go\n// Functional options\ntype Option func(*Config)\n\nfunc WithTimeout(d time.Duration) Option {\n return func(c *Config) { c.Timeout = d }\n}\n\nfunc NewClient(opts ...Option) *Client {\n cfg := defaultConfig()\n for _, opt := range opts {\n opt(&cfg)\n }\n return &Client{config: cfg}\n}\n\n// Interface-based design\ntype UserRepository interface {\n FindByID(ctx context.Context, id string) (*User, error)\n Save(ctx context.Context, user *User) error\n}\n```\n",
|
|
1429
|
-
"language/go/testing.md": "# Go Testing\n\n## Test File Structure\n\n```\nmyproject/\n├── user.go\n├── user_test.go # Tests alongside source\n├── user_internal_test.go # Internal tests (same package)\n└── testdata/ # Test fixtures\n └── fixtures.json\n```\n\n## Test Functions\n\n```go\n// Basic test\nfunc TestCreateUser(t *testing.T) {\n user := CreateUser(\"test@example.com\")\n\n if user.Email != \"test@example.com\" {\n t.Errorf(\"expected email %q, got %q\", \"test@example.com\", user.Email)\n }\n}\n\n// Table-driven tests (preferred)\nfunc TestValidateEmail(t *testing.T) {\n tests := []struct {\n name string\n email string\n wantErr bool\n }{\n {\"valid email\", \"test@example.com\", false},\n {\"missing @\", \"invalid\", true},\n {\"empty\", \"\", true},\n }\n\n for _, tt := range tests {\n t.Run(tt.name, func(t *testing.T) {\n err := ValidateEmail(tt.email)\n if (err != nil) != tt.wantErr {\n t.Errorf(\"ValidateEmail(%q) error = %v, wantErr %v\",\n tt.email, err, tt.wantErr)\n }\n })\n }\n}\n```\n\n## Subtests and Parallel\n\n```go\nfunc TestUserService(t *testing.T) {\n t.Run(\"Create\", func(t *testing.T) {\n t.Parallel() // Run in parallel\n // test create\n })\n\n t.Run(\"Update\", func(t *testing.T) {\n t.Parallel()\n // test update\n })\n}\n```\n\n## Test Helpers\n\n```go\n// Helper function (call t.Helper() first)\nfunc createTestUser(t *testing.T, email string) *User {\n t.Helper()\n user, err := NewUser(email)\n if err != nil {\n t.Fatalf(\"failed to create test user: %v\", err)\n }\n return user\n}\n\n// Cleanup\nfunc TestWithTempFile(t *testing.T) {\n f, err := os.CreateTemp(\"\", \"test\")\n if err != nil {\n t.Fatal(err)\n }\n t.Cleanup(func() { os.Remove(f.Name()) })\n\n // use f...\n}\n```\n\n## Mocking with Interfaces\n\n```go\n// Define interface for dependency\ntype UserRepository interface {\n Save(user *User) error\n FindByID(id string) (*User, error)\n}\n\n// Mock implementation\ntype mockRepository struct {\n users map[string]*User\n saveErr error\n}\n\nfunc (m *mockRepository) Save(user *User) error {\n if m.saveErr != nil {\n return m.saveErr\n }\n m.users[user.ID] = user\n return nil\n}\n\nfunc (m *mockRepository) FindByID(id string) (*User, error) {\n if user, ok := m.users[id]; ok {\n return user, nil\n }\n return nil, ErrNotFound\n}\n\n// Use in tests\nfunc TestUserService_Create(t *testing.T) {\n repo := &mockRepository{users: make(map[string]*User)}\n service := NewUserService(repo)\n\n user, err := service.Create(\"test@example.com\")\n\n if err != nil {\n t.Fatalf(\"unexpected error: %v\", err)\n }\n if _, exists := repo.users[user.ID]; !exists {\n t.Error(\"user not saved to repository\")\n }\n}\n```\n\n## Benchmarks\n\n```go\nfunc BenchmarkProcessUsers(b *testing.B) {\n users := generateTestUsers(1000)\n b.ResetTimer()\n\n for i := 0; i < b.N; i++ {\n ProcessUsers(users)\n }\n}\n\n// Run: go test -bench=. -benchmem\n```\n\n## Test Coverage\n\n```bash\n# Generate coverage\ngo test -coverprofile=coverage.out ./...\n\n# View coverage report\ngo tool cover -html=coverage.out\n\n# Check coverage percentage\ngo test -cover ./...\n```\n\n## Integration Tests\n\n```go\n//go:build integration\n\npackage mypackage_test\n\nimport (\n \"testing\"\n \"database/sql\"\n)\n\nfunc TestDatabaseIntegration(t *testing.T) {\n if testing.Short() {\n t.Skip(\"skipping integration test\")\n }\n\n db, err := sql.Open(\"postgres\", os.Getenv(\"TEST_DATABASE_URL\"))\n if err != nil {\n t.Fatal(err)\n }\n t.Cleanup(func() { db.Close() })\n\n // integration tests...\n}\n\n// Run: go test -tags=integration ./...\n```\n",
|
|
1430
|
-
"language/index.md": "# Language-Specific Guidelines\n\nProgramming language best practices and idioms.\n\n## Available Languages\n\n- `typescript/` - TypeScript guidelines\n- `javascript/` - JavaScript (ES6+) guidelines\n- `python/` - Python guidelines\n- `go/` - Go guidelines\n- `rust/` - Rust guidelines\n- `java/` - Java guidelines\n- `csharp/` - C# guidelines\n- `ruby/` - Ruby guidelines\n",
|
|
1431
|
-
"language/java/basics.md": "# Java Fundamentals\n\n## Project Structure (Maven/Gradle)\n\n```\nmyproject/\n├── src/\n│ ├── main/\n│ │ ├── java/\n│ │ │ └── com/example/\n│ │ │ ├── Application.java\n│ │ │ ├── controller/\n│ │ │ ├── service/\n│ │ │ ├── repository/\n│ │ │ └── model/\n│ │ └── resources/\n│ │ └── application.yml\n│ └── test/\n│ └── java/\n├── pom.xml (Maven) or build.gradle (Gradle)\n```\n\n## Naming Conventions\n\n```java\n// Classes: PascalCase\npublic class UserService {}\n\n// Interfaces: PascalCase, often -able suffix\npublic interface Comparable {}\npublic interface UserRepository {}\n\n// Methods/variables: camelCase\npublic void createUser() {}\nprivate String userName;\n\n// Constants: UPPER_SNAKE_CASE\npublic static final int MAX_RETRIES = 3;\n\n// Packages: lowercase\npackage com.example.service;\n```\n\n## Modern Java Features (17+)\n\n```java\n// Records for immutable data\npublic record User(String id, String email, String name) {}\n\n// Pattern matching\nif (obj instanceof String s) {\n System.out.println(s.length());\n}\n\n// Switch expressions\nString result = switch (status) {\n case ACTIVE -> \"Active\";\n case PENDING -> \"Pending\";\n case DELETED -> \"Deleted\";\n};\n\n// Text blocks\nString json = \"\"\"\n {\n \"name\": \"test\",\n \"value\": 123\n }\n \"\"\";\n\n// Sealed classes\npublic sealed interface Shape permits Circle, Rectangle {}\n```\n\n## Exception Handling\n\n```java\n// Checked exceptions\npublic User findUser(String id) throws UserNotFoundException {\n return repository.findById(id)\n .orElseThrow(() -> new UserNotFoundException(id));\n}\n\n// Try-with-resources\ntry (var reader = new BufferedReader(new FileReader(path))) {\n return reader.readLine();\n} catch (IOException e) {\n throw new DataAccessException(\"Failed to read file\", e);\n}\n\n// Custom exceptions\npublic class UserNotFoundException extends RuntimeException {\n public UserNotFoundException(String id) {\n super(\"User not found: \" + id);\n }\n}\n```\n\n## Optional\n\n```java\n// Avoid null, use Optional\npublic Optional<User> findUser(String id) {\n return Optional.ofNullable(repository.find(id));\n}\n\n// Chaining\nfindUser(id)\n .map(User::getEmail)\n .filter(email -> email.contains(\"@\"))\n .orElse(\"unknown@example.com\");\n\n// Never use Optional in fields or parameters\n// Only for return types\n```\n\n## Streams\n\n```java\n// Filter, map, collect\nList<String> emails = users.stream()\n .filter(u -> u.isActive())\n .map(User::getEmail)\n .collect(Collectors.toList());\n\n// Grouping\nMap<String, List<User>> byDepartment = users.stream()\n .collect(Collectors.groupingBy(User::getDepartment));\n\n// Reduce\nint totalAge = users.stream()\n .mapToInt(User::getAge)\n .sum();\n```\n\n## Testing (JUnit 5)\n\n```java\n@ExtendWith(MockitoExtension.class)\nclass UserServiceTest {\n\n @Mock\n private UserRepository repository;\n\n @InjectMocks\n private UserService service;\n\n @Test\n void shouldCreateUser() {\n // Arrange\n var request = new CreateUserRequest(\"test@example.com\");\n when(repository.save(any())).thenReturn(new User(\"1\", \"test@example.com\"));\n\n // Act\n var user = service.create(request);\n\n // Assert\n assertThat(user.getEmail()).isEqualTo(\"test@example.com\");\n verify(repository).save(any());\n }\n\n @ParameterizedTest\n @ValueSource(strings = {\"invalid\", \"no-at\", \"\"})\n void shouldRejectInvalidEmails(String email) {\n assertThrows(ValidationException.class,\n () -> service.create(new CreateUserRequest(email)));\n }\n}\n```\n\n## Dependency Injection (Spring)\n\n```java\n@Service\npublic class UserService {\n private final UserRepository repository;\n private final EmailService emailService;\n\n // Constructor injection (preferred)\n public UserService(UserRepository repository, EmailService emailService) {\n this.repository = repository;\n this.emailService = emailService;\n }\n}\n```\n",
|
|
1432
|
-
"language/java/testing.md": "# Java Testing (JUnit 5)\n\n## Test Structure\n\n```\nsrc/\n├── main/java/com/example/\n│ └── UserService.java\n└── test/java/com/example/\n └── UserServiceTest.java\n```\n\n## Basic Tests\n\n```java\nimport org.junit.jupiter.api.*;\nimport static org.junit.jupiter.api.Assertions.*;\n\nclass UserServiceTest {\n\n private UserService service;\n\n @BeforeEach\n void setUp() {\n service = new UserService();\n }\n\n @Test\n void createUser_WithValidEmail_ReturnsUser() {\n User user = service.create(\"test@example.com\");\n\n assertEquals(\"test@example.com\", user.getEmail());\n assertNotNull(user.getId());\n }\n\n @Test\n void createUser_WithInvalidEmail_ThrowsException() {\n assertThrows(ValidationException.class, () -> {\n service.create(\"invalid\");\n });\n }\n}\n```\n\n## Assertions\n\n```java\n// Equality\nassertEquals(expected, actual);\nassertNotEquals(unexpected, actual);\n\n// Boolean\nassertTrue(condition);\nassertFalse(condition);\n\n// Null checks\nassertNull(value);\nassertNotNull(value);\n\n// Collections\nassertIterableEquals(expected, actual);\nassertArrayEquals(expectedArray, actualArray);\n\n// Multiple assertions (all run even if some fail)\nassertAll(\n () -> assertEquals(\"John\", user.getName()),\n () -> assertEquals(\"john@example.com\", user.getEmail()),\n () -> assertTrue(user.isActive())\n);\n```\n\n## Parameterized Tests\n\n```java\n@ParameterizedTest\n@ValueSource(strings = {\"\", \" \", \"invalid\", \"no-at-sign\"})\nvoid validateEmail_WithInvalidInput_ReturnsFalse(String email) {\n assertFalse(validator.isValid(email));\n}\n\n@ParameterizedTest\n@CsvSource({\n \"test@example.com, true\",\n \"invalid, false\",\n \"'', false\"\n})\nvoid validateEmail_WithVariousInputs(String email, boolean expected) {\n assertEquals(expected, validator.isValid(email));\n}\n\n@ParameterizedTest\n@MethodSource(\"provideUsersForTest\")\nvoid processUser_WithVariousUsers(User user, String expectedStatus) {\n assertEquals(expectedStatus, processor.process(user));\n}\n\nstatic Stream<Arguments> provideUsersForTest() {\n return Stream.of(\n Arguments.of(new User(\"active@example.com\", true), \"processed\"),\n Arguments.of(new User(\"inactive@example.com\", false), \"skipped\")\n );\n}\n```\n\n## Nested Tests\n\n```java\n@DisplayName(\"UserService\")\nclass UserServiceTest {\n\n @Nested\n @DisplayName(\"create\")\n class Create {\n\n @Test\n @DisplayName(\"with valid email creates user\")\n void withValidEmail() {\n // test\n }\n\n @Test\n @DisplayName(\"with duplicate email throws exception\")\n void withDuplicateEmail() {\n // test\n }\n }\n\n @Nested\n @DisplayName(\"delete\")\n class Delete {\n // delete tests\n }\n}\n```\n\n## Mocking with Mockito\n\n```java\nimport org.mockito.*;\nimport static org.mockito.Mockito.*;\n\n@ExtendWith(MockitoExtension.class)\nclass UserServiceTest {\n\n @Mock\n private UserRepository repository;\n\n @InjectMocks\n private UserService service;\n\n @Test\n void create_SavesUserToRepository() {\n User user = new User(\"test@example.com\");\n when(repository.save(any(User.class))).thenReturn(user);\n\n User result = service.create(\"test@example.com\");\n\n verify(repository).save(any(User.class));\n assertEquals(\"test@example.com\", result.getEmail());\n }\n\n @Test\n void findById_WhenNotFound_ThrowsException() {\n when(repository.findById(\"123\")).thenReturn(Optional.empty());\n\n assertThrows(NotFoundException.class, () -> {\n service.findById(\"123\");\n });\n }\n}\n```\n\n## Lifecycle Hooks\n\n```java\n@BeforeAll\nstatic void initAll() {\n // Run once before all tests\n}\n\n@BeforeEach\nvoid init() {\n // Run before each test\n}\n\n@AfterEach\nvoid tearDown() {\n // Run after each test\n}\n\n@AfterAll\nstatic void tearDownAll() {\n // Run once after all tests\n}\n```\n\n## Async Testing\n\n```java\n@Test\nvoid asyncOperation_CompletesWithinTimeout() {\n assertTimeout(Duration.ofSeconds(2), () -> {\n service.longRunningOperation();\n });\n}\n\n@Test\nvoid asyncOperation_WithCompletableFuture() throws Exception {\n CompletableFuture<User> future = service.createAsync(\"test@example.com\");\n\n User user = future.get(5, TimeUnit.SECONDS);\n assertEquals(\"test@example.com\", user.getEmail());\n}\n```\n\n## Test Tags and Filtering\n\n```java\n@Tag(\"integration\")\n@Test\nvoid databaseIntegrationTest() {\n // integration test\n}\n\n@Tag(\"slow\")\n@Test\nvoid slowPerformanceTest() {\n // slow test\n}\n\n// Run: mvn test -Dgroups=\"integration\"\n// Exclude: mvn test -DexcludedGroups=\"slow\"\n```\n\n## Spring Boot Testing\n\n```java\n@SpringBootTest\nclass UserServiceIntegrationTest {\n\n @Autowired\n private UserService service;\n\n @MockBean\n private EmailService emailService;\n\n @Test\n void create_SendsWelcomeEmail() {\n service.create(\"test@example.com\");\n\n verify(emailService).sendWelcome(any(User.class));\n }\n}\n\n@WebMvcTest(UserController.class)\nclass UserControllerTest {\n\n @Autowired\n private MockMvc mockMvc;\n\n @MockBean\n private UserService service;\n\n @Test\n void getUser_ReturnsUser() throws Exception {\n when(service.findById(\"1\")).thenReturn(new User(\"1\", \"test@example.com\"));\n\n mockMvc.perform(get(\"/users/1\"))\n .andExpect(status().isOk())\n .andExpect(jsonPath(\"$.email\").value(\"test@example.com\"));\n }\n}\n```\n",
|
|
1433
|
-
"language/javascript/basics.md": "# JavaScript Fundamentals\n\n## Project Structure\n\n```\nmyproject/\n├── src/\n│ ├── index.js # Entry point\n│ ├── config/\n│ ├── controllers/\n│ ├── services/\n│ ├── models/\n│ └── utils/\n├── tests/\n├── package.json\n└── .eslintrc.js\n```\n\n## Modern JavaScript (ES6+)\n\n```javascript\n// const/let instead of var\nconst immutable = \"cannot change\";\nlet mutable = \"can change\";\n\n// Arrow functions\nconst add = (a, b) => a + b;\nconst users = data.map(d => new User(d));\n\n// Destructuring\nconst { name, email } = user;\nconst [first, ...rest] = items;\n\n// Spread operator\nconst merged = { ...defaults, ...options };\nconst combined = [...array1, ...array2];\n\n// Template literals\nconst message = `Hello, ${name}!`;\n\n// Optional chaining\nconst avatar = user?.profile?.avatar ?? defaultAvatar;\n\n// Nullish coalescing\nconst value = input ?? defaultValue;\n```\n\n## Async/Await\n\n```javascript\n// Async functions\nasync function fetchUser(id) {\n const response = await fetch(`/api/users/${id}`);\n if (!response.ok) {\n throw new Error(`Failed to fetch user: ${response.status}`);\n }\n return response.json();\n}\n\n// Error handling\nasync function processUser(id) {\n try {\n const user = await fetchUser(id);\n return await processData(user);\n } catch (error) {\n console.error(\"Processing failed:\", error);\n throw error;\n }\n}\n\n// Parallel execution\nconst [users, posts] = await Promise.all([\n fetchUsers(),\n fetchPosts()\n]);\n\n// Promise.allSettled for partial failures\nconst results = await Promise.allSettled([\n fetchUser(1),\n fetchUser(2),\n fetchUser(3)\n]);\n```\n\n## Classes\n\n```javascript\nclass UserService {\n #repository; // Private field\n\n constructor(repository) {\n this.#repository = repository;\n }\n\n async create(data) {\n const user = new User(data);\n await this.#validate(user);\n return this.#repository.save(user);\n }\n\n async #validate(user) {\n if (!user.email) {\n throw new ValidationError(\"Email required\");\n }\n }\n\n static fromConfig(config) {\n return new UserService(new Repository(config));\n }\n}\n```\n\n## Error Handling\n\n```javascript\n// Custom errors\nclass NotFoundError extends Error {\n constructor(id) {\n super(`Not found: ${id}`);\n this.name = \"NotFoundError\";\n this.id = id;\n }\n}\n\nclass ValidationError extends Error {\n constructor(message, field) {\n super(message);\n this.name = \"ValidationError\";\n this.field = field;\n }\n}\n\n// Error handling\nasync function handleRequest(req) {\n try {\n return await processRequest(req);\n } catch (error) {\n if (error instanceof NotFoundError) {\n return { status: 404, message: error.message };\n }\n if (error instanceof ValidationError) {\n return { status: 400, message: error.message, field: error.field };\n }\n throw error; // Re-throw unexpected errors\n }\n}\n```\n\n## Modules\n\n```javascript\n// Named exports\nexport function createUser(data) { }\nexport const MAX_USERS = 100;\n\n// Default export\nexport default class UserService { }\n\n// Imports\nimport UserService from \"./user-service.js\";\nimport { createUser, MAX_USERS } from \"./utils.js\";\nimport * as utils from \"./utils.js\";\n```\n\n## Array Methods\n\n```javascript\n// Map, filter, reduce\nconst emails = users.map(u => u.email);\nconst active = users.filter(u => u.isActive);\nconst total = orders.reduce((sum, o) => sum + o.total, 0);\n\n// Find\nconst user = users.find(u => u.id === targetId);\nconst index = users.findIndex(u => u.id === targetId);\n\n// Some/every\nconst hasAdmin = users.some(u => u.role === \"admin\");\nconst allActive = users.every(u => u.isActive);\n\n// Chaining\nconst result = users\n .filter(u => u.isActive)\n .map(u => u.email)\n .sort();\n```\n\n## Testing (Jest)\n\n```javascript\ndescribe(\"UserService\", () => {\n let repository;\n let service;\n\n beforeEach(() => {\n repository = { save: jest.fn(), find: jest.fn() };\n service = new UserService(repository);\n });\n\n describe(\"create\", () => {\n it(\"creates user with valid data\", async () => {\n repository.save.mockResolvedValue({ id: \"1\", email: \"test@example.com\" });\n\n const user = await service.create({ email: \"test@example.com\" });\n\n expect(user.email).toBe(\"test@example.com\");\n expect(repository.save).toHaveBeenCalled();\n });\n\n it(\"throws on invalid email\", async () => {\n await expect(service.create({ email: \"\" }))\n .rejects\n .toThrow(ValidationError);\n });\n });\n});\n```\n",
|
|
1434
|
-
"language/javascript/testing.md": "# JavaScript Testing (Jest)\n\n## Project Structure\n\n```\nmyproject/\n├── src/\n│ └── services/\n│ └── userService.js\n└── tests/ # or __tests__/\n └── services/\n └── userService.test.js\n```\n\n## Basic Tests\n\n```javascript\nconst { UserService } = require(\"../src/services/userService\");\n\ndescribe(\"UserService\", () => {\n let service;\n\n beforeEach(() => {\n service = new UserService();\n });\n\n describe(\"create\", () => {\n it(\"creates user with valid email\", async () => {\n const user = await service.create({ email: \"test@example.com\" });\n\n expect(user.email).toBe(\"test@example.com\");\n expect(user.id).toBeDefined();\n });\n\n it(\"throws on invalid email\", async () => {\n await expect(service.create({ email: \"invalid\" }))\n .rejects\n .toThrow(ValidationError);\n });\n });\n});\n```\n\n## Matchers\n\n```javascript\n// Equality\nexpect(value).toBe(exact); // ===\nexpect(value).toEqual(deepEqual); // deep equality\nexpect(value).toStrictEqual(obj); // deep + type\n\n// Truthiness\nexpect(value).toBeTruthy();\nexpect(value).toBeFalsy();\nexpect(value).toBeNull();\nexpect(value).toBeUndefined();\nexpect(value).toBeDefined();\n\n// Numbers\nexpect(value).toBeGreaterThan(3);\nexpect(value).toBeLessThanOrEqual(5);\nexpect(value).toBeCloseTo(0.3, 5); // floating point\n\n// Strings\nexpect(string).toMatch(/pattern/);\nexpect(string).toContain(\"substring\");\n\n// Arrays\nexpect(array).toContain(item);\nexpect(array).toHaveLength(3);\nexpect(array).toContainEqual({ id: 1 });\n\n// Objects\nexpect(object).toHaveProperty(\"name\");\nexpect(object).toHaveProperty(\"user.email\", \"test@example.com\");\nexpect(object).toMatchObject({ name: \"John\" });\n\n// Exceptions\nexpect(() => fn()).toThrow();\nexpect(() => fn()).toThrow(ErrorType);\nexpect(() => fn()).toThrow(\"message\");\n```\n\n## Async Testing\n\n```javascript\n// Async/await\nit(\"fetches user\", async () => {\n const user = await service.fetch(\"123\");\n expect(user.id).toBe(\"123\");\n});\n\n// Promises\nit(\"fetches user\", () => {\n return service.fetch(\"123\").then(user => {\n expect(user.id).toBe(\"123\");\n });\n});\n\n// Rejections\nit(\"rejects on not found\", async () => {\n await expect(service.fetch(\"invalid\"))\n .rejects\n .toThrow(NotFoundError);\n});\n```\n\n## Mocking\n\n```javascript\n// Mock functions\nconst mockFn = jest.fn();\nmockFn.mockReturnValue(42);\nmockFn.mockResolvedValue(user);\nmockFn.mockRejectedValue(new Error(\"failed\"));\n\n// Mock implementations\nmockFn.mockImplementation((x) => x * 2);\n\n// Verify calls\nexpect(mockFn).toHaveBeenCalled();\nexpect(mockFn).toHaveBeenCalledWith(\"arg1\", \"arg2\");\nexpect(mockFn).toHaveBeenCalledTimes(2);\n\n// Mock modules\njest.mock(\"../src/services/emailService\");\nconst { EmailService } = require(\"../src/services/emailService\");\nEmailService.prototype.send = jest.fn().mockResolvedValue(true);\n\n// Spy on existing methods\nconst spy = jest.spyOn(console, \"log\");\n// ... test\nspy.mockRestore();\n```\n\n## Testing with Mocked Dependencies\n\n```javascript\ndescribe(\"UserService\", () => {\n let repository;\n let notifier;\n let service;\n\n beforeEach(() => {\n repository = {\n save: jest.fn(),\n find: jest.fn()\n };\n notifier = {\n sendWelcome: jest.fn().mockResolvedValue(true)\n };\n service = new UserService(repository, notifier);\n });\n\n it(\"saves user and sends welcome\", async () => {\n const userData = { email: \"test@example.com\" };\n repository.save.mockResolvedValue({ id: \"1\", ...userData });\n\n const user = await service.create(userData);\n\n expect(repository.save).toHaveBeenCalledWith(expect.objectContaining({\n email: \"test@example.com\"\n }));\n expect(notifier.sendWelcome).toHaveBeenCalledWith(user);\n });\n});\n```\n\n## Setup and Teardown\n\n```javascript\nbeforeAll(() => {\n // Run once before all tests\n});\n\nbeforeEach(() => {\n // Run before each test\n});\n\nafterEach(() => {\n // Run after each test\n jest.clearAllMocks();\n});\n\nafterAll(() => {\n // Run once after all tests\n});\n```\n\n## Snapshot Testing\n\n```javascript\nit(\"renders correctly\", () => {\n const tree = renderer.create(<Button label=\"Click me\" />).toJSON();\n expect(tree).toMatchSnapshot();\n});\n\n// Inline snapshot\nit(\"serializes correctly\", () => {\n expect(user.toJSON()).toMatchInlineSnapshot(`\n {\n \"email\": \"test@example.com\",\n \"id\": \"1\"\n }\n `);\n});\n```\n\n## Test Each (Parameterized)\n\n```javascript\ndescribe(\"validateEmail\", () => {\n it.each([\n [\"test@example.com\", true],\n [\"invalid\", false],\n [\"\", false]\n ])(\"validates %s as %s\", (email, expected) => {\n expect(validateEmail(email)).toBe(expected);\n });\n\n // With named parameters\n it.each`\n email | expected\n ${\"test@example.com\"} | ${true}\n ${\"invalid\"} | ${false}\n `(\"validates $email\", ({ email, expected }) => {\n expect(validateEmail(email)).toBe(expected);\n });\n});\n```\n\n## Timer Mocking\n\n```javascript\njest.useFakeTimers();\n\nit(\"calls callback after delay\", () => {\n const callback = jest.fn();\n\n delayedCall(callback, 1000);\n\n expect(callback).not.toHaveBeenCalled();\n jest.advanceTimersByTime(1000);\n expect(callback).toHaveBeenCalled();\n});\n\nafterEach(() => {\n jest.useRealTimers();\n});\n```\n\n## Running Tests\n\n```bash\n# Run all tests\nnpm test\n\n# Watch mode\nnpm test -- --watch\n\n# Coverage\nnpm test -- --coverage\n\n# Run specific file\nnpm test -- userService.test.js\n\n# Run matching tests\nnpm test -- -t \"creates user\"\n```\n",
|
|
1435
|
-
"language/python/async.md": "# Python Async/Await\n\n## Basic Async Patterns\n\n```python\nimport asyncio\nfrom typing import List\n\n# ✅ Async function definition\nasync def fetch_user(user_id: int) -> User:\n async with aiohttp.ClientSession() as session:\n async with session.get(f\"/users/{user_id}\") as response:\n data = await response.json()\n return User(**data)\n\n# ✅ Running async code\nasync def main():\n user = await fetch_user(1)\n print(user.name)\n\nasyncio.run(main())\n```\n\n## Parallel Execution\n\n```python\n# ❌ Sequential (slow)\nasync def get_all_users(ids: List[int]) -> List[User]:\n users = []\n for user_id in ids:\n user = await fetch_user(user_id) # One at a time\n users.append(user)\n return users\n\n# ✅ Parallel with gather (fast)\nasync def get_all_users(ids: List[int]) -> List[User]:\n tasks = [fetch_user(user_id) for user_id in ids]\n return await asyncio.gather(*tasks) # All at once\n\n# ✅ Parallel with error handling\nasync def get_all_users_safe(ids: List[int]) -> List[User | Exception]:\n tasks = [fetch_user(user_id) for user_id in ids]\n return await asyncio.gather(*tasks, return_exceptions=True)\n```\n\n## Async Context Managers\n\n```python\nfrom contextlib import asynccontextmanager\n\n# ✅ Async context manager\n@asynccontextmanager\nasync def get_connection():\n conn = await database.connect()\n try:\n yield conn\n finally:\n await conn.close()\n\n# Usage\nasync def query_users():\n async with get_connection() as conn:\n return await conn.execute(\"SELECT * FROM users\")\n```\n\n## Timeouts and Cancellation\n\n```python\n# ✅ Add timeouts to prevent hanging\nasync def fetch_with_timeout(url: str, timeout: float = 10.0):\n try:\n async with asyncio.timeout(timeout):\n return await fetch(url)\n except asyncio.TimeoutError:\n raise ServiceError(f\"Request to {url} timed out\")\n\n# ✅ Handle cancellation gracefully\nasync def long_running_task():\n try:\n while True:\n await process_batch()\n await asyncio.sleep(1)\n except asyncio.CancelledError:\n await cleanup()\n raise\n```\n\n## Semaphore for Rate Limiting\n\n```python\n# ✅ Limit concurrent operations\nasync def fetch_all(urls: List[str], max_concurrent: int = 10):\n semaphore = asyncio.Semaphore(max_concurrent)\n\n async def fetch_one(url: str):\n async with semaphore:\n return await fetch(url)\n\n return await asyncio.gather(*[fetch_one(url) for url in urls])\n```\n",
|
|
1436
|
-
"language/python/basics.md": "# Python Fundamentals\n\n## PEP 8 Style Guide\n\n```python\n# Naming conventions\nvariable_name = \"snake_case\" # Variables and functions\nCONSTANT_VALUE = 42 # Constants\nClassName = \"PascalCase\" # Classes\n_private_var = \"internal\" # Private by convention\n\n# Imports - group and order\nimport os # 1. Standard library\nimport sys\n\nimport requests # 2. Third-party\nfrom flask import Flask\n\nfrom myapp.models import User # 3. Local application\nfrom myapp.utils import helper\n```\n\n## String Formatting\n\n```python\n# ✅ Use f-strings (Python 3.6+)\nname = \"Alice\"\nage = 30\nmessage = f\"Hello, {name}! You are {age} years old.\"\n\n# ✅ Multi-line f-strings\nquery = f\"\"\"\n SELECT *\n FROM users\n WHERE name = '{name}'\n AND age > {age - 5}\n\"\"\"\n\n# ❌ Avoid old-style formatting\nmessage = \"Hello, %s!\" % name # Old style\nmessage = \"Hello, {}!\".format(name) # Verbose\n```\n\n## List Comprehensions\n\n```python\n# ✅ Simple and readable\nsquares = [x ** 2 for x in range(10)]\neven_squares = [x ** 2 for x in range(10) if x % 2 == 0]\n\n# ❌ Too complex - use regular loop instead\nresult = [\n transform(item)\n for sublist in nested_list\n for item in sublist\n if condition(item) and another_condition(item)\n]\n\n# ✅ Break into steps when complex\nfiltered_items = [item for sublist in nested_list for item in sublist]\nfiltered_items = [item for item in filtered_items if condition(item)]\nresult = [transform(item) for item in filtered_items]\n```\n\n## Context Managers\n\n```python\n# ✅ Always use context managers for resources\nwith open('file.txt', 'r') as f:\n content = f.read()\n# File automatically closed\n\n# ✅ Database connections\nwith db.connection() as conn:\n cursor = conn.execute(query)\n\n# ✅ Multiple resources\nwith open('input.txt') as infile, open('output.txt', 'w') as outfile:\n outfile.write(infile.read())\n```\n\n## Pythonic Patterns\n\n```python\n# ✅ EAFP (Easier to Ask Forgiveness than Permission)\ntry:\n value = my_dict[key]\nexcept KeyError:\n value = default\n\n# Or simply:\nvalue = my_dict.get(key, default)\n\n# ✅ Truthiness\nif my_list: # Instead of: if len(my_list) > 0\n process(my_list)\n\nif name: # Instead of: if name != \"\"\n greet(name)\n```\n",
|
|
1437
|
-
"language/python/index.md": "# Python Language Guidelines\n\nThis directory contains Python-specific coding guidelines.\n\n## Available Chunks\n\n- **basics.md** - PEP 8, string formatting, comprehensions, context managers\n- **types.md** - Type hints, TypedDict, Protocols, generics\n- **async.md** - async/await, asyncio, parallel execution\n- **testing.md** - pytest fixtures, parametrized tests, mocking\n",
|
|
1438
|
-
"language/python/testing.md": "# Python Testing with pytest\n\n## Basic Test Structure\n\n```python\nimport pytest\nfrom myapp.services import UserService\n\nclass TestUserService:\n def test_create_user_with_valid_data(self):\n # Arrange\n service = UserService()\n user_data = {\"email\": \"test@example.com\", \"name\": \"Test User\"}\n\n # Act\n user = service.create_user(user_data)\n\n # Assert\n assert user.id is not None\n assert user.email == \"test@example.com\"\n\n def test_create_user_with_invalid_email_raises_error(self):\n service = UserService()\n\n with pytest.raises(ValidationError, match=\"Invalid email\"):\n service.create_user({\"email\": \"invalid\", \"name\": \"Test\"})\n```\n\n## Fixtures\n\n```python\nimport pytest\nfrom sqlalchemy import create_engine\n\n@pytest.fixture\ndef db_session():\n \"\"\"Provide a transactional database session.\"\"\"\n engine = create_engine(\"sqlite:///:memory:\")\n Session = sessionmaker(bind=engine)\n session = Session()\n\n yield session\n\n session.rollback()\n session.close()\n\n@pytest.fixture\ndef user_service(db_session):\n \"\"\"Provide UserService with test database.\"\"\"\n return UserService(db_session)\n\n# Usage - fixtures injected automatically\ndef test_find_user(user_service, db_session):\n user = User(email=\"test@example.com\")\n db_session.add(user)\n db_session.commit()\n\n found = user_service.find_by_email(\"test@example.com\")\n assert found.id == user.id\n```\n\n## Parametrized Tests\n\n```python\n@pytest.mark.parametrize(\"age,expected\", [\n (17, False),\n (18, True),\n (21, True),\n (0, False),\n (-1, False),\n])\ndef test_is_adult(age, expected):\n assert is_adult(age) == expected\n\n@pytest.mark.parametrize(\"email\", [\n \"user@example.com\",\n \"user.name@example.co.uk\",\n \"user+tag@example.com\",\n])\ndef test_valid_emails(email):\n assert validate_email(email) is True\n```\n\n## Mocking\n\n```python\nfrom unittest.mock import Mock, patch, AsyncMock\n\ndef test_send_notification(mocker):\n # Mock external service\n mock_email = mocker.patch(\"myapp.services.email_client\")\n mock_email.send.return_value = True\n\n service = NotificationService()\n result = service.send_welcome_email(\"user@example.com\")\n\n assert result is True\n mock_email.send.assert_called_once_with(\n to=\"user@example.com\",\n template=\"welcome\"\n )\n\n# Async mocking\n@pytest.mark.asyncio\nasync def test_fetch_user(mocker):\n mock_client = mocker.patch(\"myapp.api.http_client\")\n mock_client.get = AsyncMock(return_value={\"id\": 1, \"name\": \"Test\"})\n\n user = await fetch_user(1)\n assert user[\"name\"] == \"Test\"\n```\n\n## pytest Configuration\n\n```ini\n# pytest.ini\n[pytest]\ntestpaths = tests\npython_files = test_*.py\npython_functions = test_*\naddopts = -v --tb=short --strict-markers\nmarkers =\n slow: marks tests as slow\n integration: marks tests as integration tests\n```\n",
|
|
1439
|
-
"language/python/types.md": "# Python Type Hints\n\n## Basic Type Annotations\n\n```python\nfrom typing import List, Dict, Optional, Union, Tuple\n\n# Variable annotations\nname: str = \"Alice\"\nage: int = 30\nprices: List[float] = [9.99, 19.99, 29.99]\nuser_scores: Dict[str, int] = {\"alice\": 100, \"bob\": 85}\n\n# Function annotations\ndef greet(name: str, times: int = 1) -> str:\n return f\"Hello, {name}! \" * times\n\ndef find_user(user_id: int) -> Optional[User]:\n \"\"\"Returns User or None if not found.\"\"\"\n return db.get(user_id)\n```\n\n## Modern Python 3.10+ Syntax\n\n```python\n# ✅ Use built-in types directly (Python 3.9+)\ndef process(items: list[str]) -> dict[str, int]:\n return {item: len(item) for item in items}\n\n# ✅ Union syntax with | (Python 3.10+)\ndef parse(value: str | int | None) -> str:\n if value is None:\n return \"\"\n return str(value)\n\n# Instead of:\nfrom typing import Union, Optional\ndef parse(value: Union[str, int, None]) -> str: ...\n```\n\n## TypedDict and Protocols\n\n```python\nfrom typing import TypedDict, Protocol\n\n# ✅ TypedDict for structured dictionaries\nclass UserDict(TypedDict):\n id: int\n name: str\n email: str\n is_active: bool\n\ndef create_user(data: UserDict) -> User:\n return User(**data)\n\n# ✅ Protocol for structural typing (duck typing)\nclass Readable(Protocol):\n def read(self) -> str: ...\n\ndef process_file(file: Readable) -> None:\n content = file.read()\n # Works with any object that has read() method\n```\n\n## Generics\n\n```python\nfrom typing import TypeVar, Generic\n\nT = TypeVar('T')\n\nclass Repository(Generic[T]):\n def __init__(self, model: type[T]) -> None:\n self.model = model\n\n def find(self, id: int) -> T | None:\n return self.db.get(self.model, id)\n\n def save(self, entity: T) -> T:\n return self.db.save(entity)\n\n# Usage\nuser_repo = Repository[User](User)\nuser = user_repo.find(1) # Returns User | None\n```\n\n## Type Checking with mypy\n\n```bash\n# Run type checker\nmypy src/\n\n# mypy.ini configuration\n[mypy]\npython_version = 3.11\nstrict = True\nwarn_return_any = True\nwarn_unused_ignores = True\n```\n",
|
|
1440
|
-
"language/ruby/basics.md": "# Ruby Fundamentals\n\n## Project Structure (Rails)\n\n```\nmyapp/\n├── app/\n│ ├── controllers/\n│ ├── models/\n│ ├── services/\n│ ├── views/\n│ └── jobs/\n├── config/\n├── db/\n│ └── migrate/\n├── lib/\n├── spec/ or test/\n├── Gemfile\n└── Gemfile.lock\n```\n\n## Naming Conventions\n\n```ruby\n# Classes/Modules: PascalCase\nclass UserService\nend\n\nmodule Authentication\nend\n\n# Methods/variables: snake_case\ndef create_user(email)\n user_name = \"test\"\nend\n\n# Constants: SCREAMING_SNAKE_CASE\nMAX_RETRIES = 3\nDEFAULT_TIMEOUT = 30\n\n# Predicate methods: end with ?\ndef valid?\n @errors.empty?\nend\n\n# Dangerous methods: end with !\ndef save!\n raise Error unless save\nend\n\n# Private attr: prefix with _\nattr_reader :_internal_state\n```\n\n## Idiomatic Ruby\n\n```ruby\n# Blocks\nusers.each do |user|\n puts user.name\nend\n\n# Short blocks with &:method\nemails = users.map(&:email)\nactive = users.select(&:active?)\n\n# Safe navigation\nuser&.profile&.avatar_url\n\n# Default values\ndef greet(name = \"World\")\n \"Hello, #{name}!\"\nend\n\n# Keyword arguments\ndef create_user(email:, name: nil, role: :user)\n User.new(email: email, name: name, role: role)\nend\n\n# Multiple return values\ndef parse(input)\n [result, errors]\nend\n\nresult, errors = parse(input)\n```\n\n## Error Handling\n\n```ruby\n# Begin/rescue/ensure\nbegin\n risky_operation\nrescue NetworkError => e\n logger.error(\"Network failed: #{e.message}\")\n retry if should_retry?\nrescue StandardError => e\n logger.error(\"Unexpected error: #{e.message}\")\n raise\nensure\n cleanup\nend\n\n# Custom errors\nclass NotFoundError < StandardError\n attr_reader :id\n\n def initialize(id)\n @id = id\n super(\"Not found: #{id}\")\n end\nend\n\n# Inline rescue (use sparingly)\nvalue = risky_call rescue default_value\n```\n\n## Collections\n\n```ruby\n# Map/Select/Reduce\nemails = users.map { |u| u.email }\nactive = users.select { |u| u.active? }\ntotal = orders.reduce(0) { |sum, o| sum + o.total }\n\n# Chaining\nusers\n .select(&:active?)\n .map(&:email)\n .uniq\n .sort\n\n# Hash operations\ncounts = users.group_by(&:department)\n .transform_values(&:count)\n\n# Find\nuser = users.find { |u| u.id == target_id }\n```\n\n## Classes and Modules\n\n```ruby\n# Service object pattern\nclass CreateUser\n def initialize(repository:, notifier:)\n @repository = repository\n @notifier = notifier\n end\n\n def call(email:, name:)\n user = User.new(email: email, name: name)\n @repository.save(user)\n @notifier.welcome(user)\n user\n end\nend\n\n# Module for shared behavior\nmodule Timestampable\n def created_at\n @created_at ||= Time.now\n end\nend\n\nclass User\n include Timestampable\nend\n```\n\n## Testing (RSpec)\n\n```ruby\nRSpec.describe UserService do\n let(:repository) { instance_double(UserRepository) }\n let(:service) { described_class.new(repository: repository) }\n\n describe \"#create\" do\n context \"with valid email\" do\n it \"creates a user\" do\n allow(repository).to receive(:save)\n\n user = service.create(email: \"test@example.com\")\n\n expect(user.email).to eq(\"test@example.com\")\n expect(repository).to have_received(:save).with(user)\n end\n end\n\n context \"with invalid email\" do\n it \"raises ValidationError\" do\n expect { service.create(email: \"invalid\") }\n .to raise_error(ValidationError)\n end\n end\n end\nend\n```\n\n## Rails Conventions\n\n```ruby\n# Controller\nclass UsersController < ApplicationController\n def create\n @user = User.new(user_params)\n if @user.save\n redirect_to @user, notice: \"User created\"\n else\n render :new, status: :unprocessable_entity\n end\n end\n\n private\n\n def user_params\n params.require(:user).permit(:email, :name)\n end\nend\n\n# Model\nclass User < ApplicationRecord\n validates :email, presence: true, uniqueness: true\n has_many :posts, dependent: :destroy\n scope :active, -> { where(active: true) }\nend\n```\n",
|
|
1441
|
-
"language/ruby/testing.md": "# Ruby Testing (RSpec)\n\n## Project Structure\n\n```\nmyapp/\n├── app/\n│ └── services/\n│ └── user_service.rb\n└── spec/\n ├── spec_helper.rb\n ├── rails_helper.rb # Rails projects\n └── services/\n └── user_service_spec.rb\n```\n\n## Basic Specs\n\n```ruby\nRSpec.describe UserService do\n describe \"#create\" do\n it \"creates a user with valid email\" do\n service = UserService.new\n\n user = service.create(email: \"test@example.com\")\n\n expect(user.email).to eq(\"test@example.com\")\n end\n\n it \"raises error with invalid email\" do\n service = UserService.new\n\n expect { service.create(email: \"invalid\") }\n .to raise_error(ValidationError)\n end\n end\nend\n```\n\n## Let and Subject\n\n```ruby\nRSpec.describe UserService do\n subject(:service) { described_class.new(repository: repository) }\n let(:repository) { instance_double(UserRepository) }\n let(:user) { User.new(email: \"test@example.com\") }\n\n describe \"#find\" do\n before do\n allow(repository).to receive(:find).with(\"1\").and_return(user)\n end\n\n it \"returns the user\" do\n result = service.find(\"1\")\n expect(result).to eq(user)\n end\n end\nend\n```\n\n## Matchers\n\n```ruby\n# Equality\nexpect(actual).to eq(expected)\nexpect(actual).not_to eq(unexpected)\nexpect(actual).to eql(expected) # stricter equality\n\n# Boolean\nexpect(value).to be true\nexpect(value).to be_truthy\nexpect(value).to be_falsy\nexpect(value).to be_nil\n\n# Comparisons\nexpect(value).to be > 5\nexpect(value).to be_between(1, 10)\n\n# Collections\nexpect(array).to include(item)\nexpect(array).to contain_exactly(1, 2, 3)\nexpect(array).to match_array([3, 1, 2])\nexpect(array).to be_empty\nexpect(hash).to have_key(:name)\n\n# Strings\nexpect(string).to start_with(\"Hello\")\nexpect(string).to end_with(\"World\")\nexpect(string).to match(/pattern/)\n\n# Types\nexpect(object).to be_a(User)\nexpect(object).to be_an_instance_of(User)\n\n# Predicates (calls object.active?)\nexpect(user).to be_active\nexpect(user).to have_orders # calls has_orders?\n```\n\n## Contexts and Shared Examples\n\n```ruby\nRSpec.describe UserService do\n describe \"#create\" do\n context \"with valid email\" do\n it \"creates the user\" do\n # test\n end\n\n it \"sends welcome email\" do\n # test\n end\n end\n\n context \"with invalid email\" do\n it \"raises ValidationError\" do\n # test\n end\n end\n end\nend\n\n# Shared examples\nRSpec.shared_examples \"a persisted entity\" do\n it \"has an id\" do\n expect(entity.id).not_to be_nil\n end\n\n it \"has timestamps\" do\n expect(entity.created_at).not_to be_nil\n end\nend\n\nRSpec.describe User do\n let(:entity) { User.create(email: \"test@example.com\") }\n\n it_behaves_like \"a persisted entity\"\nend\n```\n\n## Mocking and Stubbing\n\n```ruby\nRSpec.describe UserService do\n let(:repository) { instance_double(UserRepository) }\n let(:notifier) { instance_double(EmailNotifier) }\n let(:service) { described_class.new(repository: repository, notifier: notifier) }\n\n describe \"#create\" do\n it \"saves user and sends notification\" do\n user = User.new(email: \"test@example.com\")\n\n # Stubbing\n allow(repository).to receive(:save).and_return(user)\n allow(notifier).to receive(:welcome)\n\n result = service.create(email: \"test@example.com\")\n\n # Verification\n expect(repository).to have_received(:save).with(an_instance_of(User))\n expect(notifier).to have_received(:welcome).with(user)\n end\n\n it \"raises when repository fails\" do\n allow(repository).to receive(:save).and_raise(DatabaseError)\n\n expect { service.create(email: \"test@example.com\") }\n .to raise_error(DatabaseError)\n end\n end\nend\n\n# Partial doubles (real objects with stubbed methods)\nRSpec.describe User do\n it \"can stub specific methods\" do\n user = User.new(email: \"test@example.com\")\n allow(user).to receive(:premium?).and_return(true)\n\n expect(user.premium?).to be true\n end\nend\n```\n\n## Before/After Hooks\n\n```ruby\nRSpec.describe UserService do\n before(:all) do\n # Run once before all examples\n DatabaseCleaner.strategy = :transaction\n end\n\n before(:each) do\n # Run before each example\n DatabaseCleaner.start\n end\n\n after(:each) do\n # Run after each example\n DatabaseCleaner.clean\n end\n\n around(:each) do |example|\n # Wrap each example\n Timecop.freeze(Time.local(2024)) do\n example.run\n end\n end\nend\n```\n\n## Testing Rails Controllers\n\n```ruby\nRSpec.describe UsersController, type: :controller do\n describe \"POST #create\" do\n context \"with valid params\" do\n it \"creates a new user\" do\n expect {\n post :create, params: { user: { email: \"test@example.com\" } }\n }.to change(User, :count).by(1)\n end\n\n it \"redirects to the user\" do\n post :create, params: { user: { email: \"test@example.com\" } }\n expect(response).to redirect_to(User.last)\n end\n end\n end\nend\n```\n\n## Request Specs (API Testing)\n\n```ruby\nRSpec.describe \"Users API\", type: :request do\n describe \"GET /api/users/:id\" do\n let(:user) { User.create(email: \"test@example.com\") }\n\n it \"returns the user\" do\n get \"/api/users/#{user.id}\"\n\n expect(response).to have_http_status(:ok)\n expect(JSON.parse(response.body)[\"email\"]).to eq(\"test@example.com\")\n end\n end\nend\n```\n\n## Running Tests\n\n```bash\n# Run all specs\nbundle exec rspec\n\n# Run specific file\nbundle exec rspec spec/services/user_service_spec.rb\n\n# Run specific example\nbundle exec rspec spec/services/user_service_spec.rb:15\n\n# Run with tag\nbundle exec rspec --tag integration\n\n# Run with format\nbundle exec rspec --format documentation\n```\n",
|
|
1442
|
-
"language/rust/basics.md": "# Rust Fundamentals\n\n## Project Structure\n\n```\nmyproject/\n├── src/\n│ ├── main.rs # Binary entry point\n│ ├── lib.rs # Library root\n│ ├── models/\n│ │ └── mod.rs\n│ └── services/\n│ └── mod.rs\n├── tests/ # Integration tests\n├── Cargo.toml\n└── Cargo.lock\n```\n\n## Ownership & Borrowing\n\n```rust\n// Ownership: each value has one owner\nlet s1 = String::from(\"hello\");\nlet s2 = s1; // s1 is moved, no longer valid\n\n// Borrowing: references without ownership\nfn print_len(s: &String) {\n println!(\"{}\", s.len());\n}\n\n// Mutable borrowing (only one at a time)\nfn append(s: &mut String) {\n s.push_str(\" world\");\n}\n\n// Lifetimes: ensure references are valid\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\n```\n\n## Error Handling\n\n```rust\n// Result for recoverable errors\nfn read_file(path: &str) -> Result<String, io::Error> {\n fs::read_to_string(path)\n}\n\n// ? operator for propagation\nfn process_file(path: &str) -> Result<Data, Error> {\n let content = fs::read_to_string(path)?;\n let data = parse(&content)?;\n Ok(data)\n}\n\n// Custom error types\n#[derive(Debug)]\nenum AppError {\n NotFound(String),\n InvalidInput(String),\n Database(sqlx::Error),\n}\n\nimpl From<sqlx::Error> for AppError {\n fn from(err: sqlx::Error) -> Self {\n AppError::Database(err)\n }\n}\n```\n\n## Option & Pattern Matching\n\n```rust\n// Option for nullable values\nfn find_user(id: u64) -> Option<User> {\n users.get(&id).cloned()\n}\n\n// Pattern matching\nmatch find_user(42) {\n Some(user) => println!(\"Found: {}\", user.name),\n None => println!(\"Not found\"),\n}\n\n// if let for single patterns\nif let Some(user) = find_user(42) {\n process(user);\n}\n\n// Combinators\nfind_user(42)\n .map(|u| u.email)\n .unwrap_or_default()\n```\n\n## Traits\n\n```rust\n// Define behavior\ntrait Repository {\n fn find(&self, id: u64) -> Option<Entity>;\n fn save(&mut self, entity: Entity) -> Result<(), Error>;\n}\n\n// Implement for types\nimpl Repository for PostgresRepo {\n fn find(&self, id: u64) -> Option<Entity> {\n // Implementation\n }\n}\n\n// Trait bounds\nfn process<T: Repository + Clone>(repo: T) {\n // Can use Repository and Clone methods\n}\n\n// Default implementations\ntrait Greet {\n fn greet(&self) -> String {\n String::from(\"Hello!\")\n }\n}\n```\n\n## Testing\n\n```rust\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_create_user() {\n let user = User::new(\"test@example.com\");\n assert_eq!(user.email, \"test@example.com\");\n }\n\n #[test]\n #[should_panic(expected = \"invalid email\")]\n fn test_invalid_email_panics() {\n User::new(\"invalid\");\n }\n\n #[test]\n fn test_find_user() -> Result<(), Error> {\n let repo = TestRepo::new();\n let user = repo.find(1)?;\n assert!(user.is_some());\n Ok(())\n }\n}\n```\n\n## Async/Await\n\n```rust\n// Async functions\nasync fn fetch_data(url: &str) -> Result<Data, Error> {\n let response = reqwest::get(url).await?;\n let data = response.json().await?;\n Ok(data)\n}\n\n// Spawning tasks\nlet handle = tokio::spawn(async {\n fetch_data(\"https://api.example.com\").await\n});\n\n// Concurrent execution\nlet (result1, result2) = tokio::join!(\n fetch_data(\"url1\"),\n fetch_data(\"url2\")\n);\n```\n",
|
|
1443
|
-
"language/rust/testing.md": "# Rust Testing\n\n## Test Module Structure\n\n```rust\n// In src/lib.rs or src/user.rs\npub fn create_user(email: &str) -> Result<User, Error> {\n // implementation\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_create_user() {\n let user = create_user(\"test@example.com\").unwrap();\n assert_eq!(user.email, \"test@example.com\");\n }\n}\n```\n\n## Assertions\n\n```rust\n#[test]\nfn test_assertions() {\n // Equality\n assert_eq!(actual, expected);\n assert_ne!(value1, value2);\n\n // Boolean\n assert!(condition);\n assert!(!condition);\n\n // With custom message\n assert_eq!(result, expected, \"failed for input: {}\", input);\n}\n```\n\n## Testing Results and Options\n\n```rust\n#[test]\nfn test_result() -> Result<(), Error> {\n let user = create_user(\"test@example.com\")?;\n assert_eq!(user.email, \"test@example.com\");\n Ok(())\n}\n\n#[test]\nfn test_option() {\n let result = find_user(\"123\");\n assert!(result.is_some());\n assert_eq!(result.unwrap().id, \"123\");\n}\n```\n\n## Testing Panics\n\n```rust\n#[test]\n#[should_panic]\nfn test_panics() {\n divide(1, 0);\n}\n\n#[test]\n#[should_panic(expected = \"division by zero\")]\nfn test_panic_message() {\n divide(1, 0);\n}\n```\n\n## Test Organization\n\n```rust\n#[cfg(test)]\nmod tests {\n use super::*;\n\n mod create {\n use super::*;\n\n #[test]\n fn with_valid_email() {\n // test\n }\n\n #[test]\n fn with_invalid_email() {\n // test\n }\n }\n\n mod update {\n use super::*;\n\n #[test]\n fn existing_user() {\n // test\n }\n }\n}\n```\n\n## Test Fixtures\n\n```rust\nstruct TestContext {\n db: MockDatabase,\n service: UserService,\n}\n\nimpl TestContext {\n fn new() -> Self {\n let db = MockDatabase::new();\n let service = UserService::new(db.clone());\n Self { db, service }\n }\n}\n\n#[test]\nfn test_with_context() {\n let ctx = TestContext::new();\n let user = ctx.service.create(\"test@example.com\").unwrap();\n assert!(ctx.db.contains(&user.id));\n}\n```\n\n## Mocking with Traits\n\n```rust\n// Define trait\ntrait UserRepository {\n fn save(&self, user: &User) -> Result<(), Error>;\n fn find_by_id(&self, id: &str) -> Option<User>;\n}\n\n// Mock implementation\nstruct MockRepository {\n users: RefCell<HashMap<String, User>>,\n}\n\nimpl UserRepository for MockRepository {\n fn save(&self, user: &User) -> Result<(), Error> {\n self.users.borrow_mut().insert(user.id.clone(), user.clone());\n Ok(())\n }\n\n fn find_by_id(&self, id: &str) -> Option<User> {\n self.users.borrow().get(id).cloned()\n }\n}\n\n#[test]\nfn test_service_create() {\n let repo = MockRepository { users: RefCell::new(HashMap::new()) };\n let service = UserService::new(Box::new(repo));\n\n let user = service.create(\"test@example.com\").unwrap();\n assert_eq!(user.email, \"test@example.com\");\n}\n```\n\n## Integration Tests\n\n```\ntests/\n├── integration_test.rs\n└── common/\n └── mod.rs\n```\n\n```rust\n// tests/common/mod.rs\npub fn setup() -> TestDatabase {\n TestDatabase::new()\n}\n\n// tests/integration_test.rs\nmod common;\n\n#[test]\nfn test_database_integration() {\n let db = common::setup();\n // integration test...\n}\n```\n\n## Async Tests\n\n```rust\n#[tokio::test]\nasync fn test_async_create() {\n let service = UserService::new();\n let user = service.create_async(\"test@example.com\").await.unwrap();\n assert_eq!(user.email, \"test@example.com\");\n}\n```\n\n## Running Tests\n\n```bash\n# Run all tests\ncargo test\n\n# Run specific test\ncargo test test_create_user\n\n# Run tests with output\ncargo test -- --nocapture\n\n# Run ignored tests\ncargo test -- --ignored\n\n# Run benchmarks (nightly)\ncargo bench\n```\n",
|
|
1444
|
-
"language/typescript/async.md": "# Async/Await Patterns\n\n## Prefer async/await\n\nAlways use async/await over promise chains:\n\n```typescript\n// ✅ Good\nasync function fetchUser(id: string): Promise<User> {\n const response = await fetch(`/api/users/${id}`);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n return await response.json();\n}\n\n// ❌ Avoid\nfunction fetchUser(id: string): Promise<User> {\n return fetch(`/api/users/${id}`)\n .then(res => res.json());\n}\n```\n\n## Error Handling\n\nAlways wrap async operations in try/catch:\n\n```typescript\nasync function safeOperation(): Promise<Result> {\n try {\n const data = await riskyOperation();\n return { success: true, data };\n } catch (error) {\n logger.error('Operation failed', error);\n return { success: false, error: error.message };\n }\n}\n```\n\n## Parallel Execution\n\nUse `Promise.all()` for independent operations:\n\n```typescript\n// ✅ Good - parallel (fast)\nconst [users, posts, comments] = await Promise.all([\n fetchUsers(),\n fetchPosts(),\n fetchComments()\n]);\n\n// ❌ Bad - sequential (slow)\nconst users = await fetchUsers();\nconst posts = await fetchPosts();\nconst comments = await fetchComments();\n```\n\n## Handling Failures\n\nUse `Promise.allSettled()` when some failures are acceptable:\n\n```typescript\nconst results = await Promise.allSettled([\n fetchData1(),\n fetchData2(),\n fetchData3()\n]);\n\nresults.forEach((result, index) => {\n if (result.status === 'fulfilled') {\n console.log(`Success ${index}:`, result.value);\n } else {\n console.error(`Failed ${index}:`, result.reason);\n }\n});\n```\n\n## Retry Pattern\n\nImplement retry with exponential backoff:\n\n```typescript\nasync function retryWithBackoff<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3\n): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n if (attempt < maxRetries - 1) {\n const delay = 1000 * Math.pow(2, attempt);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError!;\n}\n```\n",
|
|
1445
|
-
"language/typescript/basics.md": "# TypeScript Fundamentals\n\n## Strict Mode (Required)\n\nAlways use strict mode in `tsconfig.json`:\n\n```json\n{\n \"compilerOptions\": {\n \"strict\": true,\n \"noImplicitAny\": true,\n \"strictNullChecks\": true,\n \"strictFunctionTypes\": true\n }\n}\n```\n\n## Type Annotations\n\nUse explicit types for clarity:\n\n```typescript\n// Function signatures\nfunction calculateTotal(items: CartItem[], taxRate: number): number {\n const subtotal = items.reduce((sum, item) => sum + item.price, 0);\n return subtotal * (1 + taxRate);\n}\n\n// Variable declarations\nconst userName: string = \"Alice\";\nconst age: number = 30;\nconst isActive: boolean = true;\n```\n\n## Avoid `any`\n\nNever use `any` - use `unknown` with type guards:\n\n```typescript\n// ❌ Bad\nfunction processData(data: any) {\n return data.value;\n}\n\n// ✅ Good\nfunction processData(data: unknown): string {\n if (typeof data === 'object' && data !== null && 'value' in data) {\n return String(data.value);\n }\n throw new Error('Invalid data structure');\n}\n```\n\n## Type Guards\n\nImplement custom type guards:\n\n```typescript\ninterface User {\n id: string;\n email: string;\n}\n\nfunction isUser(value: unknown): value is User {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'email' in value &&\n typeof value.id === 'string' &&\n typeof value.email === 'string'\n );\n}\n\n// Usage\nif (isUser(data)) {\n console.log(data.email); // Type: User\n}\n```\n\n## Naming Conventions\n\n- Classes/Interfaces: `PascalCase`\n- Functions/Variables: `camelCase`\n- Constants: `UPPER_SNAKE_CASE`\n- Files: `kebab-case.ts`\n- No `I` prefix for interfaces\n",
|
|
1446
|
-
"language/typescript/config.md": "# TypeScript Configuration\n\n## tsconfig.json Best Practices\n\n```json\n{\n \"compilerOptions\": {\n // Strict type checking\n \"strict\": true,\n \"noImplicitAny\": true,\n \"strictNullChecks\": true,\n \"strictFunctionTypes\": true,\n \"strictBindCallApply\": true,\n \"strictPropertyInitialization\": true,\n \"noImplicitThis\": true,\n \"alwaysStrict\": true,\n\n // Additional checks\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noImplicitReturns\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedIndexedAccess\": true,\n\n // Module resolution\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"esModuleInterop\": true,\n \"allowSyntheticDefaultImports\": true,\n \"resolveJsonModule\": true,\n\n // Output\n \"target\": \"ES2022\",\n \"outDir\": \"./dist\",\n \"declaration\": true,\n \"declarationMap\": true,\n \"sourceMap\": true,\n\n // Path aliases\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"src/*\"],\n \"@services/*\": [\"src/services/*\"],\n \"@models/*\": [\"src/models/*\"]\n }\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\", \"**/*.test.ts\"]\n}\n```\n\n## Path Aliases Setup\n\n```typescript\n// With path aliases configured:\nimport { UserService } from '@services/user';\nimport { User } from '@models/user';\n\n// Instead of relative paths:\nimport { UserService } from '../../../services/user';\n```\n\n## Project References (Monorepo)\n\n```json\n// packages/shared/tsconfig.json\n{\n \"compilerOptions\": {\n \"composite\": true,\n \"outDir\": \"./dist\"\n }\n}\n\n// packages/api/tsconfig.json\n{\n \"extends\": \"../../tsconfig.base.json\",\n \"references\": [\n { \"path\": \"../shared\" }\n ]\n}\n```\n\n## Environment-Specific Configs\n\n```json\n// tsconfig.build.json - for production builds\n{\n \"extends\": \"./tsconfig.json\",\n \"compilerOptions\": {\n \"sourceMap\": false,\n \"removeComments\": true\n },\n \"exclude\": [\"**/*.test.ts\", \"**/*.spec.ts\"]\n}\n```\n",
|
|
1447
|
-
"language/typescript/error-handling.md": "# TypeScript Error Handling\n\n## Custom Error Classes\n\n```typescript\n// ✅ Create structured error hierarchy\nclass AppError extends Error {\n constructor(\n message: string,\n public statusCode: number = 500,\n public code: string = 'INTERNAL_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nclass NotFoundError extends AppError {\n constructor(resource: string, id: string) {\n super(`${resource} with id ${id} not found`, 404, 'NOT_FOUND', { resource, id });\n }\n}\n\nclass ValidationError extends AppError {\n constructor(message: string, details: unknown) {\n super(message, 400, 'VALIDATION_ERROR', details);\n }\n}\n```\n\n## Async Error Handling\n\n```typescript\n// ✅ Always handle promise rejections\nasync function fetchUser(id: string): Promise<User> {\n try {\n const response = await api.get(`/users/${id}`);\n return response.data;\n } catch (error) {\n if (error instanceof ApiError && error.status === 404) {\n throw new NotFoundError('User', id);\n }\n throw new AppError('Failed to fetch user', 500, 'FETCH_ERROR', { userId: id });\n }\n}\n\n// ✅ Use wrapper for Express async handlers\nconst asyncHandler = (fn: RequestHandler) => {\n return (req: Request, res: Response, next: NextFunction) => {\n Promise.resolve(fn(req, res, next)).catch(next);\n };\n};\n```\n\n## Result Type Pattern\n\n```typescript\n// ✅ Explicit success/failure without exceptions\ntype Result<T, E = Error> =\n | { success: true; value: T }\n | { success: false; error: E };\n\nfunction parseJSON<T>(json: string): Result<T, string> {\n try {\n return { success: true, value: JSON.parse(json) };\n } catch {\n return { success: false, error: 'Invalid JSON' };\n }\n}\n\n// Usage\nconst result = parseJSON<User>(data);\nif (result.success) {\n console.log(result.value.name);\n} else {\n console.error(result.error);\n}\n```\n\n## Centralized Error Handler\n\n```typescript\n// ✅ Express error middleware\napp.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n if (err instanceof AppError) {\n return res.status(err.statusCode).json({\n error: { message: err.message, code: err.code, details: err.details }\n });\n }\n\n console.error('Unexpected error:', err);\n res.status(500).json({\n error: { message: 'Internal server error', code: 'INTERNAL_ERROR' }\n });\n});\n```\n",
|
|
1448
|
-
"language/typescript/generics.md": "# TypeScript Generics\n\n## Basic Generic Functions\n\n```typescript\n// ✅ Generic function for type-safe operations\nfunction first<T>(array: T[]): T | undefined {\n return array[0];\n}\n\nconst numbers = [1, 2, 3];\nconst firstNumber = first(numbers); // Type: number | undefined\n\nconst users = [{ name: 'John' }];\nconst firstUser = first(users); // Type: { name: string } | undefined\n```\n\n## Generic Interfaces\n\n```typescript\n// ✅ Generic repository pattern\ninterface Repository<T> {\n findById(id: string): Promise<T | null>;\n findAll(): Promise<T[]>;\n create(entity: Omit<T, 'id'>): Promise<T>;\n update(id: string, data: Partial<T>): Promise<T>;\n delete(id: string): Promise<void>;\n}\n\nclass UserRepository implements Repository<User> {\n async findById(id: string): Promise<User | null> {\n return this.db.users.findUnique({ where: { id } });\n }\n // ... other methods\n}\n```\n\n## Generic Constraints\n\n```typescript\n// ✅ Constrain generic types\ninterface HasId {\n id: string;\n}\n\nfunction getById<T extends HasId>(items: T[], id: string): T | undefined {\n return items.find(item => item.id === id);\n}\n\n// Works with any type that has an id\ngetById(users, '123');\ngetById(products, '456');\n```\n\n## Mapped Types\n\n```typescript\n// ✅ Create transformed types\ntype Nullable<T> = {\n [K in keyof T]: T[K] | null;\n};\n\ntype NullableUser = Nullable<User>;\n// { id: string | null; name: string | null; ... }\n\n// ✅ Conditional types\ntype ExtractArrayType<T> = T extends Array<infer U> ? U : never;\n\ntype StringArrayElement = ExtractArrayType<string[]>; // string\n```\n\n## Default Generic Parameters\n\n```typescript\n// ✅ Provide defaults for flexibility\ninterface ApiResponse<T = unknown, E = Error> {\n data?: T;\n error?: E;\n status: number;\n}\n\n// Can use with or without type parameters\nconst response1: ApiResponse<User> = { data: user, status: 200 };\nconst response2: ApiResponse = { status: 500, error: new Error('Failed') };\n```\n",
|
|
1449
|
-
"language/typescript/index.md": "# TypeScript Guidelines\n\nTypeScript-specific best practices for Claude Code.\n\n## Chunks\n\n- `basics.md` - Type system fundamentals and strict mode\n- `interfaces-types.md` - Interfaces vs types, when to use each\n- `generics.md` - Generic programming patterns\n- `async.md` - Async/await and Promise patterns\n- `error-handling.md` - Type-safe error handling\n- `testing.md` - Testing TypeScript code\n- `config.md` - tsconfig.json best practices\n- `performance.md` - Performance optimization\n",
|
|
1450
|
-
"language/typescript/interfaces-types.md": "# TypeScript Types & Interfaces\n\n## Prefer Interfaces for Public APIs\n\n```typescript\n// ✅ Use interfaces for object shapes\ninterface User {\n id: string;\n name: string;\n email: string;\n createdAt: Date;\n}\n\n// ✅ Use type aliases for unions and complex types\ntype UserRole = 'admin' | 'editor' | 'viewer';\ntype ResponseHandler = (response: Response) => void;\n```\n\n## Discriminated Unions\n\n```typescript\n// ✅ Use discriminated unions for variant types\ntype Result<T> =\n | { success: true; data: T }\n | { success: false; error: string };\n\nfunction handleResult(result: Result<User>) {\n if (result.success) {\n console.log(result.data.name); // TypeScript knows data exists\n } else {\n console.error(result.error); // TypeScript knows error exists\n }\n}\n```\n\n## Utility Types\n\n```typescript\n// Use built-in utility types\ntype PartialUser = Partial<User>; // All fields optional\ntype RequiredUser = Required<User>; // All fields required\ntype ReadonlyUser = Readonly<User>; // All fields readonly\ntype UserKeys = keyof User; // 'id' | 'name' | 'email' | 'createdAt'\ntype PickedUser = Pick<User, 'id' | 'name'>; // Only id and name\ntype OmittedUser = Omit<User, 'createdAt'>; // Everything except createdAt\n```\n\n## Type Guards\n\n```typescript\n// ✅ Use type guards for runtime checking\nfunction isUser(value: unknown): value is User {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'email' in value\n );\n}\n\n// Usage\nconst data: unknown = fetchData();\nif (isUser(data)) {\n console.log(data.email); // TypeScript knows it's a User\n}\n```\n\n## Avoid `any`\n\n```typescript\n// ❌ Never use any\nfunction process(data: any) {\n return data.name; // No type safety\n}\n\n// ✅ Use unknown with type guards\nfunction process(data: unknown) {\n if (isUser(data)) {\n return data.name; // Type-safe\n }\n throw new Error('Invalid data');\n}\n```\n",
|
|
1451
|
-
"language/typescript/performance.md": "# TypeScript Performance\n\n## Choose Right Data Structures\n\n```typescript\n// ❌ Array for lookups (O(n))\nconst users: User[] = [];\nconst findUser = (id: string) => users.find(u => u.id === id);\n\n// ✅ Map for O(1) lookups\nconst users = new Map<string, User>();\nconst findUser = (id: string) => users.get(id);\n\n// ❌ Array for membership checks\nconst hasPermission = (perms: string[], perm: string) => perms.includes(perm);\n\n// ✅ Set for O(1) membership\nconst hasPermission = (perms: Set<string>, perm: string) => perms.has(perm);\n```\n\n## Avoid N+1 Queries\n\n```typescript\n// ❌ N+1 queries\nconst getOrdersWithCustomers = async () => {\n const orders = await db.query('SELECT * FROM orders');\n for (const order of orders) {\n order.customer = await db.query('SELECT * FROM customers WHERE id = ?', [order.customerId]);\n }\n return orders;\n};\n\n// ✅ Single JOIN query\nconst getOrdersWithCustomers = async () => {\n return db.query(`\n SELECT orders.*, customers.name as customer_name\n FROM orders\n JOIN customers ON orders.customer_id = customers.id\n `);\n};\n\n// ✅ Using ORM with eager loading\nconst getOrdersWithCustomers = async () => {\n return orderRepository.find({ relations: ['customer'] });\n};\n```\n\n## Parallel Execution\n\n```typescript\n// ❌ Sequential (slow)\nconst getUserData = async (userId: string) => {\n const user = await fetchUser(userId); // 100ms\n const posts = await fetchPosts(userId); // 150ms\n const comments = await fetchComments(userId); // 120ms\n return { user, posts, comments }; // Total: 370ms\n};\n\n// ✅ Parallel (fast)\nconst getUserData = async (userId: string) => {\n const [user, posts, comments] = await Promise.all([\n fetchUser(userId),\n fetchPosts(userId),\n fetchComments(userId)\n ]);\n return { user, posts, comments }; // Total: 150ms\n};\n```\n\n## Memoization\n\n```typescript\nconst memoize = <T extends (...args: any[]) => any>(fn: T): T => {\n const cache = new Map<string, ReturnType<T>>();\n\n return ((...args: any[]) => {\n const key = JSON.stringify(args);\n if (cache.has(key)) return cache.get(key);\n const result = fn(...args);\n cache.set(key, result);\n return result;\n }) as T;\n};\n\nconst expensiveCalc = memoize((n: number) => {\n // Expensive computation\n return result;\n});\n```\n\n## Batch Processing\n\n```typescript\n// ✅ Process in batches\nconst processUsers = async (userIds: string[]) => {\n const BATCH_SIZE = 50;\n\n for (let i = 0; i < userIds.length; i += BATCH_SIZE) {\n const batch = userIds.slice(i, i + BATCH_SIZE);\n await Promise.all(batch.map(id => updateUser(id)));\n }\n};\n```\n",
|
|
1452
|
-
"language/typescript/testing.md": "# TypeScript Testing\n\n## Test Structure: Arrange-Act-Assert\n\n```typescript\ndescribe('UserService', () => {\n describe('createUser', () => {\n it('should create user with hashed password', async () => {\n // Arrange\n const userData = { email: 'test@example.com', password: 'password123' };\n const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };\n const service = new UserService(mockRepo);\n\n // Act\n const result = await service.createUser(userData);\n\n // Assert\n expect(result.id).toBe('1');\n expect(mockRepo.save).toHaveBeenCalledWith(\n expect.objectContaining({ email: 'test@example.com' })\n );\n });\n });\n});\n```\n\n## Test Observable Behavior, Not Implementation\n\n```typescript\n// ❌ Testing implementation details\nit('should call validateEmail method', () => {\n const spy = jest.spyOn(service, 'validateEmail');\n service.createUser({ email: 'test@example.com' });\n expect(spy).toHaveBeenCalled(); // Brittle - breaks if refactored\n});\n\n// ✅ Testing observable behavior\nit('should reject invalid email', async () => {\n await expect(\n service.createUser({ email: 'invalid' })\n ).rejects.toThrow('Invalid email');\n});\n```\n\n## Test Doubles\n\n```typescript\n// Stub: Returns canned responses\nconst stubDatabase = {\n findUser: () => ({ id: '1', name: 'Test User' })\n};\n\n// Mock: Pre-programmed with expectations\nconst mockPayment = {\n charge: jest.fn()\n .mockResolvedValueOnce({ success: true })\n .mockResolvedValueOnce({ success: false })\n};\n\n// Fake: Working implementation (not for production)\nclass FakeDatabase implements Database {\n private data = new Map<string, any>();\n\n async save(id: string, data: any) { this.data.set(id, data); }\n async find(id: string) { return this.data.get(id); }\n}\n```\n\n## One Test Per Condition\n\n```typescript\n// ❌ Multiple assertions for different scenarios\nit('should validate user input', () => {\n expect(() => validate({ age: -1 })).toThrow();\n expect(() => validate({ age: 200 })).toThrow();\n expect(() => validate({ name: '' })).toThrow();\n});\n\n// ✅ One test per condition\nit('should reject negative age', () => {\n expect(() => validate({ age: -1 })).toThrow('Age must be positive');\n});\n\nit('should reject age over 150', () => {\n expect(() => validate({ age: 200 })).toThrow('Age must be under 150');\n});\n```\n\n## Keep Tests Independent\n\n```typescript\n// ✅ Each test is self-contained\nit('should update user', async () => {\n const user = await service.createUser({ name: 'Test' });\n const updated = await service.updateUser(user.id, { name: 'Updated' });\n expect(updated.name).toBe('Updated');\n});\n```\n",
|
|
1453
|
-
"patterns/base-patterns.md": "# Base Patterns\n\n## Value Object\n\nImmutable object defined by its value, not identity.\n\n```typescript\nclass Email {\n private readonly value: string;\n\n constructor(email: string) {\n if (!this.isValid(email)) throw new Error('Invalid email');\n this.value = email.toLowerCase();\n }\n\n equals(other: Email): boolean {\n return this.value === other.value;\n }\n}\n\nclass Money {\n constructor(\n public readonly amount: number,\n public readonly currency: Currency\n ) {\n Object.freeze(this);\n }\n\n add(other: Money): Money {\n this.assertSameCurrency(other);\n return new Money(this.amount + other.amount, this.currency);\n }\n}\n```\n\n## Special Case (Null Object)\n\nReplace null checks with polymorphism.\n\n```typescript\nabstract class Customer {\n abstract getDiscount(): number;\n}\n\nclass RealCustomer extends Customer {\n getDiscount(): number { return 0.1; }\n}\n\nclass GuestCustomer extends Customer {\n getDiscount(): number { return 0; } // No discount\n}\n\n// No null checks needed\nconst customer = repo.findById(id) || new GuestCustomer();\nconst discount = customer.getDiscount();\n```\n\n## Registry\n\nGlobal access point for services.\n\n```typescript\nclass ServiceRegistry {\n private static services = new Map<string, any>();\n\n static register<T>(key: string, service: T): void {\n this.services.set(key, service);\n }\n\n static get<T>(key: string): T {\n return this.services.get(key);\n }\n}\n\n// Prefer dependency injection over registry\n```\n\n## Plugin\n\nExtend behavior without modifying core code.\n\n```typescript\ninterface ValidationPlugin {\n validate(user: User): ValidationResult;\n}\n\nclass UserValidator {\n private plugins: ValidationPlugin[] = [];\n\n registerPlugin(plugin: ValidationPlugin): void {\n this.plugins.push(plugin);\n }\n\n validate(user: User): ValidationResult[] {\n return this.plugins.map(p => p.validate(user));\n }\n}\n```\n\n## Best Practices\n\n- Use Value Objects to avoid primitive obsession\n- Make Value Objects immutable\n- Use Special Case instead of null checks\n- Prefer dependency injection over Registry\n",
|
|
1454
|
-
"patterns/concurrency.md": "# Concurrency Patterns\n\n## Optimistic Locking\n\nDetect conflicts on commit using version numbers.\n\n```typescript\nclass Product {\n constructor(\n public id: string,\n public name: string,\n public version: number = 1\n ) {}\n}\n\nclass ProductRepository {\n async save(product: Product): Promise<void> {\n const result = await this.db.execute(\n `UPDATE products SET name = $1, version = version + 1\n WHERE id = $2 AND version = $3`,\n [product.name, product.id, product.version]\n );\n\n if (result.rowCount === 0) {\n throw new OptimisticLockException('Product was modified');\n }\n product.version++;\n }\n}\n```\n\n## Pessimistic Locking\n\nLock resources before editing.\n\n```typescript\nclass LockManager {\n async acquireLock(resourceId: string, ownerId: string): Promise<boolean> {\n const existing = await this.db.queryOne(\n 'SELECT * FROM locks WHERE resource_id = $1 AND expires_at > NOW()',\n [resourceId]\n );\n\n if (existing) return false;\n\n await this.db.execute(\n 'INSERT INTO locks (resource_id, owner_id, expires_at) VALUES ($1, $2, $3)',\n [resourceId, ownerId, new Date(Date.now() + 30000)]\n );\n return true;\n }\n\n async releaseLock(resourceId: string, ownerId: string): Promise<void> {\n await this.db.execute(\n 'DELETE FROM locks WHERE resource_id = $1 AND owner_id = $2',\n [resourceId, ownerId]\n );\n }\n}\n```\n\n## Coarse-Grained Lock\n\nLock entire aggregate rather than individual entities.\n\n```typescript\nclass OrderRepository {\n async save(order: Order): Promise<void> {\n // Lock aggregate root, all children implicitly locked\n await this.db.execute(\n 'SELECT * FROM orders WHERE id = $1 FOR UPDATE',\n [order.id]\n );\n\n // Update order and all items in single transaction\n await this.updateOrder(order);\n await this.updateOrderItems(order.items);\n }\n}\n```\n\n## Best Practices\n\n- Use optimistic locking for low-contention scenarios\n- Use pessimistic locking for high-contention or critical data\n- Always set lock timeouts\n- Implement retry logic with exponential backoff\n",
|
|
1455
|
-
"patterns/data-access.md": "# Data Access Patterns\n\n## Repository\n\nCollection-like interface for domain objects.\n\n```typescript\ninterface UserRepository {\n findById(id: string): Promise<User | null>;\n findByEmail(email: string): Promise<User | null>;\n save(user: User): Promise<void>;\n delete(user: User): Promise<void>;\n}\n\nclass PostgreSQLUserRepository implements UserRepository {\n async findById(id: string): Promise<User | null> {\n const row = await this.db.queryOne('SELECT * FROM users WHERE id = $1', [id]);\n return row ? this.mapToUser(row) : null;\n }\n}\n```\n\n## Data Mapper\n\nComplete separation between domain and persistence.\n\n```typescript\nclass UserMapper {\n toDomain(row: DbRow): User {\n return new User(row.id, row.name, new Email(row.email));\n }\n\n toDatabase(user: User): DbRow {\n return { id: user.id, name: user.name, email: user.email.toString() };\n }\n}\n```\n\n## Unit of Work\n\nTrack changes and commit together.\n\n```typescript\nclass UnitOfWork {\n private newObjects = new Set<any>();\n private dirtyObjects = new Set<any>();\n\n registerNew(obj: any): void { this.newObjects.add(obj); }\n registerDirty(obj: any): void { this.dirtyObjects.add(obj); }\n\n async commit(): Promise<void> {\n await this.db.beginTransaction();\n try {\n for (const obj of this.newObjects) await this.insert(obj);\n for (const obj of this.dirtyObjects) await this.update(obj);\n await this.db.commit();\n } catch (e) {\n await this.db.rollback();\n throw e;\n }\n }\n}\n```\n\n## Identity Map\n\nEnsure each object loaded only once per session.\n\n```typescript\nclass IdentityMap {\n private map = new Map<string, any>();\n\n get(id: string): any | null { return this.map.get(id) || null; }\n put(id: string, obj: any): void { this.map.set(id, obj); }\n}\n```\n\n## Best Practices\n\n- Return domain objects from repositories\n- Use one repository per aggregate root\n- Keep repositories focused on persistence\n- Don't leak database details into domain\n",
|
|
1456
|
-
"patterns/distribution.md": "# Distribution Patterns\n\n## Remote Facade\n\nCoarse-grained interface to reduce network calls.\n\n```typescript\n// Bad: Multiple network calls\nconst customer = await api.getCustomer(id);\nconst orders = await api.getOrders(id);\nconst addresses = await api.getAddresses(id);\n\n// Good: Single call via facade\nconst details = await api.getCustomerDetails(id);\n// Returns { customer, orders, addresses }\n```\n\n## Data Transfer Object (DTO)\n\nBundle data for transfer across boundaries.\n\n```typescript\ninterface OrderDTO {\n id: string;\n customerId: string;\n items: OrderItemDTO[];\n total: number;\n status: string;\n}\n\nclass OrderDTOMapper {\n static toDTO(order: Order): OrderDTO {\n return {\n id: order.id,\n customerId: order.customer.id,\n items: order.items.map(i => this.itemToDTO(i)),\n total: order.total.amount,\n status: order.status.toString()\n };\n }\n}\n```\n\n## Gateway\n\nAbstract external system access.\n\n```typescript\ninterface PaymentGateway {\n charge(amount: Money, method: PaymentMethod): Promise<PaymentResult>;\n}\n\nclass StripeGateway implements PaymentGateway {\n async charge(amount: Money, method: PaymentMethod): Promise<PaymentResult> {\n const result = await this.stripe.paymentIntents.create({\n amount: amount.cents,\n currency: amount.currency\n });\n return this.mapToResult(result);\n }\n}\n```\n\n## Service Stub\n\nTest double for external services.\n\n```typescript\nclass StubPaymentGateway implements PaymentGateway {\n private shouldSucceed = true;\n\n async charge(amount: Money): Promise<PaymentResult> {\n if (!this.shouldSucceed) throw new PaymentDeclinedError();\n return { success: true, transactionId: 'stub-123' };\n }\n\n configureFail(): void { this.shouldSucceed = false; }\n}\n```\n\n## Best Practices\n\n- Design facades around client use cases\n- Keep DTOs simple and serializable\n- Isolate vendor code in gateways\n- Use stubs for testing, not production\n",
|
|
1457
|
-
"patterns/domain-logic.md": "# Domain Logic Patterns\n\n## Transaction Script\n\nProcedural approach - one procedure per operation.\n\n```typescript\nasync function transferMoney(fromId: string, toId: string, amount: number) {\n const db = await Database.connect();\n await db.beginTransaction();\n\n try {\n const from = await db.query('SELECT * FROM accounts WHERE id = $1', [fromId]);\n if (from.balance < amount) throw new Error('Insufficient funds');\n\n await db.execute('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [amount, fromId]);\n await db.execute('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toId]);\n await db.commit();\n } catch (e) {\n await db.rollback();\n throw e;\n }\n}\n```\n\n**Use for:** Simple apps, CRUD, reports.\n\n## Domain Model\n\nRich objects with behavior.\n\n```typescript\nclass Account {\n constructor(private balance: Money, private overdraftLimit: Money) {}\n\n withdraw(amount: Money): void {\n if (!this.canWithdraw(amount)) throw new InsufficientFundsError();\n this.balance = this.balance.subtract(amount);\n }\n\n transfer(amount: Money, recipient: Account): void {\n this.withdraw(amount);\n recipient.deposit(amount);\n }\n}\n```\n\n**Use for:** Complex business rules, rich domains.\n\n## Service Layer\n\nApplication boundary coordinating domain objects.\n\n```typescript\nclass AccountService {\n constructor(\n private accountRepo: AccountRepository,\n private unitOfWork: UnitOfWork\n ) {}\n\n async transfer(fromId: string, toId: string, amount: Money): Promise<void> {\n const from = await this.accountRepo.findById(fromId);\n const to = await this.accountRepo.findById(toId);\n\n from.transfer(amount, to); // Domain logic\n\n await this.accountRepo.save(from);\n await this.accountRepo.save(to);\n await this.unitOfWork.commit();\n }\n}\n```\n\n**Use for:** API boundaries, multiple clients, transaction coordination.\n\n## Best Practices\n\n- Choose pattern based on complexity\n- Service layer orchestrates, domain model contains logic\n- Keep services thin, domain objects rich\n- Combine Domain Model + Service Layer for complex apps\n",
|
|
1458
|
-
"patterns/gof.md": "# Gang of Four Patterns\n\n## Creational\n\n### Factory Method\n```typescript\ninterface Logger { log(msg: string): void; }\n\nabstract class Application {\n abstract createLogger(): Logger;\n run(): void { this.createLogger().log('Started'); }\n}\n\nclass DevApp extends Application {\n createLogger(): Logger { return new ConsoleLogger(); }\n}\n```\n\n### Builder\n```typescript\nconst query = new QueryBuilder()\n .from('users')\n .select('id', 'name')\n .where('active = true')\n .limit(10)\n .build();\n```\n\n## Structural\n\n### Adapter\n```typescript\nclass PaymentAdapter implements PaymentProcessor {\n constructor(private legacy: OldPaymentSystem) {}\n\n async process(amount: number): Promise<boolean> {\n return this.legacy.makePayment(amount);\n }\n}\n```\n\n### Decorator\n```typescript\ninterface Coffee { cost(): number; }\n\nclass MilkDecorator implements Coffee {\n constructor(private coffee: Coffee) {}\n cost(): number { return this.coffee.cost() + 2; }\n}\n\nlet coffee: Coffee = new SimpleCoffee();\ncoffee = new MilkDecorator(coffee);\n```\n\n### Facade\n```typescript\nclass ComputerFacade {\n start(): void {\n this.cpu.freeze();\n this.memory.load(0, this.hdd.read(0, 1024));\n this.cpu.execute();\n }\n}\n```\n\n## Behavioral\n\n### Strategy\n```typescript\ninterface SortStrategy { sort(data: number[]): number[]; }\n\nclass Sorter {\n constructor(private strategy: SortStrategy) {}\n sort(data: number[]): number[] { return this.strategy.sort(data); }\n}\n```\n\n### Observer\n```typescript\nclass Stock {\n private observers: Observer[] = [];\n\n attach(o: Observer): void { this.observers.push(o); }\n notify(): void { this.observers.forEach(o => o.update(this)); }\n\n setPrice(price: number): void {\n this.price = price;\n this.notify();\n }\n}\n```\n\n### Command\n```typescript\ninterface Command { execute(): void; undo(): void; }\n\nclass AppendCommand implements Command {\n constructor(private editor: Editor, private text: string) {}\n execute(): void { this.editor.append(this.text); }\n undo(): void { this.editor.delete(this.text.length); }\n}\n```\n\n## Best Practices\n\n- Use patterns to solve specific problems, not everywhere\n- Combine patterns when appropriate\n- Favor composition over inheritance\n- Keep implementations simple\n",
|
|
1459
|
-
"patterns/index.md": "# Enterprise Patterns\n\nThis directory contains enterprise application patterns.\n\n## Available Chunks\n\n- **base-patterns.md** - Value Objects, Money, Special Case, Registry, Plugin\n- **concurrency.md** - Optimistic/Pessimistic locking, Coarse-Grained Lock\n- **data-access.md** - Repository, Data Mapper, Active Record, Unit of Work\n- **distribution.md** - Remote Facade, DTO, Gateway, Service Stub\n- **domain-logic.md** - Transaction Script, Domain Model, Service Layer\n- **gof.md** - Gang of Four: Creational, Structural, Behavioral patterns\n",
|
|
1460
|
-
"performance/async.md": "# Async Performance Patterns\n\n## Parallel Execution\n\n```typescript\n// ❌ Sequential - slow\nasync function getUserData(userId: string) {\n const user = await fetchUser(userId); // 100ms\n const posts = await fetchPosts(userId); // 150ms\n const comments = await fetchComments(userId); // 120ms\n return { user, posts, comments }; // Total: 370ms\n}\n\n// ✅ Parallel - fast\nasync function getUserData(userId: string) {\n const [user, posts, comments] = await Promise.all([\n fetchUser(userId),\n fetchPosts(userId),\n fetchComments(userId)\n ]);\n return { user, posts, comments }; // Total: 150ms\n}\n\n// ✅ Partial parallel with dependencies\nasync function getOrderDetails(orderId: string) {\n const order = await fetchOrder(orderId); // Must fetch first\n\n const [customer, items, shipping] = await Promise.all([\n fetchCustomer(order.customerId),\n fetchOrderItems(orderId),\n fetchShippingInfo(orderId)\n ]);\n\n return { order, customer, items, shipping };\n}\n```\n\n## Promise.allSettled for Partial Failures\n\n```typescript\n// Return partial data instead of complete failure\nasync function getDashboard(userId: string) {\n const [user, orders, stats] = await Promise.allSettled([\n getUser(userId),\n getOrders(userId),\n getStats(userId)\n ]);\n\n return {\n user: user.status === 'fulfilled' ? user.value : null,\n orders: orders.status === 'fulfilled' ? orders.value : [],\n stats: stats.status === 'fulfilled' ? stats.value : null,\n errors: {\n user: user.status === 'rejected' ? user.reason.message : null,\n orders: orders.status === 'rejected' ? orders.reason.message : null,\n stats: stats.status === 'rejected' ? stats.reason.message : null\n }\n };\n}\n```\n\n## Batch Processing\n\n```typescript\n// ❌ One at a time - slow\nasync function processUsers(userIds: string[]) {\n for (const id of userIds) {\n await updateUser(id);\n }\n}\n\n// ✅ Batch processing\nasync function processUsers(userIds: string[]) {\n const BATCH_SIZE = 50;\n\n for (let i = 0; i < userIds.length; i += BATCH_SIZE) {\n const batch = userIds.slice(i, i + BATCH_SIZE);\n await Promise.all(batch.map(id => updateUser(id)));\n }\n}\n\n// ✅ Bulk database operations\nasync function createUsers(users: User[]) {\n await db.query(`\n INSERT INTO users (name, email)\n VALUES ${users.map(() => '(?, ?)').join(', ')}\n `, users.flatMap(u => [u.name, u.email]));\n}\n```\n\n## Debouncing and Throttling\n\n```typescript\n// Debounce: Wait until user stops typing\nconst debounce = <T extends (...args: any[]) => any>(\n fn: T,\n delay: number\n): ((...args: Parameters<T>) => void) => {\n let timeoutId: NodeJS.Timeout;\n\n return (...args: Parameters<T>) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n};\n\n// Throttle: Execute at most once per interval\nconst throttle = <T extends (...args: any[]) => any>(\n fn: T,\n limit: number\n): ((...args: Parameters<T>) => void) => {\n let inThrottle: boolean;\n\n return (...args: Parameters<T>) => {\n if (!inThrottle) {\n fn(...args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n};\n\n// Usage\nconst searchUsers = debounce(query => api.search(query), 300);\nconst handleScroll = throttle(() => console.log('scroll'), 100);\n```\n\n## Rate Limiting Concurrent Operations\n\n```typescript\nasync function processWithLimit<T>(\n items: T[],\n fn: (item: T) => Promise<void>,\n concurrency: number\n): Promise<void> {\n const chunks = [];\n for (let i = 0; i < items.length; i += concurrency) {\n chunks.push(items.slice(i, i + concurrency));\n }\n\n for (const chunk of chunks) {\n await Promise.all(chunk.map(fn));\n }\n}\n\n// Usage: Process 100 items, max 10 at a time\nawait processWithLimit(users, updateUser, 10);\n```\n",
|
|
1461
|
-
"performance/basics.md": "# Performance Basics\n\n## Choose the Right Data Structure\n\nDifferent data structures have different speeds for different operations.\n\n### Arrays vs Objects vs Maps\n\n```pseudocode\n// ❌ Slow: Looking up in array (O(n))\nusers = [\n { id: 1, name: 'Alice' },\n { id: 2, name: 'Bob' },\n // ... 1000 more\n]\nuser = users.find(u => u.id == 500) // Checks 500 items\n\n// ✅ Fast: Looking up in Map (O(1))\nusers = Map()\nusers.set(1, { id: 1, name: 'Alice' })\nusers.set(2, { id: 2, name: 'Bob' })\n\nuser = users.get(500) // Instant lookup\n```\n\n### Arrays vs Sets\n\n```pseudocode\n// ❌ Slow: Checking if item exists in array\nitems = [1, 2, 3, 4, 5, ... 1000 more]\nif items.contains(500): // Checks every item\n\n// ✅ Fast: Checking if item exists in Set\nitems = Set([1, 2, 3, 4, 5, ... 1000 more])\nif items.has(500): // Instant check\n```\n\n### When to Use Each\n\n| Data Structure | Good For |\n|----------------|----------|\n| **Array/List** | Ordered items, iteration |\n| **Object/Dict** | Key-value pairs (string keys) |\n| **Map** | Key-value pairs (any type keys), frequent lookups |\n| **Set** | Unique values, membership checks |\n\n## Avoid N+1 Queries\n\nOne of the most common performance problems.\n\n```pseudocode\n// ❌ BAD: N+1 queries (1 + N database calls)\norders = database.query(\"SELECT * FROM orders\")\n\nfor each order in orders:\n // Separate query for EACH order! 😱\n customer = database.query(\n \"SELECT * FROM customers WHERE id = ?\",\n [order.customer_id]\n )\n order.customer = customer\n// If 100 orders = 101 database calls!\n\n// ✅ GOOD: Single query with JOIN\nordersWithCustomers = database.query(\"\n SELECT\n orders.*,\n customers.name as customer_name,\n customers.email as customer_email\n FROM orders\n JOIN customers ON orders.customer_id = customers.id\n\")\n// Only 1 database call!\n```\n\n## Don't Load What You Don't Need\n\n```pseudocode\n// ❌ Bad: Fetching entire object when you only need one field\nuser = database.query(\"SELECT * FROM users WHERE id = ?\", [id])\nprint(user.email)\n\n// ✅ Good: Fetch only what you need\nresult = database.query(\n \"SELECT email FROM users WHERE id = ?\",\n [id]\n)\nprint(result.email)\n\n// ❌ Bad: Loading all records\nusers = database.query(\"SELECT * FROM users\")\n\n// ✅ Good: Add LIMIT\nusers = database.query(\"SELECT * FROM users LIMIT 100\")\n```\n\n## Use Async for I/O Operations\n\nDon't block the program waiting for slow operations.\n\n```pseudocode\n// ❌ Slow: Blocking operations (synchronous)\nfile1 = readFileSync(\"file1.txt\")\nfile2 = readFileSync(\"file2.txt\")\nfile3 = readFileSync(\"file3.txt\")\n// Total: 300ms (100ms each, one after another)\n\n// ✅ Fast: Async operations (parallel)\nfiles = await Promise.all([\n readFile(\"file1.txt\"),\n readFile(\"file2.txt\"),\n readFile(\"file3.txt\")\n])\n// Total: 100ms (all at once)\n```\n\n## Avoid Unnecessary Work in Loops\n\n```pseudocode\n// ❌ Bad: Work done every iteration\nfor i in 0 to items.length:\n total = calculateTotal(items) // Recalculated each time!\n if items[i].price > total * 0.1:\n // ...\n\n// ✅ Good: Work done once\ntotal = calculateTotal(items)\nfor i in 0 to items.length:\n if items[i].price > total * 0.1:\n // ...\n\n// ❌ Bad: Array length calculated each time\nfor i in 0 to items.length:\n // ...\n\n// ✅ Good: Length cached (minor improvement)\nlen = items.length\nfor i in 0 to len:\n // ...\n\n// ✅ Best: Modern for-each loop\nfor each item in items:\n // ...\n```\n\n## Index Your Database\n\nIndexes make lookups fast, but slow down writes.\n\n```sql\n-- Without index: Checks every row\nSELECT * FROM users WHERE email = 'alice@example.com';\n-- With 1 million users: ~1 second\n\n-- Add index\nCREATE INDEX idx_users_email ON users(email);\n\n-- Now same query is instant\nSELECT * FROM users WHERE email = 'alice@example.com';\n-- With 1 million users: ~1 millisecond\n```\n\n### When to Add Indexes\n\n- Columns used in WHERE clauses\n- Columns used in JOIN conditions\n- Columns used in ORDER BY\n\n```sql\n-- Frequently queried\nCREATE INDEX idx_orders_status ON orders(status);\nCREATE INDEX idx_users_email ON users(email);\n\n-- Used in joins\nCREATE INDEX idx_orders_customer_id ON orders(customer_id);\n```\n\n## Cache Expensive Results\n\nDon't recalculate the same thing repeatedly.\n\n```pseudocode\n// ❌ Bad: Calculating every time\nfunction getReport(userId):\n data = expensiveCalculation(userId) // 5 seconds\n return data\n\n// Called 100 times = 500 seconds!\n\n// ✅ Good: Cache results\ncache = Map()\n\nfunction getReport(userId):\n if cache.has(userId):\n return cache.get(userId) // Instant\n\n data = expensiveCalculation(userId)\n cache.set(userId, data)\n return data\n\n// First call: 5 seconds, next 99 calls: instant\n```\n\n## Batch Operations\n\nProcess multiple items together instead of one at a time.\n\n```pseudocode\n// ❌ Bad: Individual database calls\nfor each user in users:\n database.execute(\"INSERT INTO users (name) VALUES (?)\", [user.name])\n// 100 users = 100 database calls\n\n// ✅ Good: Batch insert\ndatabase.execute(\"\n INSERT INTO users (name)\n VALUES \" + users.map(u => \"(?)\").join(\", \"),\n users.map(u => u.name)\n)\n// 100 users = 1 database call\n```\n\n## Profile Before Optimizing\n\nDon't guess where the problem is - measure!\n\n```pseudocode\n// Measure execution time\nstartTime = currentTime()\nresult = await slowOperation()\nendTime = currentTime()\nprint(\"Operation took:\", endTime - startTime, \"ms\")\n\n// Measure specific parts\nstartDB = currentTime()\ndata = await database.query(\"...\")\nprint(\"Database:\", currentTime() - startDB, \"ms\")\n\nstartProcess = currentTime()\nprocessed = processData(data)\nprint(\"Processing:\", currentTime() - startProcess, \"ms\")\n```\n\n## Common Performance Mistakes\n\n### Mistake 1: Nested Loops with Database Queries\n\n```pseudocode\n// ❌ TERRIBLE: Nested queries\nfor each user in users:\n for each order in orders:\n product = await database.query(\n \"SELECT * FROM products WHERE id = ?\",\n [order.product_id]\n )\n// 100 users × 50 orders = 5000 database calls!\n\n// ✅ GOOD: Load all data first\nproducts = await database.query(\"SELECT * FROM products\")\nproductMap = Map()\nfor each p in products:\n productMap.set(p.id, p)\n\nfor each user in users:\n for each order in orders:\n product = productMap.get(order.product_id) // Instant\n```\n\n### Mistake 2: Loading Everything into Memory\n\n```pseudocode\n// ❌ Bad: Loading 1 million records\nallUsers = await database.query(\"SELECT * FROM users\")\n// Crashes with out of memory!\n\n// ✅ Good: Process in batches\nBATCH_SIZE = 1000\noffset = 0\n\nwhile true:\n users = await database.query(\n \"SELECT * FROM users LIMIT ? OFFSET ?\",\n [BATCH_SIZE, offset]\n )\n\n if users.length == 0:\n break\n\n await processUsers(users)\n offset = offset + BATCH_SIZE\n```\n\n### Mistake 3: Not Using Indexes\n\n```sql\n-- ❌ Slow: No index on email column\nSELECT * FROM users WHERE email = 'alice@example.com';\n-- 1 million rows: ~2 seconds\n\n-- ✅ Fast: Add index\nCREATE INDEX idx_users_email ON users(email);\n-- Same query: ~2 milliseconds\n```\n\n## Quick Performance Checklist\n\n- [ ] Use Map/Set for lookups instead of Array\n- [ ] Avoid N+1 queries (use JOINs)\n- [ ] Add database indexes on frequently queried columns\n- [ ] Don't load all records (use LIMIT)\n- [ ] Cache expensive calculations\n- [ ] Run independent operations in parallel\n- [ ] Move work outside of loops\n- [ ] Batch database operations\n- [ ] Profile before optimizing\n\n## When to Optimize\n\n1. **Measure first** - Is there actually a problem?\n2. **Find the bottleneck** - What's slow?\n3. **Fix the biggest problem** - Don't waste time on small gains\n4. **Measure again** - Did it help?\n\nDon't optimize prematurely - write clear code first, optimize when needed!\n",
|
|
1462
|
-
"performance/caching-strategies.md": "# Caching Strategies\n\n## Cache Patterns\n\n### Cache-Aside (Lazy Loading)\n```typescript\nasync function getUser(id: string): Promise<User> {\n const cached = await cache.get(`user:${id}`);\n if (cached) return cached;\n\n const user = await db.findUser(id);\n await cache.set(`user:${id}`, user, { ttl: 3600 });\n return user;\n}\n```\n\n### Write-Through\n```typescript\nasync function updateUser(user: User): Promise<void> {\n await db.saveUser(user);\n await cache.set(`user:${user.id}`, user);\n}\n```\n\n### Write-Behind (Write-Back)\n```typescript\nasync function updateUser(user: User): Promise<void> {\n await cache.set(`user:${user.id}`, user);\n await queue.add('sync-to-db', { user }); // Async persistence\n}\n```\n\n## Cache Invalidation\n\n```typescript\n// Time-based expiration\nawait cache.set('key', value, { ttl: 3600 });\n\n// Event-based invalidation\neventBus.on('user.updated', async (userId) => {\n await cache.delete(`user:${userId}`);\n});\n\n// Pattern-based invalidation\nawait cache.deleteByPattern('user:*');\n```\n\n## HTTP Caching\n\n```typescript\n// Cache-Control headers\nres.setHeader('Cache-Control', 'public, max-age=3600');\nres.setHeader('ETag', etag(content));\n\n// Conditional requests\nif (req.headers['if-none-match'] === currentEtag) {\n return res.status(304).end();\n}\n```\n\n## Best Practices\n\n- Cache at appropriate layers (CDN, app, DB)\n- Use consistent cache keys\n- Set appropriate TTLs\n- Monitor cache hit rates\n- Plan for cache failures (fallback to source)\n- Avoid caching sensitive data\n",
|
|
1463
|
-
"performance/caching.md": "# Caching Strategies\n\n## In-Memory Caching\n\n```typescript\nclass Cache<T> {\n private cache = new Map<string, { value: T; expiry: number }>();\n\n set(key: string, value: T, ttlMs: number = 60000): void {\n this.cache.set(key, {\n value,\n expiry: Date.now() + ttlMs\n });\n }\n\n get(key: string): T | null {\n const item = this.cache.get(key);\n if (!item) return null;\n\n if (Date.now() > item.expiry) {\n this.cache.delete(key);\n return null;\n }\n\n return item.value;\n }\n}\n\n// Usage\nconst userCache = new Cache<User>();\n\nasync function getUser(id: string): Promise<User> {\n const cached = userCache.get(id);\n if (cached) return cached;\n\n const user = await db.findUser(id);\n userCache.set(id, user, 300000); // 5 minutes\n return user;\n}\n```\n\n## Redis Caching\n\n```typescript\nimport Redis from 'ioredis';\n\nconst redis = new Redis();\n\nasync function getCachedUser(id: string): Promise<User | null> {\n const cached = await redis.get(`user:${id}`);\n if (cached) return JSON.parse(cached);\n\n const user = await db.findUser(id);\n await redis.setex(`user:${id}`, 300, JSON.stringify(user)); // 5 min TTL\n return user;\n}\n\n// Cache invalidation on update\nasync function updateUser(id: string, data: Partial<User>) {\n const user = await db.updateUser(id, data);\n await redis.del(`user:${id}`); // Invalidate cache\n return user;\n}\n```\n\n## HTTP Caching\n\n```typescript\n// Cache-Control headers\napp.get('/api/products', (req, res) => {\n res.set('Cache-Control', 'public, max-age=300'); // 5 minutes\n res.json(products);\n});\n\n// ETag for conditional requests\napp.get('/api/user/:id', async (req, res) => {\n const user = await getUser(req.params.id);\n const etag = generateETag(user);\n\n res.set('ETag', etag);\n\n if (req.headers['if-none-match'] === etag) {\n return res.status(304).end(); // Not Modified\n }\n\n res.json(user);\n});\n```\n\n## Cache-Aside Pattern\n\n```typescript\n// Also called \"lazy loading\"\nasync function getProduct(id: string): Promise<Product> {\n // 1. Check cache\n const cached = await redis.get(`product:${id}`);\n if (cached) return JSON.parse(cached);\n\n // 2. Cache miss - load from database\n const product = await db.findProduct(id);\n\n // 3. Store in cache\n await redis.setex(`product:${id}`, 600, JSON.stringify(product));\n\n return product;\n}\n```\n\n## Memoization\n\n```typescript\nconst memoize = <T extends (...args: any[]) => any>(fn: T): T => {\n const cache = new Map<string, ReturnType<T>>();\n\n return ((...args: any[]) => {\n const key = JSON.stringify(args);\n if (cache.has(key)) return cache.get(key);\n\n const result = fn(...args);\n cache.set(key, result);\n return result;\n }) as T;\n};\n\n// Cache expensive computations\nconst calculateDiscount = memoize((price: number, tier: string) => {\n // Complex calculation\n return result;\n});\n```\n\n## Cache Invalidation Strategies\n\n```typescript\n// Time-based expiry\nawait redis.setex(key, 300, value); // Expires after 5 minutes\n\n// Event-based invalidation\nasync function updateProduct(id: string, data: ProductUpdate) {\n await db.updateProduct(id, data);\n await redis.del(`product:${id}`);\n await redis.del('products:list'); // Invalidate list cache too\n}\n\n// Cache warming\nasync function warmCache() {\n const popularProducts = await db.getMostViewed(100);\n for (const product of popularProducts) {\n await redis.setex(`product:${product.id}`, 3600, JSON.stringify(product));\n }\n}\n```\n",
|
|
1464
|
-
"performance/index.md": "# Performance Guidelines\n\nThis directory contains performance optimization patterns.\n\n## Available Chunks\n\n- **caching.md** - In-memory, Redis, HTTP caching, memoization\n- **async.md** - Parallel execution, batching, debouncing, throttling\n",
|
|
1465
|
-
"practices/code-review.md": "# Code Review Practices\n\n## Review Checklist\n\n- [ ] Code follows project style guidelines\n- [ ] No obvious bugs or logic errors\n- [ ] Error handling is appropriate\n- [ ] Tests cover new functionality\n- [ ] No security vulnerabilities introduced\n- [ ] Performance implications considered\n- [ ] Documentation updated if needed\n\n## Giving Feedback\n\n**Good:**\n```\nConsider using `Array.find()` here instead of `filter()[0]` -\nit's more readable and stops at the first match.\n```\n\n**Bad:**\n```\nThis is wrong.\n```\n\n## PR Description Template\n\n```markdown\n## Summary\nBrief description of changes\n\n## Changes\n- Added X feature\n- Fixed Y bug\n- Refactored Z\n\n## Testing\n- [ ] Unit tests added\n- [ ] Manual testing performed\n\n## Screenshots (if UI changes)\n```\n\n## Best Practices\n\n- Review promptly (within 24 hours)\n- Focus on logic and design, not style (use linters)\n- Ask questions rather than make demands\n- Praise good solutions\n- Keep PRs small and focused\n- Use \"nitpick:\" prefix for minor suggestions\n- Approve with minor comments when appropriate\n",
|
|
1466
|
-
"practices/documentation.md": "# Documentation Organization\n\n## Keep Root Clean\n\n**RULE: Documentation must NOT clutter the project root.**\n\n```\n❌ BAD: Root folder mess\nproject/\n├── README.md\n├── ARCHITECTURE.md\n├── API_DOCS.md\n├── DEPLOYMENT.md\n├── TROUBLESHOOTING.md\n├── USER_GUIDE.md\n├── DATABASE_SCHEMA.md\n├── TESTING_GUIDE.md\n└── ... (20 more .md files)\n\n✅ GOOD: Organized structure\nproject/\n├── README.md (overview only)\n├── docs/\n│ ├── architecture/\n│ ├── api/\n│ ├── deployment/\n│ └── guides/\n└── src/\n```\n\n## Documentation Structure\n\n**Standard documentation folder:**\n\n```\ndocs/\n├── architecture/\n│ ├── overview.md\n│ ├── decisions/ # Architecture Decision Records\n│ │ ├── 001-database-choice.md\n│ │ └── 002-api-design.md\n│ └── diagrams/\n│\n├── api/\n│ ├── endpoints.md\n│ ├── authentication.md\n│ └── examples/\n│\n├── guides/\n│ ├── getting-started.md\n│ ├── development.md\n│ ├── deployment.md\n│ └── troubleshooting.md\n│\n├── features/ # Organize by feature\n│ ├── user-auth/\n│ │ ├── overview.md\n│ │ ├── implementation.md\n│ │ └── testing.md\n│ ├── payments/\n│ └── notifications/\n│\n└── planning/ # Active work planning\n ├── memory-lane.md # Context preservation\n ├── current-phase.md # Active work\n └── next-steps.md # Backlog\n```\n\n## Memory Lane Document\n\n**CRITICAL: Maintain context across sessions**\n\n### Purpose\nWhen AI context limit is reached, reload from memory lane to restore working context.\n\n### Structure\n\n```markdown\n# Memory Lane - Project Context\n\n## Last Updated\n2024-12-10 15:30\n\n## Current Objective\nImplementing user authentication system with OAuth2 support\n\n## Recent Progress\n- ✅ Set up database schema (2024-12-08)\n- ✅ Implemented user registration (2024-12-09)\n- 🔄 Working on: OAuth2 integration (2024-12-10)\n- ⏳ Next: Session management\n\n## Key Decisions\n1. **Database**: PostgreSQL chosen for ACID compliance\n2. **Auth Strategy**: OAuth2 + JWT tokens\n3. **Session Store**: Redis for performance\n\n## Important Files\n- `src/auth/oauth.ts` - OAuth2 implementation (IN PROGRESS)\n- `src/models/user.ts` - User model and validation\n- `docs/architecture/decisions/003-auth-system.md` - Full context\n\n## Active Questions\n1. Should we support refresh tokens? (Pending user decision)\n2. Token expiry: 1h or 24h? (Pending user decision)\n\n## Technical Context\n- Using Passport.js for OAuth\n- Google and GitHub providers configured\n- Callback URLs: /auth/google/callback, /auth/github/callback\n\n## Known Issues\n- OAuth redirect not working in development (investigating)\n- Need to add rate limiting to prevent abuse\n\n## Next Session\n1. Fix OAuth redirect issue\n2. Implement refresh token rotation\n3. Add comprehensive auth tests\n```\n\n### Update Frequency\n- Update after each significant milestone\n- Update before context limit is reached\n- Update when switching between features\n\n## Context Reload Strategy\n\n**For AI Tools with Hooks:**\n\nCreate a hook to reload memory lane on startup:\n\n```json\n{\n \"hooks\": {\n \"startup\": {\n \"command\": \"cat docs/planning/memory-lane.md\"\n }\n }\n}\n```\n\n**For AI Tools with Agents:**\n\nCreate a context restoration agent:\n\n```markdown\n# Context Restoration Agent\n\nTask: Read and summarize current project state\n\nSources:\n1. docs/planning/memory-lane.md\n2. docs/architecture/decisions/ (recent ADRs)\n3. git log --oneline -10 (recent commits)\n\nOutput: Concise summary of where we are and what's next\n```\n\n## Feature Documentation\n\n**Organize by feature/scope, not by type:**\n\n```\n❌ BAD: Organized by document type\ndocs/\n├── specifications/\n│ ├── auth.md\n│ ├── payments.md\n│ └── notifications.md\n├── implementations/\n│ ├── auth.md\n│ ├── payments.md\n│ └── notifications.md\n└── tests/\n ├── auth.md\n └── payments.md\n\n✅ GOOD: Organized by feature\ndocs/features/\n├── auth/\n│ ├── specification.md\n│ ├── implementation.md\n│ ├── api.md\n│ └── testing.md\n├── payments/\n│ ├── specification.md\n│ ├── implementation.md\n│ └── providers.md\n└── notifications/\n ├── specification.md\n └── channels.md\n```\n\n**Benefits:**\n- All related docs in one place\n- Easy to find feature-specific information\n- Natural scope boundaries\n- Easier to maintain\n\n## Planning Documents\n\n**Active planning should be in docs/planning/:**\n\n```\ndocs/planning/\n├── memory-lane.md # Context preservation\n├── current-sprint.md # Active work\n├── backlog.md # Future work\n└── spike-results/ # Research findings\n ├── database-options.md\n └── auth-libraries.md\n```\n\n## Documentation Principles\n\n1. **Separate folder**: All docs in `docs/` directory\n2. **Organize by scope**: Group by feature, not document type\n3. **Keep root clean**: Only README.md in project root\n4. **Maintain memory lane**: Update regularly for context preservation\n5. **Link related docs**: Use relative links between related documents\n\n## README Guidelines\n\n**Root README should be concise:**\n\n```markdown\n# Project Name\n\nBrief description\n\n## Quick Start\n[Link to docs/guides/getting-started.md]\n\n## Documentation\n- [Architecture](docs/architecture/overview.md)\n- [API Docs](docs/api/endpoints.md)\n- [Development Guide](docs/guides/development.md)\n\n## Contributing\n[Link to CONTRIBUTING.md or docs/guides/contributing.md]\n```\n\n**Keep it short, link to detailed docs.**\n\n## Anti-Patterns\n\n❌ **Don't:**\n- Put 10+ markdown files in project root\n- Mix documentation types in same folder\n- Forget to update memory lane before context expires\n- Create documentation without clear organization\n- Duplicate information across multiple docs\n\n✅ **Do:**\n- Use `docs/` directory for all documentation\n- Organize by feature/scope\n- Maintain memory lane for context preservation\n- Link related documents together\n- Update docs as code evolves\n",
|
|
1467
|
-
"practices/index.md": "# Development Practices\n\nThis directory contains development best practices.\n\n## Available Chunks\n\n- **planning.md** - Planning workflow, phases, asking for clarification, getting approval\n- **documentation.md** - Documentation organization, folder structure, memory lane\n- **code-review.md** - Review guidelines, PR templates, feedback\n- **refactoring.md** - Code smells, refactoring patterns\n- **version-control.md** - Git workflows, branching strategies\n",
|
|
1468
|
-
"practices/planning.md": "# Planning Best Practices\n\n## Plan Before Implementation\n\n**ALWAYS design and plan before writing code:**\n\n1. **Understand Requirements**\n - Clarify the goal and scope\n - Identify constraints and dependencies\n - Ask questions about ambiguous requirements\n\n2. **Break Down Into Phases**\n - Divide work into logical phases\n - Define deliverables for each phase\n - Prioritize phases by value and dependencies\n\n3. **Design First**\n - Sketch architecture and data flow\n - Identify components and interfaces\n - Consider edge cases and error scenarios\n\n4. **Get User Approval**\n - Present the plan to stakeholders\n - Explain trade-offs and alternatives\n - Wait for approval before implementation\n\n## Never Make Assumptions\n\n**CRITICAL: When in doubt, ASK:**\n\n```typescript\n// ❌ BAD: Assuming what user wants\nasync function processOrder(orderId: string) {\n // Assuming we should send email, but maybe not?\n await sendConfirmationEmail(orderId);\n // Assuming payment is already captured?\n await fulfillOrder(orderId);\n}\n\n// ✅ GOOD: Clarify requirements first\n// Q: Should we send confirmation email at this stage?\n// Q: Is payment already captured or should we capture it here?\n// Q: What happens if fulfillment fails?\n```\n\n**Ask about:**\n- Expected behavior in edge cases\n- Error handling strategy\n- Performance requirements\n- Security considerations\n- User experience preferences\n\n## Plan in Phases\n\n**Structure work into clear phases:**\n\n### Phase 1: Foundation\n- Set up project structure\n- Configure tooling and dependencies\n- Create basic types and interfaces\n\n### Phase 2: Core Implementation\n- Implement main business logic\n- Add error handling\n- Write unit tests\n\n### Phase 3: Integration\n- Connect components\n- Add integration tests\n- Handle edge cases\n\n### Phase 4: Polish\n- Performance optimization\n- Documentation\n- Final review\n\n**Checkpoint after each phase:**\n- Demo functionality\n- Get feedback\n- Adjust plan if needed\n\n## Planning Template\n\n```markdown\n## Goal\n[What are we building and why?]\n\n## Requirements\n- [ ] Requirement 1\n- [ ] Requirement 2\n- [ ] Requirement 3\n\n## Questions for Clarification\n1. [Question about requirement X]\n2. [Question about edge case Y]\n3. [Question about preferred approach for Z]\n\n## Proposed Approach\n[Describe the solution]\n\n## Phases\n1. **Phase 1**: [Description]\n - Task 1\n - Task 2\n\n2. **Phase 2**: [Description]\n - Task 1\n - Task 2\n\n## Risks & Mitigation\n- **Risk**: [Description]\n **Mitigation**: [How to handle]\n\n## Alternatives Considered\n- **Option A**: [Pros/Cons]\n- **Option B**: [Pros/Cons]\n- **Chosen**: Option A because [reason]\n```\n\n## Communication Principles\n\n1. **Ask Early**: Don't wait until you're stuck\n2. **Be Specific**: \"Should error X retry or fail immediately?\"\n3. **Propose Options**: \"Would you prefer A or B?\"\n4. **Explain Trade-offs**: \"Fast but risky vs. Slow but safe\"\n5. **Document Decisions**: Record what was decided and why\n\n## Anti-Patterns\n\n❌ **Don't:**\n- Start coding without understanding requirements\n- Assume you know what the user wants\n- Skip the planning phase to \"save time\"\n- Make architectural decisions without discussion\n- Proceed with unclear requirements\n\n✅ **Do:**\n- Ask questions when requirements are vague\n- Create a plan and get it approved\n- Break work into reviewable phases\n- Document decisions and reasoning\n- Communicate early and often\n",
|
|
1469
|
-
"practices/refactoring.md": "# Refactoring Patterns\n\n## Common Code Smells\n\n### Long Method\nSplit into smaller, focused functions.\n\n```typescript\n// Before\nfunction processOrder(order: Order) {\n // 100 lines of code...\n}\n\n// After\nfunction processOrder(order: Order) {\n validateOrder(order);\n calculateTotals(order);\n applyDiscounts(order);\n saveOrder(order);\n}\n```\n\n### Duplicate Code\nExtract common logic.\n\n```typescript\n// Before\nfunction getAdminUsers() {\n return users.filter(u => u.role === 'admin' && u.active);\n}\nfunction getModeratorUsers() {\n return users.filter(u => u.role === 'moderator' && u.active);\n}\n\n// After\nfunction getActiveUsersByRole(role: string) {\n return users.filter(u => u.role === role && u.active);\n}\n```\n\n### Primitive Obsession\nUse value objects.\n\n```typescript\n// Before\nfunction sendEmail(email: string) { /* ... */ }\n\n// After\nclass Email {\n constructor(private value: string) {\n if (!this.isValid(value)) throw new Error('Invalid email');\n }\n}\nfunction sendEmail(email: Email) { /* ... */ }\n```\n\n### Feature Envy\nMove method to class it uses most.\n\n```typescript\n// Before - Order is accessing customer too much\nclass Order {\n getDiscount() {\n return this.customer.isPremium() ?\n this.customer.premiumDiscount :\n this.customer.regularDiscount;\n }\n}\n\n// After\nclass Customer {\n getDiscount(): number {\n return this.isPremium() ? this.premiumDiscount : this.regularDiscount;\n }\n}\n```\n\n## Safe Refactoring Steps\n\n1. Ensure tests pass before refactoring\n2. Make one small change at a time\n3. Run tests after each change\n4. Commit frequently\n5. Refactor in separate commits from feature work\n\n## Best Practices\n\n- Refactor when adding features, not separately\n- Keep refactoring commits separate\n- Use IDE refactoring tools when available\n- Write tests before refactoring if missing\n",
|
|
1470
|
-
"practices/version-control.md": "# Version Control Patterns\n\n## Branching Strategies\n\n### GitHub Flow\nSimple: main + feature branches.\n\n```\nmain ─────●─────●─────●─────●─────\n \\ /\nfeature ●───●───●\n```\n\n### Git Flow\nFor scheduled releases: main, develop, feature, release, hotfix.\n\n```\nmain ─────●─────────────●─────\n \\ /\nrelease ●─────────●\n \\ /\ndevelop ●───●───●───●───●───●───\n \\ /\nfeature ●───●\n```\n\n## Commit Messages\n\n```\nfeat: add user authentication\n\n- Implement JWT-based auth\n- Add login/logout endpoints\n- Include password hashing\n\nCloses #123\n```\n\n**Prefixes:**\n- `feat:` - New feature\n- `fix:` - Bug fix\n- `refactor:` - Code change that doesn't fix bug or add feature\n- `docs:` - Documentation only\n- `test:` - Adding tests\n- `chore:` - Maintenance tasks\n\n## Best Practices\n\n- Keep commits atomic and focused\n- Write descriptive commit messages\n- Pull/rebase before pushing\n- Never force push to shared branches\n- Use pull requests for code review\n- Delete merged branches\n- Tag releases with semantic versions\n",
|
|
1471
|
-
"README.md": "# aicgen Guidelines Repository\n\nThis repository contains coding guidelines and best practices that power aicgen configurations.\n\n## Directory Structure\n\n```\ndata/\n├── guideline-mappings.yml # Maps guideline IDs to files and filters\n├── api/ # API design patterns\n├── architecture/ # Architecture patterns (clean, DDD, etc.)\n├── database/ # Database guidelines\n├── devops/ # CI/CD and deployment\n├── error-handling/ # Error handling strategies\n├── language/ # Language-specific (typescript, python)\n├── patterns/ # Design patterns\n├── performance/ # Performance optimization\n├── practices/ # Best practices\n├── security/ # Security guidelines\n├── style/ # Code style guidelines\n├── templates/ # Reusable templates\n└── testing/ # Testing strategies\n```\n\n## Contributing Guidelines\n\n### Step 1: Create Your Guideline File\n\nCreate a markdown file in the appropriate category folder:\n\n```bash\n# Example: Adding a new TypeScript guideline\ndata/language/typescript/my-guideline.md\n```\n\n**Guideline Format:**\n\n```markdown\n# Guideline Title\n\nBrief description of what this guideline covers.\n\n## Section 1\n\nClear, actionable instructions with code examples:\n\n\\`\\`\\`typescript\n// Good example\nfunction goodExample(): string {\n return \"well-structured code\";\n}\n\n// Bad example - explain why\nfunction badExample() { // Missing return type\n return \"unclear code\";\n}\n\\`\\`\\`\n\n## Section 2\n\nMore sections as needed...\n```\n\n**Writing Tips:**\n- Be concise and actionable\n- Include both good and bad code examples\n- Use language-appropriate code blocks\n- Focus on the \"why\" not just the \"what\"\n\n### Step 2: Add to Mappings\n\nAdd your guideline to `guideline-mappings.yml`:\n\n```yaml\nmy-guideline-id:\n path: language/typescript/my-guideline.md\n category: Language\n languages:\n - typescript\n levels:\n - standard\n - expert\n - full\n tags:\n - typescript\n - relevant-tag\n```\n\n### Mapping Fields\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `path` | Yes | Relative path to the guideline file |\n| `category` | Yes | Display category (Language, Architecture, Testing, etc.) |\n| `languages` | No | Which languages this applies to. Omit for all languages |\n| `levels` | No | Instruction levels: `basic`, `standard`, `expert`, `full`. Omit for all |\n| `architectures` | No | Architecture types. Omit for all |\n| `tags` | No | Search/organization tags |\n\n### Available Values\n\n**Languages:**\n- `typescript`, `python`, `go`, `rust`, `java`, `csharp`, `ruby`, `php`, `swift`, `kotlin`\n\n**Levels:**\n- `basic` - Essential guidelines only\n- `standard` - Common best practices\n- `expert` - Advanced patterns\n- `full` - Comprehensive coverage\n\n**Architectures:**\n- `layered`, `clean-architecture`, `hexagonal`, `ddd`, `microservices`\n- `modular-monolith`, `event-driven`, `serverless`, `other`\n\n**Categories:**\n- `Language`, `Architecture`, `Testing`, `Security`, `Performance`\n- `Database`, `API Design`, `Code Style`, `Error Handling`, `DevOps`\n- `Best Practices`, `Design Patterns`\n\n## Examples\n\n### Language-Specific Guideline\n\n```yaml\ntypescript-decorators:\n path: language/typescript/decorators.md\n category: Language\n languages:\n - typescript\n levels:\n - expert\n - full\n tags:\n - typescript\n - decorators\n - metadata\n```\n\n### Universal Guideline (All Languages)\n\n```yaml\nsolid-principles:\n path: architecture/solid/principles.md\n category: Architecture\n levels:\n - standard\n - expert\n - full\n tags:\n - solid\n - design-principles\n - oop\n```\n\n### Architecture-Specific Guideline\n\n```yaml\nddd-aggregates:\n path: architecture/ddd/aggregates.md\n category: Architecture\n architectures:\n - ddd\n - clean-architecture\n levels:\n - expert\n - full\n tags:\n - ddd\n - aggregates\n - domain-model\n```\n\n## Testing Your Changes\n\nAfter adding a guideline:\n\n1. **Rebuild aicgen:**\n ```bash\n bun run build\n ```\n\n2. **Check it's loaded:**\n ```bash\n bun run start stats\n ```\n\n3. **Test generation:**\n ```bash\n bun run start init --force\n ```\n\n## Guideline Quality Checklist\n\n- [ ] Clear, descriptive title\n- [ ] Actionable instructions\n- [ ] Code examples (good and bad)\n- [ ] Appropriate language/level targeting\n- [ ] Meaningful category and tags\n- [ ] No duplicate content with existing guidelines\n\n## License\n\nMIT License - See LICENSE file\n",
|
|
1472
|
-
"security/auth-jwt.md": "# Authentication & JWT Security\n\n## Password Storage\n\n```typescript\nimport bcrypt from 'bcrypt';\n\nconst SALT_ROUNDS = 12; // Work factor\n\n// ✅ Hash password with bcrypt\nasync function hashPassword(password: string): Promise<string> {\n return bcrypt.hash(password, SALT_ROUNDS);\n}\n\nasync function verifyPassword(password: string, hash: string): Promise<boolean> {\n return bcrypt.compare(password, hash);\n}\n\n// ✅ Validate password strength\nfunction validatePassword(password: string): void {\n if (password.length < 12) {\n throw new Error('Password must be at least 12 characters');\n }\n if (password.length > 160) {\n throw new Error('Password too long'); // Prevent DoS via bcrypt\n }\n}\n```\n\n## JWT Best Practices\n\n```typescript\nimport jwt from 'jsonwebtoken';\n\nconst JWT_SECRET = process.env.JWT_SECRET!;\nconst ACCESS_TOKEN_EXPIRY = '15m';\nconst REFRESH_TOKEN_EXPIRY = '7d';\n\n// ✅ Generate tokens\nfunction generateTokens(userId: string) {\n const accessToken = jwt.sign(\n { sub: userId, type: 'access' },\n JWT_SECRET,\n { expiresIn: ACCESS_TOKEN_EXPIRY }\n );\n\n const refreshToken = jwt.sign(\n { sub: userId, type: 'refresh' },\n JWT_SECRET,\n { expiresIn: REFRESH_TOKEN_EXPIRY }\n );\n\n return { accessToken, refreshToken };\n}\n\n// ✅ Verify and decode token\nfunction verifyToken(token: string) {\n try {\n return jwt.verify(token, JWT_SECRET);\n } catch (error) {\n if (error instanceof jwt.TokenExpiredError) {\n throw new UnauthorizedError('Token expired');\n }\n throw new UnauthorizedError('Invalid token');\n }\n}\n```\n\n## Login Protection\n\n```typescript\nimport rateLimit from 'express-rate-limit';\n\n// ✅ Rate limit login attempts\nconst loginLimiter = rateLimit({\n windowMs: 15 * 60 * 1000, // 15 minutes\n max: 5, // 5 attempts\n message: 'Too many login attempts, please try again later',\n});\n\napp.post('/login', loginLimiter, async (req, res) => {\n const { email, password } = req.body;\n\n const user = await userService.findByEmail(email);\n\n // ✅ Generic error message (don't reveal if user exists)\n if (!user || !await verifyPassword(password, user.passwordHash)) {\n return res.status(401).json({ error: 'Invalid email or password' });\n }\n\n const tokens = generateTokens(user.id);\n\n // Regenerate session to prevent fixation\n req.session.regenerate(() => {\n res.json({ ...tokens });\n });\n});\n```\n\n## Session Security\n\n```typescript\napp.use(session({\n secret: process.env.SESSION_SECRET!,\n name: 'sessionId', // Don't use default 'connect.sid'\n\n cookie: {\n secure: true, // HTTPS only\n httpOnly: true, // Prevent XSS access\n sameSite: 'strict', // CSRF protection\n maxAge: 30 * 60 * 1000, // 30 minutes\n },\n\n resave: false,\n saveUninitialized: false,\n store: new RedisStore({ client: redisClient })\n}));\n\n// ✅ Session regeneration after login\napp.post('/login', async (req, res, next) => {\n // ... authenticate user ...\n\n req.session.regenerate((err) => {\n req.session.userId = user.id;\n res.json({ success: true });\n });\n});\n```\n\n## Authorization Middleware\n\n```typescript\n// ✅ Require authentication\nconst requireAuth = async (req: Request, res: Response, next: NextFunction) => {\n const token = req.headers.authorization?.replace('Bearer ', '');\n\n if (!token) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n try {\n const payload = verifyToken(token);\n req.user = await userService.findById(payload.sub);\n next();\n } catch (error) {\n res.status(401).json({ error: 'Invalid token' });\n }\n};\n\n// ✅ Require specific role\nconst requireRole = (...roles: string[]) => {\n return (req: Request, res: Response, next: NextFunction) => {\n if (!roles.includes(req.user.role)) {\n return res.status(403).json({ error: 'Forbidden' });\n }\n next();\n };\n};\n```\n",
|
|
1473
|
-
"security/headers.md": "# Security Headers\n\n## Essential Headers with Helmet\n\n```typescript\nimport helmet from 'helmet';\n\n// ✅ Apply security headers with sensible defaults\napp.use(helmet());\n\n// ✅ Custom configuration\napp.use(helmet({\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\", \"'unsafe-inline'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\n }\n },\n hsts: {\n maxAge: 31536000,\n includeSubDomains: true,\n preload: true\n }\n}));\n```\n\n## Manual Header Configuration\n\n```typescript\napp.use((req, res, next) => {\n // Prevent MIME sniffing\n res.setHeader('X-Content-Type-Options', 'nosniff');\n\n // Prevent clickjacking\n res.setHeader('X-Frame-Options', 'DENY');\n\n // XSS protection\n res.setHeader('X-XSS-Protection', '1; mode=block');\n\n // Force HTTPS\n res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');\n\n // Referrer policy\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\n\n // Permissions policy\n res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');\n\n next();\n});\n```\n\n## Content Security Policy (CSP)\n\n```typescript\n// ✅ Strict CSP for maximum protection\nres.setHeader('Content-Security-Policy', [\n \"default-src 'self'\",\n \"script-src 'self'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"img-src 'self' data: https:\",\n \"font-src 'self'\",\n \"connect-src 'self' https://api.example.com\",\n \"frame-ancestors 'none'\",\n \"form-action 'self'\"\n].join('; '));\n\n// For APIs that don't serve HTML\nres.setHeader('Content-Security-Policy', \"default-src 'none'\");\n```\n\n## CORS Configuration\n\n```typescript\nimport cors from 'cors';\n\n// ✅ Configure CORS properly\napp.use(cors({\n origin: ['https://example.com', 'https://app.example.com'],\n methods: ['GET', 'POST', 'PUT', 'DELETE'],\n allowedHeaders: ['Content-Type', 'Authorization'],\n credentials: true,\n maxAge: 86400 // Cache preflight for 24 hours\n}));\n\n// ❌ Never use in production\napp.use(cors({ origin: '*' })); // Allows any origin\n```\n\n## HTTPS Enforcement\n\n```typescript\n// ✅ Redirect HTTP to HTTPS\napp.use((req, res, next) => {\n if (!req.secure && req.get('x-forwarded-proto') !== 'https') {\n return res.redirect(301, `https://${req.hostname}${req.url}`);\n }\n next();\n});\n\n// ✅ HSTS header (included in helmet)\nres.setHeader(\n 'Strict-Transport-Security',\n 'max-age=31536000; includeSubDomains; preload'\n);\n```\n\n## Cookie Security\n\n```typescript\n// ✅ Secure cookie settings\napp.use(session({\n cookie: {\n secure: true, // Only send over HTTPS\n httpOnly: true, // Not accessible via JavaScript\n sameSite: 'strict', // CSRF protection\n maxAge: 30 * 60 * 1000\n }\n}));\n\n// ✅ Set secure cookies manually\nres.cookie('token', value, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 3600000\n});\n```\n\n## Header Checklist\n\n```\n✅ X-Content-Type-Options: nosniff\n✅ X-Frame-Options: DENY\n✅ X-XSS-Protection: 1; mode=block\n✅ Strict-Transport-Security: max-age=31536000\n✅ Content-Security-Policy: (appropriate policy)\n✅ Referrer-Policy: strict-origin-when-cross-origin\n✅ Permissions-Policy: restrict unused features\n✅ Secure, HttpOnly, SameSite cookies\n```\n",
|
|
1474
|
-
"security/index.md": "# Security Guidelines\n\nThis directory contains security best practices.\n\n## Available Chunks\n\n- **injection.md** - SQL injection, NoSQL injection, command injection prevention\n- **auth-jwt.md** - Password storage, JWT, session management, authorization\n- **secrets.md** - Environment variables, secret generation, CI/CD secrets\n- **headers.md** - Security headers, CORS, HTTPS, CSP\n",
|
|
1475
|
-
"security/injection.md": "# Injection Prevention\n\n## SQL Injection Prevention\n\n```typescript\n// ❌ DANGEROUS: String concatenation\nconst getUserByEmail = async (email: string) => {\n const query = `SELECT * FROM users WHERE email = '${email}'`;\n // Input: ' OR '1'='1\n // Result: SELECT * FROM users WHERE email = '' OR '1'='1'\n return db.query(query);\n};\n\n// ✅ SAFE: Parameterized queries\nconst getUserByEmail = async (email: string) => {\n return db.query('SELECT * FROM users WHERE email = ?', [email]);\n};\n\n// ✅ SAFE: Using ORM\nconst getUserByEmail = async (email: string) => {\n return userRepository.findOne({ where: { email } });\n};\n\n// ✅ SAFE: Query builder\nconst getUsers = async (minAge: number) => {\n return db\n .select('*')\n .from('users')\n .where('age', '>', minAge); // Automatically parameterized\n};\n```\n\n## NoSQL Injection Prevention\n\n```typescript\n// ❌ DANGEROUS: Accepting objects from user input\napp.post('/login', (req, res) => {\n const { username, password } = req.body;\n // If password = {$gt: \"\"}, it bypasses password check!\n db.users.findOne({ username, password });\n});\n\n// ✅ SAFE: Validate input types\napp.post('/login', (req, res) => {\n const { username, password } = req.body;\n\n if (typeof username !== 'string' || typeof password !== 'string') {\n throw new Error('Invalid input types');\n }\n\n db.users.findOne({ username, password });\n});\n```\n\n## Command Injection Prevention\n\n```typescript\n// ❌ DANGEROUS: Shell command with user input\nconst convertImage = async (filename: string) => {\n exec(`convert ${filename} output.jpg`);\n // Input: \"file.png; rm -rf /\"\n};\n\n// ✅ SAFE: Use arrays, avoid shell\nimport { execFile } from 'child_process';\n\nconst convertImage = async (filename: string) => {\n execFile('convert', [filename, 'output.jpg']);\n};\n\n// ✅ SAFE: Validate input against whitelist\nconst allowedFilename = /^[a-zA-Z0-9_-]+\\.(png|jpg|gif)$/;\nif (!allowedFilename.test(filename)) {\n throw new Error('Invalid filename');\n}\n```\n\n## Path Traversal Prevention\n\n```typescript\n// ❌ DANGEROUS: Direct path usage\napp.get('/files/:filename', (req, res) => {\n res.sendFile(`/uploads/${req.params.filename}`);\n // Input: ../../etc/passwd\n});\n\n// ✅ SAFE: Validate and normalize path\nimport path from 'path';\n\napp.get('/files/:filename', (req, res) => {\n const safeName = path.basename(req.params.filename);\n const filePath = path.join('/uploads', safeName);\n const normalizedPath = path.normalize(filePath);\n\n if (!normalizedPath.startsWith('/uploads/')) {\n return res.status(400).json({ error: 'Invalid filename' });\n }\n\n res.sendFile(normalizedPath);\n});\n```\n\n## Input Validation\n\n```typescript\n// ✅ Whitelist validation\nimport { z } from 'zod';\n\nconst userSchema = z.object({\n email: z.string().email(),\n password: z.string().min(12).max(160),\n age: z.number().int().min(0).max(150),\n role: z.enum(['user', 'admin'])\n});\n\nconst validateUser = (data: unknown) => {\n return userSchema.parse(data);\n};\n```\n",
|
|
1476
|
-
"security/secrets.md": "# Secrets Management\n\n## Environment Variables\n\n```typescript\n// ❌ NEVER hardcode secrets\nconst config = {\n dbPassword: 'super_secret_password',\n apiKey: 'sk-1234567890abcdef'\n};\n\n// ✅ Use environment variables\nimport dotenv from 'dotenv';\ndotenv.config();\n\nconst config = {\n dbPassword: process.env.DB_PASSWORD,\n apiKey: process.env.API_KEY,\n sessionSecret: process.env.SESSION_SECRET\n};\n```\n\n## Validate Required Secrets\n\n```typescript\n// ✅ Fail fast if secrets missing\nconst requiredEnvVars = [\n 'DB_PASSWORD',\n 'API_KEY',\n 'SESSION_SECRET',\n 'JWT_SECRET'\n];\n\nrequiredEnvVars.forEach(varName => {\n if (!process.env[varName]) {\n throw new Error(`Missing required environment variable: ${varName}`);\n }\n});\n\n// ✅ Type-safe config\ninterface Config {\n dbPassword: string;\n apiKey: string;\n sessionSecret: string;\n}\n\nfunction loadConfig(): Config {\n const dbPassword = process.env.DB_PASSWORD;\n if (!dbPassword) throw new Error('DB_PASSWORD required');\n\n // ... validate all required vars\n\n return { dbPassword, apiKey, sessionSecret };\n}\n```\n\n## Generate Strong Secrets\n\n```bash\n# Generate cryptographically secure secrets\nnode -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"\n\n# Or using OpenSSL\nopenssl rand -base64 32\n\n# Or using head\nhead -c32 /dev/urandom | base64\n```\n\n## .gitignore Configuration\n\n```bash\n# .gitignore - NEVER commit secrets\n.env\n.env.local\n.env.*.local\n*.key\n*.pem\nsecrets/\ncredentials.json\n```\n\n## Environment Example File\n\n```bash\n# .env.example - commit this to show required variables\nDB_HOST=localhost\nDB_PORT=5432\nDB_NAME=myapp\nDB_USER=\nDB_PASSWORD=\n\nAPI_KEY=\nSESSION_SECRET=\nJWT_SECRET=\n\n# Copy to .env and fill in actual values\n```\n\n## Secrets in CI/CD\n\n```yaml\n# GitHub Actions\n- name: Deploy\n env:\n DB_PASSWORD: ${{ secrets.DB_PASSWORD }}\n API_KEY: ${{ secrets.API_KEY }}\n run: ./deploy.sh\n\n# ❌ Never echo secrets in logs\n- name: Configure\n run: |\n echo \"Configuring application...\"\n # echo \"DB_PASSWORD=$DB_PASSWORD\" # NEVER do this!\n```\n\n## Secrets Rotation\n\n```typescript\n// ✅ Support for rotating secrets\nclass SecretManager {\n async getSecret(name: string): Promise<string> {\n // Check for new secret first (during rotation)\n const newSecret = process.env[`${name}_NEW`];\n if (newSecret) {\n return newSecret;\n }\n\n const secret = process.env[name];\n if (!secret) {\n throw new Error(`Secret ${name} not found`);\n }\n return secret;\n }\n}\n\n// ✅ Accept multiple JWT signing keys during rotation\nfunction verifyToken(token: string) {\n const keys = [process.env.JWT_SECRET, process.env.JWT_SECRET_OLD].filter(Boolean);\n\n for (const key of keys) {\n try {\n return jwt.verify(token, key);\n } catch {}\n }\n throw new Error('Invalid token');\n}\n```\n",
|
|
1477
|
-
"style/index.md": "# Code Style Guidelines\n\nThis directory contains coding style and organization patterns.\n\n## Available Chunks\n\n- **naming.md** - Variables, constants, classes, files, avoiding magic numbers\n- **organization.md** - Function length, nesting depth, file structure, SRP\n",
|
|
1478
|
-
"style/naming.md": "# Naming Conventions\n\n## Variables and Functions\n\n```typescript\n// camelCase for variables and functions\nconst userName = 'John';\nconst isActive = true;\nconst itemCount = 42;\n\nfunction calculateTotal(items: Item[]): number {\n return items.reduce((sum, item) => sum + item.price, 0);\n}\n\n// Boolean variables: use is/has/can/should prefix\nconst isValid = validate(input);\nconst hasPermission = checkPermission(user);\nconst canEdit = user.role === 'admin';\nconst shouldRetry = error.code === 'TIMEOUT';\n\n// Collections: use plural names\nconst users = getUsers();\nconst activeOrders = orders.filter(o => o.status === 'active');\n```\n\n## Constants\n\n```typescript\n// UPPER_SNAKE_CASE for constants\nconst MAX_RETRY_ATTEMPTS = 3;\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst API_BASE_URL = 'https://api.example.com';\n\n// Enum-like objects\nconst ORDER_STATUS = {\n PENDING: 'pending',\n PROCESSING: 'processing',\n SHIPPED: 'shipped',\n DELIVERED: 'delivered',\n CANCELLED: 'cancelled'\n} as const;\n\nconst HTTP_STATUS = {\n OK: 200,\n CREATED: 201,\n BAD_REQUEST: 400,\n NOT_FOUND: 404\n} as const;\n```\n\n## Classes and Types\n\n```typescript\n// PascalCase for classes and types\nclass UserService {\n constructor(private userRepository: UserRepository) {}\n}\n\ninterface User {\n id: string;\n name: string;\n email: string;\n}\n\ntype UserRole = 'admin' | 'editor' | 'viewer';\n\n// Avoid prefixes\n// ❌ IUser, CUser, TUser\n// ✅ User\n```\n\n## Files and Modules\n\n```typescript\n// kebab-case for files\nuser-service.ts\norder-repository.ts\ncreate-user.dto.ts\n\n// Match file name to primary export\n// user-service.ts exports UserService\n// order-repository.ts exports OrderRepository\n```\n\n## Avoid Bad Names\n\n```typescript\n// ❌ Bad - unclear\nconst d = Date.now();\nconst tmp = user.name;\nconst data = fetchData();\nconst flag = true;\n\n// ✅ Good - descriptive\nconst currentDate = Date.now();\nconst originalUserName = user.name;\nconst customerOrders = fetchCustomerOrders();\nconst isEmailVerified = true;\n```\n\n## Avoid Magic Numbers\n\n```typescript\n// ❌ Magic numbers\nif (user.age >= 18) { ... }\nif (items.length > 100) { ... }\nsetTimeout(callback, 5000);\n\n// ✅ Named constants\nconst LEGAL_AGE = 18;\nconst MAX_BATCH_SIZE = 100;\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nif (user.age >= LEGAL_AGE) { ... }\nif (items.length > MAX_BATCH_SIZE) { ... }\nsetTimeout(callback, DEFAULT_TIMEOUT_MS);\n```\n\n## Consistency\n\n```typescript\n// Pick ONE style and stick with it across the project\n\n// ✅ Consistent camelCase in APIs\n{\n \"userId\": 123,\n \"firstName\": \"John\",\n \"createdAt\": \"2024-01-01\"\n}\n\n// ❌ Mixed styles\n{\n \"user_id\": 123, // snake_case\n \"firstName\": \"John\", // camelCase - inconsistent!\n}\n```\n",
|
|
1479
|
-
"style/organization.md": "# Code Organization\n\n## Function Length\n\n```typescript\n// ❌ Function too long (>50 lines)\nfunction processOrder(orderId: string) {\n // 200 lines of validation, payment, inventory, shipping...\n}\n\n// ✅ Extract into smaller, focused functions\nfunction processOrder(orderId: string) {\n const order = fetchOrder(orderId);\n\n validateOrder(order);\n reserveInventory(order.items);\n processPayment(order);\n scheduleShipping(order);\n sendConfirmation(order.customer.email);\n\n return order;\n}\n```\n\n## Nesting Depth\n\n```typescript\n// ❌ Too much nesting (>3 levels)\nif (user) {\n if (user.isActive) {\n if (user.hasPermission('edit')) {\n if (resource.isAvailable) {\n // Deep nesting is hard to follow\n }\n }\n }\n}\n\n// ✅ Guard clauses to reduce nesting\nif (!user) return;\nif (!user.isActive) return;\nif (!user.hasPermission('edit')) return;\nif (!resource.isAvailable) return;\n\n// Clear logic at top level\n\n// ✅ Extract complex conditions\nfunction canEditResource(user: User, resource: Resource): boolean {\n return user &&\n user.isActive &&\n user.hasPermission('edit') &&\n resource.isAvailable;\n}\n\nif (canEditResource(user, resource)) {\n // Single level of nesting\n}\n```\n\n## File Length\n\n```typescript\n// ❌ God file (1000+ lines)\n// user-service.ts with 50 methods handling users, auth, permissions...\n\n// ✅ Split into focused modules (~200-300 lines each)\n// user-service.ts - CRUD operations\n// auth-service.ts - login, logout, tokens\n// permission-service.ts - role checks\n```\n\n## File Organization\n\n```typescript\n// Consistent structure within files:\n\n// 1. Imports (grouped and ordered)\nimport fs from 'fs'; // Standard library\nimport express from 'express'; // External dependencies\nimport { UserService } from './user'; // Internal modules\n\n// 2. Constants and type definitions\nconst MAX_RETRIES = 3;\n\ninterface UserDTO {\n id: string;\n name: string;\n}\n\n// 3. Helper functions (if needed)\nfunction validateInput(input: unknown): boolean {\n // ...\n}\n\n// 4. Main exports/classes\nexport class OrderService {\n // ...\n}\n\n// 5. Module initialization (if applicable)\nexport default new OrderService();\n```\n\n## Single Responsibility\n\n```typescript\n// ❌ Class doing too much\nclass UserManager {\n createUser() {}\n updateUser() {}\n sendEmail() {}\n hashPassword() {}\n generateToken() {}\n}\n\n// ✅ Split by responsibility\nclass UserRepository {\n create(user: User) {}\n update(id: string, data: Partial<User>) {}\n}\n\nclass EmailService {\n send(to: string, template: string) {}\n}\n\nclass PasswordService {\n hash(password: string): string {}\n verify(password: string, hash: string): boolean {}\n}\n\nclass AuthService {\n generateToken(userId: string): string {}\n}\n```\n\n## DRY (Don't Repeat Yourself)\n\n```typescript\n// ❌ Duplicated logic\nfunction processUserOrder(order: Order) {\n const total = order.items.reduce((sum, i) => sum + i.price * i.quantity, 0);\n const tax = total * 0.08;\n return total + tax;\n}\n\nfunction processGuestOrder(order: Order) {\n const total = order.items.reduce((sum, i) => sum + i.price * i.quantity, 0);\n const tax = total * 0.08;\n return total + tax;\n}\n\n// ✅ Extract common logic\nfunction calculateOrderTotal(items: Item[]): number {\n const subtotal = items.reduce((sum, i) => sum + i.price * i.quantity, 0);\n const tax = subtotal * 0.08;\n return subtotal + tax;\n}\n\nfunction processUserOrder(order: Order) {\n return calculateOrderTotal(order.items);\n}\n```\n",
|
|
1480
|
-
"templates/agents/architecture-reviewer.md": "---\nmodel: \"claude-sonnet-4-5\"\ndescription: \"Reviews architectural decisions and patterns\"\n---\n\n# Architecture Reviewer\n\nYou are an architecture review agent ensuring code changes align with the project's architectural principles and patterns.\n\n## Your Responsibilities\n\n### Architectural Compliance\n- Verify changes follow established architecture pattern (layered, hexagonal, microservices, etc.)\n- Check dependency directions are correct\n- Ensure proper separation of concerns\n- Validate module boundaries\n\n### Design Patterns\n- Identify appropriate use of design patterns\n- Flag anti-patterns (God objects, tight coupling, etc.)\n- Suggest pattern improvements when beneficial\n- Verify SOLID principles adherence\n\n### Technical Debt\n- Identify potential technical debt introduced\n- Flag shortcuts that may cause future issues\n- Suggest refactoring opportunities\n- Assess long-term maintainability impact\n\n## Review Checklist\n\n- [ ] Does this change respect the existing architecture?\n- [ ] Are dependencies pointing in the correct direction?\n- [ ] Is there proper separation between layers/modules?\n- [ ] Are interfaces/contracts well-defined?\n- [ ] Is the change introducing tight coupling?\n- [ ] Could this be simplified using existing patterns?\n- [ ] Does this create technical debt?\n- [ ] Is this scalable and maintainable?\n\n## Output Format\n\n```\n🏗️ Architecture Review\n\nFiles reviewed: X\nArchitecture: [Layered/Hexagonal/Microservices/etc.]\n\n✅ Strengths:\n- Proper dependency injection in ServiceFactory\n- Clean interface boundaries in API layer\n\n⚠️ Concerns:\n\n1. Dependency Violation (Critical)\n - File: src/ui/components/UserForm.tsx:23\n - Issue: Direct database access from UI layer\n - Impact: Violates layered architecture\n - Solution: Access data through service layer\n\n2. Tight Coupling (Important)\n - File: src/services/email-service.ts:45\n - Issue: Hard-coded dependency on specific SMTP library\n - Impact: Difficult to swap email providers\n - Solution: Use adapter pattern with EmailProvider interface\n\n3. Potential Debt (Minor)\n - File: src/utils/cache.ts:12\n - Issue: In-memory cache without eviction strategy\n - Impact: May cause memory issues at scale\n - Solution: Implement LRU eviction or use Redis\n\n📊 Summary:\n- Critical issues: 1\n- Important issues: 1\n- Minor issues: 1\n- Technical debt score: Medium\n\nRecommendation: Address critical dependency violation before merging\n```\n\n## Guidelines\n\n- Focus on architectural implications, not minor style issues\n- Consider both immediate and long-term impacts\n- Provide specific, actionable solutions\n- Explain the \"why\" behind each concern\n- Balance idealism with pragmatism\n",
|
|
1481
|
-
"templates/agents/guideline-checker.md": "---\nmodel: \"claude-opus-4-5\"\ndescription: \"Verifies code changes comply with project guidelines\"\n---\n\n# Guideline Compliance Checker\n\nYou are an automated code review agent that verifies code changes follow the project's established guidelines.\n\n## Your Responsibilities\n\nWhen code changes are made, automatically verify:\n\n### Code Style Compliance\n- Naming conventions match project standards\n- File organization follows project structure\n- No redundant or commented-out code\n- Proper indentation and formatting\n\n### TypeScript/JavaScript Standards\n- TypeScript strict mode compliance\n- No `any` types (use `unknown` with type guards)\n- Proper interface/type definitions\n- Async/await patterns used correctly\n\n### Best Practices\n- Functions under 50 lines\n- Maximum 3 levels of nesting\n- Complex conditionals extracted to named functions\n- Error handling implemented properly\n- No magic numbers (use named constants)\n\n### Testing Requirements\n- New functions have corresponding tests\n- Test coverage maintained or improved\n- Tests follow AAA pattern (Arrange, Act, Assert)\n\n## Output Format\n\nReport findings in this format:\n\n```\n✅ Guideline Compliance Report\n\nFiles checked: X\n\n⚠️ Issues Found:\n\nsrc/services/example.ts:45\n - Uses `any` type instead of `unknown`\n - Function exceeds 50 lines (65 lines)\n\nsrc/utils/helper.ts:12\n - Magic number 3600 should be named constant\n\nsrc/commands/init.ts:120\n - Missing error handling for async operation\n\n📋 Recommendations:\n1. Replace `any` with `unknown` and add type guard\n2. Extract SECONDS_IN_HOUR = 3600 as constant\n3. Add try-catch block for async operation\n\nOverall: 3 issues require attention\n```\n\n## Guidelines\n\n- Be specific with file paths and line numbers\n- Explain WHY each issue matters\n- Provide actionable recommendations\n- Prioritize by severity (critical, important, minor)\n- Acknowledge good practices when found\n",
|
|
1482
|
-
"templates/agents/security-auditor.md": "---\nmodel: \"claude-opus-4-5\"\ntemperature: 0.3\ndescription: \"Identifies security vulnerabilities and risks\"\n---\n\n# Security Auditor\n\nYou are a security-focused code review agent that identifies vulnerabilities, security risks, and unsafe practices.\n\n## Your Responsibilities\n\n### OWASP Top 10 Checks\n- SQL Injection vulnerabilities\n- Cross-Site Scripting (XSS)\n- Authentication and session management flaws\n- Insecure direct object references\n- Security misconfiguration\n- Sensitive data exposure\n- Missing access control\n- Cross-Site Request Forgery (CSRF)\n- Using components with known vulnerabilities\n- Insufficient logging and monitoring\n\n### Code Security\n- Input validation and sanitization\n- Output encoding\n- Parameterized queries\n- Secure random number generation\n- Cryptographic best practices\n- Secrets and credential management\n- API key and token handling\n\n### Common Vulnerabilities\n- Path traversal attacks\n- Command injection\n- XML/XXE injection\n- Deserialization vulnerabilities\n- Race conditions\n- Buffer overflows (in applicable languages)\n\n## Review Process\n\n1. Scan for obvious security issues\n2. Check data flow from user input to storage/output\n3. Verify authentication and authorization\n4. Review cryptographic usage\n5. Check dependency versions for known vulnerabilities\n6. Assess error handling and information disclosure\n\n## Output Format\n\n```\n🔒 Security Audit Report\n\nFiles audited: X\nRisk Level: [Low/Medium/High/Critical]\n\n🚨 Critical Vulnerabilities:\n\n1. SQL Injection Risk\n - File: src/database/user-repository.ts:34\n - Code: `db.query(\\`SELECT * FROM users WHERE id = ${userId}\\`)`\n - Risk: Allows arbitrary SQL execution\n - Fix: Use parameterized query: `db.query('SELECT * FROM users WHERE id = ?', [userId])`\n - CWE: CWE-89\n\n⚠️ High Risk Issues:\n\n2. Sensitive Data Exposure\n - File: src/api/auth-controller.ts:89\n - Code: User password returned in API response\n - Risk: Password hash exposed to clients\n - Fix: Remove password from response object\n\n🔔 Medium Risk Issues:\n\n3. Missing Input Validation\n - File: src/api/upload-controller.ts:12\n - Code: File upload without type validation\n - Risk: Malicious file upload\n - Fix: Validate file type and size before processing\n\n💡 Security Recommendations:\n\n- Enable Content Security Policy headers\n- Implement rate limiting on authentication endpoints\n- Add CSRF tokens to state-changing operations\n- Use secure HTTP-only cookies for sessions\n- Enable security headers (X-Frame-Options, etc.)\n\n📊 Summary:\n- Critical: 1\n- High: 1\n- Medium: 1\n- Low: 0\n\n⚠️ Action Required: Fix critical SQL injection before deployment\n```\n\n## Guidelines\n\n- Prioritize by actual risk, not theoretical scenarios\n- Provide clear, actionable fixes with code examples\n- Reference CWE/CVE numbers when applicable\n- Consider the application's threat model\n- Balance security with usability\n- Don't create false positives unnecessarily\n",
|
|
1483
|
-
"testing/basics.md": "# Testing Basics\n\n## Your First Unit Test\n\nA unit test verifies that a small piece of code works correctly.\n\n```pseudocode\n// Function to test\nfunction add(a, b):\n return a + b\n\n// Test for the function\ntest \"add should sum two numbers\":\n result = add(2, 3)\n expect result equals 5\n```\n\n## Test Structure\n\nEvery test has three parts:\n\n1. **Setup** - Prepare what you need\n2. **Execute** - Run the code\n3. **Verify** - Check the result\n\n```pseudocode\ntest \"should create user with name\":\n // 1. Setup\n userName = \"Alice\"\n\n // 2. Execute\n user = createUser(userName)\n\n // 3. Verify\n expect user.name equals \"Alice\"\n```\n\n## Common Assertions\n\n```pseudocode\n// Equality\nexpect value equals 5\nexpect value equals { id: 1 }\n\n// Truthiness\nexpect value is truthy\nexpect value is falsy\nexpect value is null\nexpect value is undefined\n\n// Numbers\nexpect value > 3\nexpect value < 10\n\n// Strings\nexpect text contains \"hello\"\n\n// Arrays/Lists\nexpect array contains item\nexpect array length equals 3\n```\n\n## Testing Expected Errors\n\n```pseudocode\ntest \"should throw error for invalid input\":\n expect error when:\n divide(10, 0)\n with message \"Cannot divide by zero\"\n```\n\n## Async Tests\n\n```pseudocode\ntest \"should fetch user data\" async:\n user = await fetchUser(123)\n expect user.id equals 123\n```\n\n## Test Naming\n\nUse clear, descriptive names:\n\n```pseudocode\n// ❌ Bad\ntest \"test1\"\ntest \"it works\"\n\n// ✅ Good\ntest \"should return user when ID exists\"\ntest \"should throw error when ID is invalid\"\n```\n\n## Running Tests\n\n```bash\n# Run all tests\nrun-tests\n\n# Run specific test file\nrun-tests user-test\n\n# Watch mode (re-run on changes)\nrun-tests --watch\n```\n\n## Best Practices\n\n1. **One test, one thing** - Test one behavior per test\n2. **Independent tests** - Tests should not depend on each other\n3. **Clear names** - Name should describe what is being tested\n4. **Fast tests** - Tests should run quickly\n\n```pseudocode\n// ❌ Bad: Testing multiple things\ntest \"user operations\":\n expect createUser(\"Bob\").name equals \"Bob\"\n expect deleteUser(1) equals true\n expect listUsers().length equals 0\n\n// ✅ Good: One test per operation\ntest \"should create user with given name\":\n user = createUser(\"Bob\")\n expect user.name equals \"Bob\"\n\ntest \"should delete user by ID\":\n result = deleteUser(1)\n expect result equals true\n\ntest \"should return empty list when no users\":\n users = listUsers()\n expect users.length equals 0\n```\n\n## When to Write Tests\n\n- **Before fixing bugs** - Write test that fails, then fix\n- **For new features** - Test expected behavior\n- **For edge cases** - Empty input, null values, large numbers\n\n## What to Test\n\n✅ **Do test:**\n- Public functions and methods\n- Edge cases (empty, null, zero, negative)\n- Error conditions\n\n❌ **Don't test:**\n- Private implementation details\n- Third-party libraries (they're already tested)\n- Getters/setters with no logic\n",
|
|
1484
|
-
"testing/index.md": "# Testing Guidelines\n\nThis directory contains testing best practices and patterns.\n\n## Available Chunks\n\n- **unit-fundamentals.md** - AAA pattern, behavior testing, descriptive names\n- **unit-mocking.md** - Test doubles, when to mock, mock verification\n- **integration.md** - API testing, database testing, test isolation\n",
|
|
1485
|
-
"testing/integration.md": "# Integration Testing\n\n## Testing Real Dependencies\n\n```typescript\ndescribe('UserRepository Integration', () => {\n let db: Database;\n let repository: UserRepository;\n\n beforeAll(async () => {\n db = await createTestDatabase();\n repository = new UserRepository(db);\n });\n\n afterAll(async () => {\n await db.close();\n });\n\n beforeEach(async () => {\n await db.clear('users'); // Clean slate for each test\n });\n\n it('should persist and retrieve user', async () => {\n const userData = { email: 'test@example.com', name: 'Test User' };\n\n const created = await repository.create(userData);\n const found = await repository.findById(created.id);\n\n expect(found).toEqual(expect.objectContaining(userData));\n });\n});\n```\n\n## API Integration Tests\n\n```typescript\ndescribe('POST /api/users', () => {\n let app: Express;\n let db: Database;\n\n beforeAll(async () => {\n db = await createTestDatabase();\n app = createApp(db);\n });\n\n afterEach(async () => {\n await db.clear('users');\n });\n\n it('should create user and return 201', async () => {\n const response = await request(app)\n .post('/api/users')\n .send({ email: 'new@example.com', name: 'New User' })\n .expect(201);\n\n expect(response.body.data).toEqual(\n expect.objectContaining({\n email: 'new@example.com',\n name: 'New User'\n })\n );\n\n // Verify in database\n const user = await db.findOne('users', { email: 'new@example.com' });\n expect(user).toBeTruthy();\n });\n\n it('should return 400 for invalid email', async () => {\n const response = await request(app)\n .post('/api/users')\n .send({ email: 'invalid', name: 'Test' })\n .expect(400);\n\n expect(response.body.error.code).toBe('VALIDATION_ERROR');\n });\n});\n```\n\n## Database Transaction Testing\n\n```typescript\ndescribe('OrderService Integration', () => {\n it('should rollback on payment failure', async () => {\n const order = await orderService.createOrder({ items: [...] });\n\n // Mock payment to fail\n paymentGateway.charge.mockRejectedValue(new Error('Declined'));\n\n await expect(\n orderService.processOrder(order.id)\n ).rejects.toThrow('Payment failed');\n\n // Verify order status unchanged\n const updatedOrder = await orderRepository.findById(order.id);\n expect(updatedOrder.status).toBe('pending');\n\n // Verify inventory not deducted\n const inventory = await inventoryRepository.findByProductId(productId);\n expect(inventory.quantity).toBe(originalQuantity);\n });\n});\n```\n\n## Test Data Builders\n\n```typescript\nclass UserBuilder {\n private data: Partial<User> = {\n email: 'default@example.com',\n name: 'Default User',\n role: 'user'\n };\n\n withEmail(email: string) { this.data.email = email; return this; }\n withRole(role: string) { this.data.role = role; return this; }\n asAdmin() { this.data.role = 'admin'; return this; }\n\n build(): User { return this.data as User; }\n\n async save(db: Database): Promise<User> {\n return db.insert('users', this.data);\n }\n}\n\n// Usage\nconst admin = await new UserBuilder()\n .withEmail('admin@example.com')\n .asAdmin()\n .save(db);\n```\n\n## Test Isolation\n\n```typescript\n// Use transactions that rollback\ndescribe('IntegrationTests', () => {\n beforeEach(async () => {\n await db.beginTransaction();\n });\n\n afterEach(async () => {\n await db.rollbackTransaction();\n });\n});\n\n// Or use test containers\nimport { PostgreSqlContainer } from '@testcontainers/postgresql';\n\nlet container: PostgreSqlContainer;\n\nbeforeAll(async () => {\n container = await new PostgreSqlContainer().start();\n db = await connect(container.getConnectionUri());\n});\n\nafterAll(async () => {\n await container.stop();\n});\n```\n",
|
|
1486
|
-
"testing/unit-fundamentals.md": "# Unit Testing Fundamentals\n\n## Arrange-Act-Assert Pattern\n\n```typescript\ndescribe('UserService', () => {\n it('should create user with hashed password', async () => {\n // Arrange - Set up test data and dependencies\n const userData = { email: 'test@example.com', password: 'secret123' };\n const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };\n const service = new UserService(mockRepo);\n\n // Act - Execute the behavior being tested\n const result = await service.createUser(userData);\n\n // Assert - Verify the outcomes\n expect(result.id).toBe('1');\n expect(mockRepo.save).toHaveBeenCalledWith(\n expect.objectContaining({ email: 'test@example.com' })\n );\n });\n});\n```\n\n## Test Observable Behavior, Not Implementation\n\n```typescript\n// ❌ Bad: Testing implementation details\nit('should call validateEmail method', () => {\n const spy = jest.spyOn(service, 'validateEmail');\n service.createUser({ email: 'test@example.com' });\n expect(spy).toHaveBeenCalled();\n});\n\n// ✅ Good: Testing observable behavior\nit('should reject invalid email', async () => {\n await expect(\n service.createUser({ email: 'invalid-email' })\n ).rejects.toThrow('Invalid email format');\n});\n\nit('should accept valid email', async () => {\n const result = await service.createUser({ email: 'valid@example.com' });\n expect(result.email).toBe('valid@example.com');\n});\n```\n\n## One Assertion Per Test Concept\n\n```typescript\n// ❌ Bad: Multiple unrelated assertions\nit('should validate user input', () => {\n expect(() => validate({ age: -1 })).toThrow();\n expect(() => validate({ age: 200 })).toThrow();\n expect(() => validate({ name: '' })).toThrow();\n});\n\n// ✅ Good: One test per scenario\nit('should reject negative age', () => {\n expect(() => validate({ age: -1 })).toThrow('Age must be positive');\n});\n\nit('should reject age over 150', () => {\n expect(() => validate({ age: 200 })).toThrow('Age must be under 150');\n});\n\nit('should reject empty name', () => {\n expect(() => validate({ name: '' })).toThrow('Name is required');\n});\n```\n\n## Descriptive Test Names\n\n```typescript\n// ❌ Vague names\nit('should work correctly', () => {});\nit('handles edge case', () => {});\n\n// ✅ Descriptive names - describe the scenario and expected outcome\nit('should return empty array when no users match filter', () => {});\nit('should throw ValidationError when email is empty', () => {});\nit('should retry failed payment up to 3 times before giving up', () => {});\n```\n\n## Tests Should Be Independent\n\n```typescript\n// ❌ Bad: Tests depend on each other\nlet userId: string;\n\nit('should create user', async () => {\n const user = await service.createUser(data);\n userId = user.id; // Shared state!\n});\n\nit('should update user', async () => {\n await service.updateUser(userId, newData); // Depends on previous test\n});\n\n// ✅ Good: Each test is self-contained\nit('should update user', async () => {\n const user = await service.createUser(data);\n const updated = await service.updateUser(user.id, newData);\n expect(updated.name).toBe(newData.name);\n});\n```\n\n## Test Edge Cases\n\n```typescript\ndescribe('divide', () => {\n it('should divide two positive numbers', () => {\n expect(divide(10, 2)).toBe(5);\n });\n\n it('should throw when dividing by zero', () => {\n expect(() => divide(10, 0)).toThrow('Division by zero');\n });\n\n it('should handle negative numbers', () => {\n expect(divide(-10, 2)).toBe(-5);\n });\n\n it('should return zero when numerator is zero', () => {\n expect(divide(0, 5)).toBe(0);\n });\n});\n```\n",
|
|
1487
|
-
"testing/unit-mocking.md": "# Test Doubles and Mocking\n\n## Types of Test Doubles\n\n```typescript\n// STUB: Returns canned responses\nconst stubUserRepo = {\n findById: () => ({ id: '1', name: 'Test User' })\n};\n\n// MOCK: Pre-programmed with expectations\nconst mockPaymentGateway = {\n charge: jest.fn()\n .mockResolvedValueOnce({ success: true, transactionId: 'tx1' })\n .mockResolvedValueOnce({ success: false, error: 'Declined' })\n};\n\n// SPY: Records calls for verification\nconst spy = jest.spyOn(emailService, 'send');\n\n// FAKE: Working implementation (not for production)\nclass FakeDatabase implements Database {\n private data = new Map<string, any>();\n\n async save(id: string, entity: any) { this.data.set(id, entity); }\n async find(id: string) { return this.data.get(id); }\n}\n```\n\n## When to Mock\n\n```typescript\n// ✅ Mock external services (APIs, databases)\nconst mockHttpClient = {\n get: jest.fn().mockResolvedValue({ data: userData })\n};\n\n// ✅ Mock time-dependent operations\njest.useFakeTimers();\njest.setSystemTime(new Date('2024-01-15'));\n\n// ✅ Mock random/non-deterministic functions\njest.spyOn(Math, 'random').mockReturnValue(0.5);\n\n// ❌ Don't mock the code you're testing\n// ❌ Don't mock simple data structures\n```\n\n## Mock Verification\n\n```typescript\nit('should send welcome email after registration', async () => {\n const mockEmail = { send: jest.fn().mockResolvedValue(true) };\n const service = new UserService({ emailService: mockEmail });\n\n await service.register({ email: 'new@example.com' });\n\n expect(mockEmail.send).toHaveBeenCalledWith({\n to: 'new@example.com',\n template: 'welcome',\n subject: 'Welcome!'\n });\n expect(mockEmail.send).toHaveBeenCalledTimes(1);\n});\n```\n\n## Partial Mocks\n\n```typescript\n// Mock only specific methods\nconst service = new OrderService();\n\njest.spyOn(service, 'validateOrder').mockReturnValue(true);\njest.spyOn(service, 'calculateTotal').mockReturnValue(100);\n// Other methods use real implementation\n\nconst result = await service.processOrder(orderData);\nexpect(result.total).toBe(100);\n```\n\n## Resetting Mocks\n\n```typescript\ndescribe('PaymentService', () => {\n const mockGateway = { charge: jest.fn() };\n const service = new PaymentService(mockGateway);\n\n beforeEach(() => {\n jest.clearAllMocks(); // Clear call history\n // or jest.resetAllMocks() to also reset return values\n });\n\n it('should process payment', async () => {\n mockGateway.charge.mockResolvedValue({ success: true });\n await service.charge(100);\n expect(mockGateway.charge).toHaveBeenCalledTimes(1);\n });\n});\n```\n\n## Mock Modules\n\n```typescript\n// Mock entire module\njest.mock('./email-service', () => ({\n EmailService: jest.fn().mockImplementation(() => ({\n send: jest.fn().mockResolvedValue(true)\n }))\n}));\n\n// Mock with partial implementation\njest.mock('./config', () => ({\n ...jest.requireActual('./config'),\n API_KEY: 'test-key'\n}));\n```\n"
|
|
1488
|
-
}
|
|
1489
|
-
};
|
|
1490
|
-
|
|
1491
|
-
export const GUIDELINE_COUNT = 109;
|
|
1492
|
-
export const MAPPING_COUNT = 82;
|