@aicgen/aicgen 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/architecture-reviewer.md +88 -0
- package/.claude/agents/guideline-checker.md +73 -0
- package/.claude/agents/security-auditor.md +108 -0
- package/.claude/guidelines/api-design.md +645 -0
- package/.claude/guidelines/architecture.md +2503 -0
- package/.claude/guidelines/best-practices.md +618 -0
- package/.claude/guidelines/code-style.md +304 -0
- package/.claude/guidelines/design-patterns.md +573 -0
- package/.claude/guidelines/devops.md +226 -0
- package/.claude/guidelines/error-handling.md +413 -0
- package/.claude/guidelines/language.md +782 -0
- package/.claude/guidelines/performance.md +706 -0
- package/.claude/guidelines/security.md +583 -0
- package/.claude/guidelines/testing.md +568 -0
- package/.claude/settings.json +98 -0
- package/.claude/settings.local.json +8 -0
- package/.env.example +23 -0
- package/.eslintrc.json +28 -0
- package/.github/workflows/release.yml +180 -0
- package/.github/workflows/test.yml +81 -0
- package/.gitmodules +3 -0
- package/.vs/ProjectSettings.json +3 -0
- package/.vs/VSWorkspaceState.json +16 -0
- package/.vs/aicgen.slnx/FileContentIndex/5f0ce2a3-fd68-4863-9e23-e428cf1794e3.vsidx +0 -0
- package/.vs/aicgen.slnx/v18/.wsuo +0 -0
- package/.vs/aicgen.slnx/v18/DocumentLayout.json +54 -0
- package/.vs/slnx.sqlite +0 -0
- package/AGENTS.md +121 -0
- package/CLAUDE.md +36 -0
- package/CONTRIBUTING.md +821 -0
- package/LICENSE +21 -0
- package/README.md +199 -0
- package/assets/icon.svg +34 -0
- package/assets/logo.svg +41 -0
- package/bun.lock +848 -0
- package/data/LICENSE +21 -0
- package/data/README.md +203 -0
- package/data/api/basics.md +292 -0
- package/data/api/index.md +8 -0
- package/data/api/pagination.md +142 -0
- package/data/api/rest.md +137 -0
- package/data/api/versioning.md +60 -0
- package/data/architecture/clean-architecture/index.md +7 -0
- package/data/architecture/clean-architecture/layers.md +111 -0
- package/data/architecture/ddd/index.md +8 -0
- package/data/architecture/ddd/strategic.md +89 -0
- package/data/architecture/ddd/tactical.md +132 -0
- package/data/architecture/event-driven/index.md +7 -0
- package/data/architecture/event-driven/messaging.md +242 -0
- package/data/architecture/event-driven/patterns.md +129 -0
- package/data/architecture/feature-toggles/index.md +7 -0
- package/data/architecture/feature-toggles/patterns.md +73 -0
- package/data/architecture/gui/index.md +7 -0
- package/data/architecture/gui/patterns.md +132 -0
- package/data/architecture/hexagonal/ports-adapters.md +132 -0
- package/data/architecture/index.md +12 -0
- package/data/architecture/layered/index.md +7 -0
- package/data/architecture/layered/layers.md +100 -0
- package/data/architecture/microservices/api-gateway.md +56 -0
- package/data/architecture/microservices/boundaries.md +80 -0
- package/data/architecture/microservices/communication.md +97 -0
- package/data/architecture/microservices/data.md +92 -0
- package/data/architecture/microservices/index.md +11 -0
- package/data/architecture/microservices/resilience.md +111 -0
- package/data/architecture/modular-monolith/boundaries.md +133 -0
- package/data/architecture/modular-monolith/structure.md +131 -0
- package/data/architecture/serverless/best-practices.md +322 -0
- package/data/architecture/serverless/index.md +7 -0
- package/data/architecture/serverless/patterns.md +80 -0
- package/data/architecture/solid/index.md +7 -0
- package/data/architecture/solid/principles.md +187 -0
- package/data/database/basics.md +365 -0
- package/data/database/design-patterns.md +68 -0
- package/data/database/index.md +8 -0
- package/data/database/indexing.md +136 -0
- package/data/database/nosql.md +223 -0
- package/data/database/schema.md +137 -0
- package/data/devops/ci-cd.md +66 -0
- package/data/devops/index.md +8 -0
- package/data/devops/observability.md +73 -0
- package/data/devops/practices.md +77 -0
- package/data/error-handling/basics.md +222 -0
- package/data/error-handling/index.md +7 -0
- package/data/error-handling/strategy.md +185 -0
- package/data/guideline-mappings.yml +1077 -0
- package/data/index.md +3 -0
- package/data/language/csharp/basics.md +210 -0
- package/data/language/csharp/testing.md +252 -0
- package/data/language/go/basics.md +158 -0
- package/data/language/go/testing.md +192 -0
- package/data/language/index.md +14 -0
- package/data/language/java/basics.md +184 -0
- package/data/language/java/testing.md +273 -0
- package/data/language/javascript/basics.md +217 -0
- package/data/language/javascript/testing.md +269 -0
- package/data/language/python/async.md +100 -0
- package/data/language/python/basics.md +100 -0
- package/data/language/python/index.md +10 -0
- package/data/language/python/testing.md +125 -0
- package/data/language/python/types.md +99 -0
- package/data/language/ruby/basics.md +227 -0
- package/data/language/ruby/testing.md +267 -0
- package/data/language/rust/basics.md +175 -0
- package/data/language/rust/testing.md +219 -0
- package/data/language/typescript/async.md +103 -0
- package/data/language/typescript/basics.md +87 -0
- package/data/language/typescript/config.md +95 -0
- package/data/language/typescript/error-handling.md +98 -0
- package/data/language/typescript/generics.md +85 -0
- package/data/language/typescript/index.md +14 -0
- package/data/language/typescript/interfaces-types.md +83 -0
- package/data/language/typescript/performance.md +103 -0
- package/data/language/typescript/testing.md +98 -0
- package/data/patterns/base-patterns.md +105 -0
- package/data/patterns/concurrency.md +87 -0
- package/data/patterns/data-access.md +83 -0
- package/data/patterns/distribution.md +86 -0
- package/data/patterns/domain-logic.md +81 -0
- package/data/patterns/gof.md +109 -0
- package/data/patterns/index.md +12 -0
- package/data/performance/async.md +148 -0
- package/data/performance/basics.md +324 -0
- package/data/performance/caching-strategies.md +68 -0
- package/data/performance/caching.md +152 -0
- package/data/performance/index.md +8 -0
- package/data/practices/code-review.md +52 -0
- package/data/practices/documentation.md +260 -0
- package/data/practices/index.md +11 -0
- package/data/practices/planning.md +142 -0
- package/data/practices/refactoring.md +91 -0
- package/data/practices/version-control.md +55 -0
- package/data/security/auth-jwt.md +159 -0
- package/data/security/headers.md +143 -0
- package/data/security/index.md +10 -0
- package/data/security/injection.md +119 -0
- package/data/security/secrets.md +148 -0
- package/data/style/index.md +8 -0
- package/data/style/naming.md +136 -0
- package/data/style/organization.md +162 -0
- package/data/templates/agents/architecture-reviewer.md +88 -0
- package/data/templates/agents/guideline-checker.md +73 -0
- package/data/templates/agents/security-auditor.md +108 -0
- package/data/templates/antigravity/rules/architecture.md.hbs +5 -0
- package/data/templates/antigravity/rules/code-style.md.hbs +5 -0
- package/data/templates/antigravity/rules/language.md.hbs +5 -0
- package/data/templates/antigravity/rules/performance.md.hbs +5 -0
- package/data/templates/antigravity/rules/security.md.hbs +5 -0
- package/data/templates/antigravity/rules/testing.md.hbs +5 -0
- package/data/templates/antigravity/workflows/add-documentation.md.hbs +23 -0
- package/data/templates/antigravity/workflows/generate-integration-tests.md.hbs +17 -0
- package/data/templates/antigravity/workflows/generate-unit-tests.md.hbs +20 -0
- package/data/templates/antigravity/workflows/performance-audit.md.hbs +24 -0
- package/data/templates/antigravity/workflows/refactor-extract-module.md.hbs +17 -0
- package/data/templates/antigravity/workflows/security-audit.md.hbs +20 -0
- package/data/templates/hooks/formatting.json +26 -0
- package/data/templates/hooks/security.json +35 -0
- package/data/templates/hooks/testing.json +17 -0
- package/data/testing/basics.md +151 -0
- package/data/testing/index.md +9 -0
- package/data/testing/integration.md +159 -0
- package/data/testing/unit-fundamentals.md +128 -0
- package/data/testing/unit-mocking.md +116 -0
- package/data/version.json +49 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +46 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/config/profiles.d.ts +4 -0
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/config/profiles.js +30 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/settings.d.ts +7 -0
- package/dist/config/settings.d.ts.map +1 -0
- package/dist/config/settings.js +7 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58489 -0
- package/dist/index.js.map +1 -0
- package/dist/models/guideline.d.ts +15 -0
- package/dist/models/guideline.d.ts.map +1 -0
- package/dist/models/guideline.js +2 -0
- package/dist/models/guideline.js.map +1 -0
- package/dist/models/preference.d.ts +9 -0
- package/dist/models/preference.d.ts.map +1 -0
- package/dist/models/preference.js +2 -0
- package/dist/models/preference.js.map +1 -0
- package/dist/models/profile.d.ts +9 -0
- package/dist/models/profile.d.ts.map +1 -0
- package/dist/models/profile.js +2 -0
- package/dist/models/profile.js.map +1 -0
- package/dist/models/project.d.ts +13 -0
- package/dist/models/project.d.ts.map +1 -0
- package/dist/models/project.js +2 -0
- package/dist/models/project.js.map +1 -0
- package/dist/services/ai/anthropic.d.ts +7 -0
- package/dist/services/ai/anthropic.d.ts.map +1 -0
- package/dist/services/ai/anthropic.js +39 -0
- package/dist/services/ai/anthropic.js.map +1 -0
- package/dist/services/generator.d.ts +2 -0
- package/dist/services/generator.d.ts.map +1 -0
- package/dist/services/generator.js +4 -0
- package/dist/services/generator.js.map +1 -0
- package/dist/services/learner.d.ts +2 -0
- package/dist/services/learner.d.ts.map +1 -0
- package/dist/services/learner.js +4 -0
- package/dist/services/learner.js.map +1 -0
- package/dist/services/scanner.d.ts +3 -0
- package/dist/services/scanner.d.ts.map +1 -0
- package/dist/services/scanner.js +54 -0
- package/dist/services/scanner.js.map +1 -0
- package/dist/utils/errors.d.ts +15 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +27 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/file.d.ts +7 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +32 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +17 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path.d.ts +6 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +14 -0
- package/dist/utils/path.js.map +1 -0
- package/docs/planning/memory-lane.md +83 -0
- package/package.json +64 -0
- package/packaging/linux/aicgen.spec +23 -0
- package/packaging/linux/control +9 -0
- package/packaging/macos/scripts/postinstall +12 -0
- package/packaging/windows/setup.nsi +92 -0
- package/planning/BRANDING-SUMMARY.md +194 -0
- package/planning/BRANDING.md +174 -0
- package/planning/BUILD.md +186 -0
- package/planning/CHUNK-IMPLEMENTATION-PLAN.md +87 -0
- package/planning/CHUNK-TAXONOMY.md +375 -0
- package/planning/CHUNKS-COMPLETE.md +382 -0
- package/planning/DESIGN.md +313 -0
- package/planning/DYNAMIC-GUIDELINES-DESIGN.md +265 -0
- package/planning/ENTERPRISE-UX-COMPLETE.md +281 -0
- package/planning/IMPLEMENTATION-PLAN.md +20 -0
- package/planning/PHASE1-COMPLETE.md +211 -0
- package/planning/PHASE2-COMPLETE.md +350 -0
- package/planning/PHASE3-COMPLETE.md +399 -0
- package/planning/PHASE4-COMPLETE.md +361 -0
- package/planning/PHASE4.5-CHUNKS.md +462 -0
- package/planning/STRUCTURE.md +170 -0
- package/scripts/add-categories.ts +87 -0
- package/scripts/build-binary.ts +46 -0
- package/scripts/embed-data.ts +105 -0
- package/scripts/generate-version.ts +150 -0
- package/scripts/test-decompress.ts +27 -0
- package/scripts/test-extract.ts +31 -0
- package/src/__tests__/services/assistant-file-writer.test.ts +400 -0
- package/src/__tests__/services/guideline-loader.test.ts +281 -0
- package/src/__tests__/services/tarball-extraction.test.ts +125 -0
- package/src/commands/add-guideline.ts +296 -0
- package/src/commands/clear.ts +61 -0
- package/src/commands/guideline-selector.ts +123 -0
- package/src/commands/init.ts +645 -0
- package/src/commands/quick-add.ts +586 -0
- package/src/commands/remove-guideline.ts +152 -0
- package/src/commands/stats.ts +49 -0
- package/src/commands/update.ts +240 -0
- package/src/config.ts +82 -0
- package/src/embedded-data.ts +1492 -0
- package/src/index.ts +67 -0
- package/src/models/profile.ts +24 -0
- package/src/models/project.ts +43 -0
- package/src/services/assistant-file-writer.ts +612 -0
- package/src/services/config-generator.ts +150 -0
- package/src/services/config-manager.ts +70 -0
- package/src/services/data-source.ts +248 -0
- package/src/services/first-run-init.ts +148 -0
- package/src/services/guideline-loader.ts +311 -0
- package/src/services/hook-generator.ts +178 -0
- package/src/services/subagent-generator.ts +310 -0
- package/src/utils/banner.ts +66 -0
- package/src/utils/errors.ts +27 -0
- package/src/utils/file.ts +67 -0
- package/src/utils/formatting.ts +172 -0
- package/src/utils/logger.ts +89 -0
- package/src/utils/path.ts +17 -0
- package/src/utils/wizard-state.ts +132 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Database Indexing
|
|
2
|
+
|
|
3
|
+
## When to Add Indexes
|
|
4
|
+
|
|
5
|
+
```sql
|
|
6
|
+
-- ✅ Columns in WHERE clauses
|
|
7
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
8
|
+
|
|
9
|
+
-- ✅ Foreign key columns
|
|
10
|
+
CREATE INDEX idx_orders_user_id ON orders(user_id);
|
|
11
|
+
|
|
12
|
+
-- ✅ Columns used in ORDER BY
|
|
13
|
+
CREATE INDEX idx_products_created_at ON products(created_at DESC);
|
|
14
|
+
|
|
15
|
+
-- ✅ Columns used in JOIN conditions
|
|
16
|
+
CREATE INDEX idx_order_items_product_id ON order_items(product_id);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Composite Indexes
|
|
20
|
+
|
|
21
|
+
```sql
|
|
22
|
+
-- Order matters! Put most selective column first
|
|
23
|
+
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
|
|
24
|
+
|
|
25
|
+
-- This index helps with:
|
|
26
|
+
SELECT * FROM orders WHERE user_id = 123;
|
|
27
|
+
SELECT * FROM orders WHERE user_id = 123 AND status = 'pending';
|
|
28
|
+
|
|
29
|
+
-- But NOT with:
|
|
30
|
+
SELECT * FROM orders WHERE status = 'pending'; -- Can't use index
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Partial Indexes
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
-- Index only rows matching condition
|
|
37
|
+
CREATE INDEX idx_active_users ON users(email) WHERE is_active = true;
|
|
38
|
+
|
|
39
|
+
-- Smaller index, faster queries on active users
|
|
40
|
+
SELECT * FROM users WHERE email = 'x@y.com' AND is_active = true;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Unique Indexes
|
|
44
|
+
|
|
45
|
+
```sql
|
|
46
|
+
-- Enforces uniqueness and improves lookup
|
|
47
|
+
CREATE UNIQUE INDEX idx_users_email ON users(email);
|
|
48
|
+
|
|
49
|
+
-- Multi-column unique
|
|
50
|
+
CREATE UNIQUE INDEX idx_unique_order_item ON order_items(order_id, product_id);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Index Types
|
|
54
|
+
|
|
55
|
+
```sql
|
|
56
|
+
-- B-tree (default): =, <, >, <=, >=, BETWEEN
|
|
57
|
+
CREATE INDEX idx_products_price ON products(price);
|
|
58
|
+
|
|
59
|
+
-- Hash: Only equality (=)
|
|
60
|
+
CREATE INDEX idx_users_id_hash ON users USING hash (id);
|
|
61
|
+
|
|
62
|
+
-- GIN: Arrays, JSONB, full-text search
|
|
63
|
+
CREATE INDEX idx_products_tags ON products USING gin (tags);
|
|
64
|
+
|
|
65
|
+
-- GiST: Geometric data, range queries
|
|
66
|
+
CREATE INDEX idx_locations ON places USING gist (location);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Analyze Query Performance
|
|
70
|
+
|
|
71
|
+
```sql
|
|
72
|
+
-- EXPLAIN ANALYZE shows actual execution
|
|
73
|
+
EXPLAIN ANALYZE
|
|
74
|
+
SELECT * FROM users WHERE email = 'test@example.com';
|
|
75
|
+
|
|
76
|
+
-- Look for:
|
|
77
|
+
-- ✅ Index Scan / Index Only Scan (good)
|
|
78
|
+
-- ❌ Seq Scan on large tables (bad)
|
|
79
|
+
-- ❌ High "actual time" values (slow)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Index Maintenance
|
|
83
|
+
|
|
84
|
+
```sql
|
|
85
|
+
-- Monitor index usage (PostgreSQL)
|
|
86
|
+
SELECT
|
|
87
|
+
schemaname, tablename, indexname, idx_scan, idx_tup_read
|
|
88
|
+
FROM pg_stat_user_indexes
|
|
89
|
+
ORDER BY idx_scan ASC;
|
|
90
|
+
|
|
91
|
+
-- Remove unused indexes (0 scans)
|
|
92
|
+
DROP INDEX IF EXISTS unused_index_name;
|
|
93
|
+
|
|
94
|
+
-- Rebuild bloated indexes
|
|
95
|
+
REINDEX INDEX index_name;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Anti-Patterns
|
|
99
|
+
|
|
100
|
+
```sql
|
|
101
|
+
-- ❌ Indexing every column
|
|
102
|
+
-- Slows down INSERT/UPDATE, wastes space
|
|
103
|
+
|
|
104
|
+
-- ❌ Indexes on low-cardinality columns
|
|
105
|
+
-- Boolean columns rarely benefit from indexes
|
|
106
|
+
|
|
107
|
+
-- ❌ Functions on indexed columns
|
|
108
|
+
-- SELECT * FROM users WHERE LOWER(email) = 'x'; -- Can't use index!
|
|
109
|
+
|
|
110
|
+
-- ✅ Use expression index instead
|
|
111
|
+
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Connection Pooling
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// ❌ New connection per query
|
|
118
|
+
const getUser = async (id: string) => {
|
|
119
|
+
const conn = await createConnection(); // Expensive!
|
|
120
|
+
const user = await conn.query('SELECT * FROM users WHERE id = ?', [id]);
|
|
121
|
+
await conn.close();
|
|
122
|
+
return user;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// ✅ Use connection pool
|
|
126
|
+
const pool = new Pool({ max: 20, idleTimeoutMillis: 30000 });
|
|
127
|
+
|
|
128
|
+
const getUser = async (id: string) => {
|
|
129
|
+
const client = await pool.connect();
|
|
130
|
+
try {
|
|
131
|
+
return await client.query('SELECT * FROM users WHERE id = $1', [id]);
|
|
132
|
+
} finally {
|
|
133
|
+
client.release(); // Return to pool
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
```
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# NoSQL Database Patterns
|
|
2
|
+
|
|
3
|
+
## Document Databases (MongoDB, CouchDB)
|
|
4
|
+
|
|
5
|
+
### Schema Design
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Embed vs Reference
|
|
9
|
+
|
|
10
|
+
// ✅ Embed: Data accessed together, 1:few relationship
|
|
11
|
+
interface Order {
|
|
12
|
+
_id: ObjectId;
|
|
13
|
+
customerId: ObjectId;
|
|
14
|
+
items: Array<{ // Embedded
|
|
15
|
+
productId: ObjectId;
|
|
16
|
+
name: string;
|
|
17
|
+
quantity: number;
|
|
18
|
+
price: number;
|
|
19
|
+
}>;
|
|
20
|
+
shippingAddress: { // Embedded
|
|
21
|
+
street: string;
|
|
22
|
+
city: string;
|
|
23
|
+
country: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ✅ Reference: Data accessed separately, 1:many relationship
|
|
28
|
+
interface Post {
|
|
29
|
+
_id: ObjectId;
|
|
30
|
+
title: string;
|
|
31
|
+
content: string;
|
|
32
|
+
authorId: ObjectId; // Reference to User
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Comment {
|
|
36
|
+
_id: ObjectId;
|
|
37
|
+
postId: ObjectId; // Reference to Post
|
|
38
|
+
authorId: ObjectId; // Reference to User
|
|
39
|
+
content: string;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Indexing
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Single field index
|
|
47
|
+
db.users.createIndex({ email: 1 });
|
|
48
|
+
|
|
49
|
+
// Compound index (order matters!)
|
|
50
|
+
db.orders.createIndex({ customerId: 1, createdAt: -1 });
|
|
51
|
+
|
|
52
|
+
// Partial index
|
|
53
|
+
db.users.createIndex(
|
|
54
|
+
{ email: 1 },
|
|
55
|
+
{ partialFilterExpression: { status: "active" } }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Text search index
|
|
59
|
+
db.products.createIndex({ name: "text", description: "text" });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Query Patterns
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Avoid N+1 queries - use $lookup for joins
|
|
66
|
+
const ordersWithCustomers = await db.orders.aggregate([
|
|
67
|
+
{
|
|
68
|
+
$lookup: {
|
|
69
|
+
from: "customers",
|
|
70
|
+
localField: "customerId",
|
|
71
|
+
foreignField: "_id",
|
|
72
|
+
as: "customer"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{ $unwind: "$customer" }
|
|
76
|
+
]).toArray();
|
|
77
|
+
|
|
78
|
+
// Use projections to limit returned fields
|
|
79
|
+
const userNames = await db.users.find(
|
|
80
|
+
{ status: "active" },
|
|
81
|
+
{ projection: { name: 1, email: 1 } }
|
|
82
|
+
).toArray();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Key-Value Stores (Redis, DynamoDB)
|
|
86
|
+
|
|
87
|
+
### Redis Patterns
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Caching with TTL
|
|
91
|
+
await redis.setex(`user:${userId}`, 3600, JSON.stringify(user));
|
|
92
|
+
|
|
93
|
+
// Rate limiting
|
|
94
|
+
async function isRateLimited(userId: string): Promise<boolean> {
|
|
95
|
+
const key = `rate:${userId}`;
|
|
96
|
+
const count = await redis.incr(key);
|
|
97
|
+
if (count === 1) {
|
|
98
|
+
await redis.expire(key, 60); // 60 second window
|
|
99
|
+
}
|
|
100
|
+
return count > 100; // 100 requests per minute
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Distributed locks
|
|
104
|
+
async function acquireLock(key: string, ttl: number): Promise<boolean> {
|
|
105
|
+
const result = await redis.set(`lock:${key}`, "1", "NX", "EX", ttl);
|
|
106
|
+
return result === "OK";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Pub/Sub
|
|
110
|
+
await redis.publish("events", JSON.stringify({ type: "user.created", data: user }));
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### DynamoDB Patterns
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Single table design - access patterns first
|
|
117
|
+
interface Item {
|
|
118
|
+
PK: string; // Partition key: USER#<userId>
|
|
119
|
+
SK: string; // Sort key: ORDER#<orderId>
|
|
120
|
+
GSI1PK?: string; // Global Secondary Index
|
|
121
|
+
GSI1SK?: string;
|
|
122
|
+
// ... attributes
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Write with condition
|
|
126
|
+
await dynamodb.put({
|
|
127
|
+
TableName: "orders",
|
|
128
|
+
Item: order,
|
|
129
|
+
ConditionExpression: "attribute_not_exists(PK)" // Prevent duplicates
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Query with begins_with
|
|
133
|
+
const userOrders = await dynamodb.query({
|
|
134
|
+
TableName: "orders",
|
|
135
|
+
KeyConditionExpression: "PK = :pk AND begins_with(SK, :sk)",
|
|
136
|
+
ExpressionAttributeValues: {
|
|
137
|
+
":pk": `USER#${userId}`,
|
|
138
|
+
":sk": "ORDER#"
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Wide Column Stores (Cassandra)
|
|
144
|
+
|
|
145
|
+
### Data Modeling
|
|
146
|
+
|
|
147
|
+
```sql
|
|
148
|
+
-- Design for queries, not relationships
|
|
149
|
+
-- One table per query pattern
|
|
150
|
+
|
|
151
|
+
CREATE TABLE orders_by_customer (
|
|
152
|
+
customer_id UUID,
|
|
153
|
+
order_date TIMESTAMP,
|
|
154
|
+
order_id UUID,
|
|
155
|
+
total DECIMAL,
|
|
156
|
+
PRIMARY KEY ((customer_id), order_date, order_id)
|
|
157
|
+
) WITH CLUSTERING ORDER BY (order_date DESC);
|
|
158
|
+
|
|
159
|
+
CREATE TABLE orders_by_date (
|
|
160
|
+
order_date DATE,
|
|
161
|
+
order_id UUID,
|
|
162
|
+
customer_id UUID,
|
|
163
|
+
total DECIMAL,
|
|
164
|
+
PRIMARY KEY ((order_date), order_id)
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Best Practices
|
|
169
|
+
|
|
170
|
+
### Denormalization
|
|
171
|
+
- Duplicate data for read performance
|
|
172
|
+
- Design for query patterns, not normalization
|
|
173
|
+
- Accept eventual consistency
|
|
174
|
+
|
|
175
|
+
### Data Modeling
|
|
176
|
+
- Start with access patterns
|
|
177
|
+
- One table per query (or single-table design for DynamoDB)
|
|
178
|
+
- Embed related data that's always accessed together
|
|
179
|
+
- Reference data that's accessed independently
|
|
180
|
+
|
|
181
|
+
### Performance
|
|
182
|
+
- Use indexes strategically
|
|
183
|
+
- Batch operations when possible
|
|
184
|
+
- Use TTL for temporary data
|
|
185
|
+
- Consider sharding/partitioning for scale
|
|
186
|
+
|
|
187
|
+
### Consistency
|
|
188
|
+
- Understand your consistency model (eventual vs strong)
|
|
189
|
+
- Use transactions when available and necessary
|
|
190
|
+
- Design for idempotency
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Idempotent writes with version/timestamp
|
|
194
|
+
async function updateUser(user: User): Promise<void> {
|
|
195
|
+
await db.users.updateOne(
|
|
196
|
+
{ _id: user._id, version: user.version },
|
|
197
|
+
{ $set: { ...user, version: user.version + 1 } }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Error Handling
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Retry with exponential backoff
|
|
206
|
+
async function withRetry<T>(
|
|
207
|
+
operation: () => Promise<T>,
|
|
208
|
+
maxRetries = 3
|
|
209
|
+
): Promise<T> {
|
|
210
|
+
let lastError: Error;
|
|
211
|
+
|
|
212
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
213
|
+
try {
|
|
214
|
+
return await operation();
|
|
215
|
+
} catch (error) {
|
|
216
|
+
lastError = error as Error;
|
|
217
|
+
await sleep(Math.pow(2, i) * 100);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
throw lastError!;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Database Schema Design
|
|
2
|
+
|
|
3
|
+
## Naming Conventions
|
|
4
|
+
|
|
5
|
+
```sql
|
|
6
|
+
-- Tables: plural, snake_case
|
|
7
|
+
CREATE TABLE users (...);
|
|
8
|
+
CREATE TABLE order_items (...);
|
|
9
|
+
|
|
10
|
+
-- Columns: singular, snake_case
|
|
11
|
+
user_id, created_at, is_active
|
|
12
|
+
|
|
13
|
+
-- Primary keys: id
|
|
14
|
+
id SERIAL PRIMARY KEY
|
|
15
|
+
|
|
16
|
+
-- Foreign keys: singular_table_id
|
|
17
|
+
user_id REFERENCES users(id)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Primary Keys
|
|
21
|
+
|
|
22
|
+
```sql
|
|
23
|
+
-- ✅ Auto-incrementing integer (simple cases)
|
|
24
|
+
id SERIAL PRIMARY KEY
|
|
25
|
+
|
|
26
|
+
-- ✅ UUID for distributed systems
|
|
27
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
28
|
+
|
|
29
|
+
-- ❌ Avoid composite primary keys when possible
|
|
30
|
+
-- They complicate joins and foreign keys
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Essential Columns
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
-- ✅ Standard audit columns
|
|
37
|
+
CREATE TABLE products (
|
|
38
|
+
id SERIAL PRIMARY KEY,
|
|
39
|
+
name VARCHAR(255) NOT NULL,
|
|
40
|
+
price DECIMAL(10,2) NOT NULL,
|
|
41
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
42
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
43
|
+
deleted_at TIMESTAMP NULL -- Soft delete
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- ✅ Version column for optimistic locking
|
|
47
|
+
version INTEGER DEFAULT 1
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Relationships
|
|
51
|
+
|
|
52
|
+
```sql
|
|
53
|
+
-- One-to-Many: Foreign key on "many" side
|
|
54
|
+
CREATE TABLE orders (
|
|
55
|
+
id SERIAL PRIMARY KEY,
|
|
56
|
+
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
|
57
|
+
total DECIMAL(10,2)
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
-- Many-to-Many: Junction table
|
|
61
|
+
CREATE TABLE order_items (
|
|
62
|
+
order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE,
|
|
63
|
+
product_id INTEGER REFERENCES products(id),
|
|
64
|
+
quantity INTEGER NOT NULL,
|
|
65
|
+
PRIMARY KEY (order_id, product_id)
|
|
66
|
+
);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Constraints
|
|
70
|
+
|
|
71
|
+
```sql
|
|
72
|
+
-- ✅ NOT NULL for required fields
|
|
73
|
+
email VARCHAR(255) NOT NULL
|
|
74
|
+
|
|
75
|
+
-- ✅ UNIQUE constraints
|
|
76
|
+
email VARCHAR(255) UNIQUE NOT NULL
|
|
77
|
+
|
|
78
|
+
-- ✅ CHECK constraints for validation
|
|
79
|
+
age INTEGER CHECK (age >= 0 AND age <= 150)
|
|
80
|
+
status VARCHAR(20) CHECK (status IN ('pending', 'active', 'cancelled'))
|
|
81
|
+
|
|
82
|
+
-- ✅ DEFAULT values
|
|
83
|
+
is_active BOOLEAN DEFAULT true
|
|
84
|
+
role VARCHAR(20) DEFAULT 'user'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Data Types
|
|
88
|
+
|
|
89
|
+
```sql
|
|
90
|
+
-- Strings
|
|
91
|
+
VARCHAR(255) -- Variable length, max 255
|
|
92
|
+
TEXT -- Unlimited length
|
|
93
|
+
|
|
94
|
+
-- Numbers
|
|
95
|
+
INTEGER -- Whole numbers
|
|
96
|
+
BIGINT -- Large whole numbers
|
|
97
|
+
DECIMAL(10,2) -- Exact decimals (money)
|
|
98
|
+
REAL/DOUBLE -- Approximate decimals (scientific)
|
|
99
|
+
|
|
100
|
+
-- Dates/Times
|
|
101
|
+
TIMESTAMP -- Date and time
|
|
102
|
+
DATE -- Date only
|
|
103
|
+
INTERVAL -- Duration
|
|
104
|
+
|
|
105
|
+
-- Other
|
|
106
|
+
BOOLEAN -- true/false
|
|
107
|
+
UUID -- Unique identifier
|
|
108
|
+
JSONB -- JSON with indexing (PostgreSQL)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Normalization Guidelines
|
|
112
|
+
|
|
113
|
+
```sql
|
|
114
|
+
-- ✅ 1NF: Atomic values, no repeating groups
|
|
115
|
+
-- ❌ Bad: tags VARCHAR = 'tag1,tag2,tag3'
|
|
116
|
+
-- ✅ Good: Separate tags table
|
|
117
|
+
|
|
118
|
+
-- ✅ 2NF: No partial dependencies
|
|
119
|
+
-- All non-key columns depend on entire primary key
|
|
120
|
+
|
|
121
|
+
-- ✅ 3NF: No transitive dependencies
|
|
122
|
+
-- Non-key columns don't depend on other non-key columns
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Denormalization (When Appropriate)
|
|
126
|
+
|
|
127
|
+
```sql
|
|
128
|
+
-- Cache computed values for read performance
|
|
129
|
+
CREATE TABLE orders (
|
|
130
|
+
id SERIAL PRIMARY KEY,
|
|
131
|
+
user_id INTEGER REFERENCES users(id),
|
|
132
|
+
items_count INTEGER DEFAULT 0, -- Denormalized
|
|
133
|
+
total DECIMAL(10,2) DEFAULT 0 -- Denormalized
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
-- Update via triggers or application logic
|
|
137
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# CI/CD Practices
|
|
2
|
+
|
|
3
|
+
## Continuous Integration
|
|
4
|
+
|
|
5
|
+
Run on every commit:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# .github/workflows/ci.yml
|
|
9
|
+
name: CI
|
|
10
|
+
on: [push, pull_request]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '20'
|
|
20
|
+
cache: 'npm'
|
|
21
|
+
- run: npm ci
|
|
22
|
+
- run: npm run lint
|
|
23
|
+
- run: npm run typecheck
|
|
24
|
+
- run: npm test
|
|
25
|
+
- run: npm run build
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Continuous Deployment
|
|
29
|
+
|
|
30
|
+
Deploy automatically after CI passes:
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
deploy:
|
|
34
|
+
needs: build
|
|
35
|
+
if: github.ref == 'refs/heads/main'
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- run: npm ci
|
|
40
|
+
- run: npm run build
|
|
41
|
+
- run: npm run deploy
|
|
42
|
+
env:
|
|
43
|
+
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Deployment Strategies
|
|
47
|
+
|
|
48
|
+
### Blue-Green Deployment
|
|
49
|
+
Run two identical environments, switch traffic instantly.
|
|
50
|
+
|
|
51
|
+
### Canary Releases
|
|
52
|
+
Route small percentage of traffic to new version first.
|
|
53
|
+
|
|
54
|
+
### Rolling Updates
|
|
55
|
+
Gradually replace instances with new version.
|
|
56
|
+
|
|
57
|
+
## Best Practices
|
|
58
|
+
|
|
59
|
+
- Run fast tests first, slow tests later
|
|
60
|
+
- Cache dependencies between runs
|
|
61
|
+
- Use matrix builds for multiple versions/platforms
|
|
62
|
+
- Keep secrets in secure storage
|
|
63
|
+
- Automate database migrations
|
|
64
|
+
- Include rollback procedures
|
|
65
|
+
- Monitor deployments with health checks
|
|
66
|
+
- Use feature flags for safer releases
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Observability
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Observability 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.
|
|
6
|
+
|
|
7
|
+
## Three Pillars
|
|
8
|
+
|
|
9
|
+
### 1. Structured Logging
|
|
10
|
+
|
|
11
|
+
Logs should be machine-readable (JSON) and contain context.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
// ✅ Good: Structured JSON logging
|
|
15
|
+
{
|
|
16
|
+
"level": "info",
|
|
17
|
+
"message": "Order processed",
|
|
18
|
+
"orderId": "ord_123",
|
|
19
|
+
"userId": "user_456",
|
|
20
|
+
"amount": 99.99,
|
|
21
|
+
"durationMs": 145,
|
|
22
|
+
"status": "success"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
```text
|
|
26
|
+
// ❌ Bad: Unstructured text
|
|
27
|
+
"Order processed: ord_123 for user_456"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Metrics
|
|
31
|
+
|
|
32
|
+
Aggregatable data points for identifying trends and health.
|
|
33
|
+
|
|
34
|
+
- **Counters**: Total requests, error counts (`http_requests_total`)
|
|
35
|
+
- **Gauges**: Queue depth, memory usage (`memory_usage_bytes`)
|
|
36
|
+
- **Histograms**: Request latency distribution (`http_request_duration_seconds`)
|
|
37
|
+
|
|
38
|
+
### 3. Distributed Tracing
|
|
39
|
+
|
|
40
|
+
Tracking requests as they propagate through services.
|
|
41
|
+
|
|
42
|
+
- **Trace ID**: Unique ID for the entire request chain
|
|
43
|
+
- **Span ID**: Unique ID for a specific operation
|
|
44
|
+
- **Context Propagation**: Passing IDs between services (e.g., W3C Trace Context)
|
|
45
|
+
|
|
46
|
+
## Implementation Strategy
|
|
47
|
+
|
|
48
|
+
### OpenTelemetry (OTel)
|
|
49
|
+
|
|
50
|
+
Use OpenTelemetry as the vendor-neutral standard for collecting telemetry data.
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
# Initialize OpenTelemetry SDK
|
|
54
|
+
SDK.Configure({
|
|
55
|
+
TraceExporter: Console/OTLP,
|
|
56
|
+
Instrumentations: [Http, Database, Grpc]
|
|
57
|
+
})
|
|
58
|
+
SDK.Start()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Health Checks
|
|
62
|
+
|
|
63
|
+
Expose standard health endpoints:
|
|
64
|
+
|
|
65
|
+
- `/health/live`: Is the process running? (Liveness)
|
|
66
|
+
- `/health/ready`: Can it accept traffic? (Readiness)
|
|
67
|
+
- `/health/startup`: Has it finished initializing? (Startup)
|
|
68
|
+
|
|
69
|
+
## Alerting Best Practices
|
|
70
|
+
|
|
71
|
+
- **Alert on Symptoms, not Causes**: "High Error Rate" (Symptom) vs "CPU High" (Cause).
|
|
72
|
+
- **Golden Signals**: Latency, Traffic, Errors, Saturation.
|
|
73
|
+
- **Actionable**: Every alert should require a specific human action.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# DevOps Practices
|
|
2
|
+
|
|
3
|
+
## Infrastructure as Code
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
# Define infrastructure as code (e.g., Terraform, Pulumi)
|
|
7
|
+
|
|
8
|
+
Resource S3Bucket "app-bucket":
|
|
9
|
+
Access: Private
|
|
10
|
+
Versioning: Enabled
|
|
11
|
+
|
|
12
|
+
Resource LambdaFunction "api":
|
|
13
|
+
Runtime: Node.js / Python / Go
|
|
14
|
+
Handler: index.handler
|
|
15
|
+
Code: ./dist
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Containerization
|
|
19
|
+
|
|
20
|
+
```dockerfile
|
|
21
|
+
# Build Stage
|
|
22
|
+
FROM base-image AS builder
|
|
23
|
+
WORKDIR /app
|
|
24
|
+
COPY dependency-files ./
|
|
25
|
+
RUN install-dependencies
|
|
26
|
+
COPY source-code .
|
|
27
|
+
RUN build-application
|
|
28
|
+
|
|
29
|
+
# Runtime Stage
|
|
30
|
+
FROM runtime-image
|
|
31
|
+
WORKDIR /app
|
|
32
|
+
COPY --from=builder /app/dist ./dist
|
|
33
|
+
EXPOSE 8080
|
|
34
|
+
CMD ["run", "application"]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Observability
|
|
38
|
+
|
|
39
|
+
### Logging
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"level": "info",
|
|
43
|
+
"message": "Order created",
|
|
44
|
+
"orderId": "ord_123",
|
|
45
|
+
"customerId": "cust_456",
|
|
46
|
+
"total": 99.99,
|
|
47
|
+
"timestamp": "2023-10-27T10:00:00Z"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Metrics
|
|
52
|
+
```text
|
|
53
|
+
Metrics.Increment("orders.created")
|
|
54
|
+
Metrics.Histogram("order.value", total)
|
|
55
|
+
Metrics.Timing("order.processing_time", duration)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Health Checks
|
|
59
|
+
```text
|
|
60
|
+
GET /health
|
|
61
|
+
Response 200 OK:
|
|
62
|
+
{
|
|
63
|
+
"status": "healthy",
|
|
64
|
+
"version": "1.2.3",
|
|
65
|
+
"uptime": 3600
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Best Practices
|
|
70
|
+
|
|
71
|
+
- Version control all infrastructure
|
|
72
|
+
- Use immutable infrastructure
|
|
73
|
+
- Implement proper secret management
|
|
74
|
+
- Set up alerting for critical metrics
|
|
75
|
+
- Use structured logging (JSON)
|
|
76
|
+
- Include correlation IDs for tracing
|
|
77
|
+
- Document runbooks for incidents
|