@hivehub/rulebook 5.5.2 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/rulebook-learn-capture.md +41 -48
- package/.claude/commands/rulebook-learn-list.md +13 -13
- package/README.md +332 -394
- package/dist/cli/commands/context-intelligence.d.ts +0 -1
- package/dist/cli/commands/context-intelligence.d.ts.map +1 -1
- package/dist/cli/commands/context-intelligence.js +12 -33
- package/dist/cli/commands/context-intelligence.js.map +1 -1
- package/dist/cli/commands/index.d.ts +4 -7
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +4 -7
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +40 -81
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts +0 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +1 -7
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/memory.d.ts +7 -1
- package/dist/cli/commands/memory.d.ts.map +1 -1
- package/dist/cli/commands/memory.js +51 -57
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/cli/commands/misc.d.ts +1 -15
- package/dist/cli/commands/misc.d.ts.map +1 -1
- package/dist/cli/commands/misc.js +36 -215
- package/dist/cli/commands/misc.js.map +1 -1
- package/dist/cli/commands/plans.d.ts +0 -6
- package/dist/cli/commands/plans.d.ts.map +1 -1
- package/dist/cli/commands/plans.js +9 -77
- package/dist/cli/commands/plans.js.map +1 -1
- package/dist/cli/commands/skills.js +6 -6
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/task.js +4 -4
- package/dist/cli/commands/task.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +122 -52
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/prompts.d.ts.map +1 -1
- package/dist/cli/prompts.js +1 -78
- package/dist/cli/prompts.js.map +1 -1
- package/dist/core/claude/claude-mcp.d.ts +59 -0
- package/dist/core/claude/claude-mcp.d.ts.map +1 -0
- package/dist/core/claude/claude-mcp.js +220 -0
- package/dist/core/claude/claude-mcp.js.map +1 -0
- package/dist/core/claude/claude-md-generator.d.ts +52 -0
- package/dist/core/claude/claude-md-generator.d.ts.map +1 -0
- package/dist/core/claude/claude-md-generator.js +104 -0
- package/dist/core/claude/claude-md-generator.js.map +1 -0
- package/dist/core/claude/claude-settings-manager.d.ts +44 -0
- package/dist/core/claude/claude-settings-manager.d.ts.map +1 -0
- package/dist/core/claude/claude-settings-manager.js +194 -0
- package/dist/core/claude/claude-settings-manager.js.map +1 -0
- package/dist/core/console/cli-bridge.d.ts +113 -0
- package/dist/core/console/cli-bridge.d.ts.map +1 -0
- package/dist/core/console/cli-bridge.js +1094 -0
- package/dist/core/console/cli-bridge.js.map +1 -0
- package/dist/core/detect/detector.d.ts +35 -0
- package/dist/core/detect/detector.d.ts.map +1 -0
- package/dist/core/detect/detector.js +541 -0
- package/dist/core/detect/detector.js.map +1 -0
- package/dist/core/docs/docs-generator.d.ts +9 -0
- package/dist/core/docs/docs-generator.d.ts.map +1 -0
- package/dist/core/docs/docs-generator.js +531 -0
- package/dist/core/docs/docs-generator.js.map +1 -0
- package/dist/core/docs/mcp-reference-generator.d.ts +13 -0
- package/dist/core/docs/mcp-reference-generator.d.ts.map +1 -0
- package/dist/core/docs/mcp-reference-generator.js +66 -0
- package/dist/core/docs/mcp-reference-generator.js.map +1 -0
- package/dist/core/generators/generator.d.ts +54 -0
- package/dist/core/generators/generator.d.ts.map +1 -0
- package/dist/core/generators/generator.js +1041 -0
- package/dist/core/generators/generator.js.map +1 -0
- package/dist/core/generators/gitignore-generator.d.ts +13 -0
- package/dist/core/generators/gitignore-generator.d.ts.map +1 -0
- package/dist/core/generators/gitignore-generator.js +307 -0
- package/dist/core/generators/gitignore-generator.js.map +1 -0
- package/dist/core/generators/minimal-scaffolder.d.ts +8 -0
- package/dist/core/generators/minimal-scaffolder.d.ts.map +1 -0
- package/dist/core/generators/minimal-scaffolder.js +51 -0
- package/dist/core/generators/minimal-scaffolder.js.map +1 -0
- package/dist/core/generators/rules-generator.d.ts +73 -0
- package/dist/core/generators/rules-generator.d.ts.map +1 -0
- package/dist/core/generators/rules-generator.js +202 -0
- package/dist/core/generators/rules-generator.js.map +1 -0
- package/dist/core/generators/workflow-generator.d.ts +15 -0
- package/dist/core/generators/workflow-generator.d.ts.map +1 -0
- package/dist/core/generators/workflow-generator.js +390 -0
- package/dist/core/generators/workflow-generator.js.map +1 -0
- package/dist/core/ide/multi-tool-generator.d.ts +59 -0
- package/dist/core/ide/multi-tool-generator.d.ts.map +1 -0
- package/dist/core/ide/multi-tool-generator.js +157 -0
- package/dist/core/ide/multi-tool-generator.js.map +1 -0
- package/dist/core/ide/opencode-generator.d.ts +72 -0
- package/dist/core/ide/opencode-generator.d.ts.map +1 -0
- package/dist/core/ide/opencode-generator.js +450 -0
- package/dist/core/ide/opencode-generator.js.map +1 -0
- package/dist/core/merger.d.ts +1 -1
- package/dist/core/merger.d.ts.map +1 -1
- package/dist/core/merger.js +5 -5
- package/dist/core/merger.js.map +1 -1
- package/dist/core/migrator.d.ts +0 -1
- package/dist/core/migrator.d.ts.map +1 -1
- package/dist/core/migrator.js +4 -29
- package/dist/core/migrator.js.map +1 -1
- package/dist/core/quality/coverage-checker.d.ts +14 -0
- package/dist/core/quality/coverage-checker.d.ts.map +1 -0
- package/dist/core/quality/coverage-checker.js +176 -0
- package/dist/core/quality/coverage-checker.js.map +1 -0
- package/dist/core/quality/dependency-checker.d.ts +21 -0
- package/dist/core/quality/dependency-checker.d.ts.map +1 -0
- package/dist/core/quality/dependency-checker.js +247 -0
- package/dist/core/quality/dependency-checker.js.map +1 -0
- package/dist/core/quality/doctor.d.ts +19 -0
- package/dist/core/quality/doctor.d.ts.map +1 -0
- package/dist/core/quality/doctor.js +163 -0
- package/dist/core/quality/doctor.js.map +1 -0
- package/dist/core/quality/validator.d.ts +21 -0
- package/dist/core/quality/validator.d.ts.map +1 -0
- package/dist/core/quality/validator.js +177 -0
- package/dist/core/quality/validator.js.map +1 -0
- package/dist/core/skills/skills-manager.d.ts +126 -0
- package/dist/core/skills/skills-manager.d.ts.map +1 -0
- package/dist/core/skills/skills-manager.js +630 -0
- package/dist/core/skills/skills-manager.js.map +1 -0
- package/dist/core/state/config-manager.d.ts +86 -0
- package/dist/core/state/config-manager.d.ts.map +1 -0
- package/dist/core/state/config-manager.js +562 -0
- package/dist/core/state/config-manager.js.map +1 -0
- package/dist/core/state/override-manager.d.ts +23 -0
- package/dist/core/state/override-manager.d.ts.map +1 -0
- package/dist/core/state/override-manager.js +82 -0
- package/dist/core/state/override-manager.js.map +1 -0
- package/dist/core/state/state-writer.d.ts +34 -0
- package/dist/core/state/state-writer.d.ts.map +1 -0
- package/dist/core/state/state-writer.js +78 -0
- package/dist/core/state/state-writer.js.map +1 -0
- package/dist/core/state/version-bumper.d.ts +19 -0
- package/dist/core/state/version-bumper.d.ts.map +1 -0
- package/dist/core/state/version-bumper.js +180 -0
- package/dist/core/state/version-bumper.js.map +1 -0
- package/dist/core/tasks/decision-manager.d.ts +25 -0
- package/dist/core/tasks/decision-manager.d.ts.map +1 -0
- package/dist/core/tasks/decision-manager.js +183 -0
- package/dist/core/tasks/decision-manager.js.map +1 -0
- package/dist/core/tasks/knowledge-manager.d.ts +24 -0
- package/dist/core/tasks/knowledge-manager.d.ts.map +1 -0
- package/dist/core/tasks/knowledge-manager.js +173 -0
- package/dist/core/tasks/knowledge-manager.js.map +1 -0
- package/dist/core/tasks/learn-manager.d.ts +27 -0
- package/dist/core/tasks/learn-manager.d.ts.map +1 -0
- package/dist/core/tasks/learn-manager.js +121 -0
- package/dist/core/tasks/learn-manager.js.map +1 -0
- package/dist/core/tasks/plans-manager.d.ts +46 -0
- package/dist/core/tasks/plans-manager.d.ts.map +1 -0
- package/dist/core/tasks/plans-manager.js +158 -0
- package/dist/core/tasks/plans-manager.js.map +1 -0
- package/dist/core/tasks/task-manager.d.ts +127 -0
- package/dist/core/tasks/task-manager.d.ts.map +1 -0
- package/dist/core/tasks/task-manager.js +607 -0
- package/dist/core/tasks/task-manager.js.map +1 -0
- package/dist/core/workspace/project-worker.d.ts +6 -6
- package/dist/core/workspace/project-worker.d.ts.map +1 -1
- package/dist/core/workspace/project-worker.js +6 -6
- package/dist/core/workspace/project-worker.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -176
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +16 -960
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/file-search.d.ts +43 -0
- package/dist/memory/file-search.d.ts.map +1 -0
- package/dist/memory/file-search.js +228 -0
- package/dist/memory/file-search.js.map +1 -0
- package/dist/memory/file-store.d.ts +99 -0
- package/dist/memory/file-store.d.ts.map +1 -0
- package/dist/memory/file-store.js +615 -0
- package/dist/memory/file-store.js.map +1 -0
- package/dist/memory/legacy-migrator.d.ts +27 -0
- package/dist/memory/legacy-migrator.d.ts.map +1 -0
- package/dist/memory/legacy-migrator.js +185 -0
- package/dist/memory/legacy-migrator.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +25 -24
- package/dist/memory/memory-manager.d.ts.map +1 -1
- package/dist/memory/memory-manager.js +97 -140
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/memory-types.d.ts +1 -1
- package/dist/memory/memory-types.d.ts.map +1 -1
- package/dist/types.d.ts +8 -119
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -6
- package/templates/agents/context-intelligence.md +50 -52
- package/templates/cli/OPENCODE.md +85 -18
- package/templates/commands/rulebook-learn-capture.md +41 -48
- package/templates/commands/rulebook-learn-list.md +13 -13
- package/templates/core/AGENTS_LEAN.md +0 -14
- package/templates/hooks/check-context-and-handoff.sh +8 -10
- package/templates/hooks/enforce-pre-tool.sh +70 -0
- package/templates/hooks/terse-mode-tracker.sh +146 -143
- package/templates/ides/OPENCODE.md +63 -0
- package/templates/skills/cli/opencode/SKILL.md +82 -28
- package/.claude/commands/ralph-config.md +0 -112
- package/.claude/commands/ralph-history.md +0 -110
- package/.claude/commands/ralph-init.md +0 -72
- package/.claude/commands/ralph-pause-resume.md +0 -105
- package/.claude/commands/ralph-run.md +0 -101
- package/.claude/commands/ralph-status.md +0 -76
- package/templates/core/RALPH.md +0 -471
- package/templates/frameworks/ANGULAR.md +0 -36
- package/templates/frameworks/DJANGO.md +0 -83
- package/templates/frameworks/ELECTRON.md +0 -147
- package/templates/frameworks/FLASK.md +0 -38
- package/templates/frameworks/FLUTTER.md +0 -55
- package/templates/frameworks/JQUERY.md +0 -32
- package/templates/frameworks/LARAVEL.md +0 -38
- package/templates/frameworks/NESTJS.md +0 -43
- package/templates/frameworks/NEXTJS.md +0 -127
- package/templates/frameworks/NUXT.md +0 -40
- package/templates/frameworks/RAILS.md +0 -66
- package/templates/frameworks/REACT.md +0 -38
- package/templates/frameworks/REACT_NATIVE.md +0 -47
- package/templates/frameworks/SPRING.md +0 -39
- package/templates/frameworks/SYMFONY.md +0 -36
- package/templates/frameworks/VUE.md +0 -36
- package/templates/frameworks/ZEND.md +0 -35
- package/templates/hooks/enforce-mcp-for-tasks.sh +0 -31
- package/templates/hooks/enforce-no-deferred.sh +0 -21
- package/templates/hooks/enforce-no-shortcuts.sh +0 -31
- package/templates/ides/COPILOT.md +0 -37
- package/templates/ides/CURSOR.md +0 -43
- package/templates/ides/JETBRAINS_AI.md +0 -35
- package/templates/ides/REPLIT.md +0 -36
- package/templates/ides/TABNINE.md +0 -29
- package/templates/ides/VSCODE.md +0 -40
- package/templates/ides/WINDSURF.md +0 -36
- package/templates/ides/ZED.md +0 -32
- package/templates/ides/cursor-mdc/go.mdc +0 -24
- package/templates/ides/cursor-mdc/python.mdc +0 -24
- package/templates/ides/cursor-mdc/quality.mdc +0 -25
- package/templates/ides/cursor-mdc/ralph.mdc +0 -39
- package/templates/ides/cursor-mdc/rulebook.mdc +0 -38
- package/templates/ides/cursor-mdc/rust.mdc +0 -24
- package/templates/ides/cursor-mdc/typescript.mdc +0 -25
- package/templates/ralph/ralph-history.bat +0 -4
- package/templates/ralph/ralph-history.sh +0 -5
- package/templates/ralph/ralph-init.bat +0 -5
- package/templates/ralph/ralph-init.sh +0 -5
- package/templates/ralph/ralph-pause.bat +0 -5
- package/templates/ralph/ralph-pause.sh +0 -5
- package/templates/ralph/ralph-run.bat +0 -5
- package/templates/ralph/ralph-run.sh +0 -5
- package/templates/ralph/ralph-status.bat +0 -4
- package/templates/ralph/ralph-status.sh +0 -5
- package/templates/services/AZURE_BLOB.md +0 -184
- package/templates/services/CASSANDRA.md +0 -239
- package/templates/services/DATADOG.md +0 -26
- package/templates/services/DOCKER.md +0 -124
- package/templates/services/DOCKER_COMPOSE.md +0 -168
- package/templates/services/DYNAMODB.md +0 -308
- package/templates/services/ELASTICSEARCH.md +0 -347
- package/templates/services/GCS.md +0 -178
- package/templates/services/HELM.md +0 -194
- package/templates/services/INFLUXDB.md +0 -265
- package/templates/services/KAFKA.md +0 -341
- package/templates/services/KUBERNETES.md +0 -208
- package/templates/services/MARIADB.md +0 -183
- package/templates/services/MEMCACHED.md +0 -242
- package/templates/services/MINIO.md +0 -201
- package/templates/services/MONGODB.md +0 -268
- package/templates/services/MYSQL.md +0 -358
- package/templates/services/NEO4J.md +0 -247
- package/templates/services/OPENTELEMETRY.md +0 -25
- package/templates/services/ORACLE.md +0 -290
- package/templates/services/PINO.md +0 -24
- package/templates/services/POSTGRESQL.md +0 -326
- package/templates/services/PROMETHEUS.md +0 -33
- package/templates/services/RABBITMQ.md +0 -286
- package/templates/services/REDIS.md +0 -292
- package/templates/services/S3.md +0 -298
- package/templates/services/SENTRY.md +0 -23
- package/templates/services/SQLITE.md +0 -294
- package/templates/services/SQLSERVER.md +0 -294
- package/templates/services/WINSTON.md +0 -30
- package/templates/skills/frameworks/angular/SKILL.md +0 -46
- package/templates/skills/frameworks/django/SKILL.md +0 -93
- package/templates/skills/frameworks/electron/SKILL.md +0 -157
- package/templates/skills/frameworks/flask/SKILL.md +0 -48
- package/templates/skills/frameworks/flutter/SKILL.md +0 -65
- package/templates/skills/frameworks/jquery/SKILL.md +0 -42
- package/templates/skills/frameworks/laravel/SKILL.md +0 -48
- package/templates/skills/frameworks/nestjs/SKILL.md +0 -53
- package/templates/skills/frameworks/nextjs/SKILL.md +0 -137
- package/templates/skills/frameworks/nuxt/SKILL.md +0 -50
- package/templates/skills/frameworks/rails/SKILL.md +0 -76
- package/templates/skills/frameworks/react/SKILL.md +0 -48
- package/templates/skills/frameworks/react-native/SKILL.md +0 -57
- package/templates/skills/frameworks/spring/SKILL.md +0 -49
- package/templates/skills/frameworks/symfony/SKILL.md +0 -46
- package/templates/skills/frameworks/vue/SKILL.md +0 -46
- package/templates/skills/frameworks/zend/SKILL.md +0 -45
- package/templates/skills/services/azure-blob/SKILL.md +0 -194
- package/templates/skills/services/cassandra/SKILL.md +0 -249
- package/templates/skills/services/dynamodb/SKILL.md +0 -318
- package/templates/skills/services/elasticsearch/SKILL.md +0 -357
- package/templates/skills/services/gcs/SKILL.md +0 -188
- package/templates/skills/services/influxdb/SKILL.md +0 -275
- package/templates/skills/services/kafka/SKILL.md +0 -351
- package/templates/skills/services/mariadb/SKILL.md +0 -193
- package/templates/skills/services/memcached/SKILL.md +0 -252
- package/templates/skills/services/minio/SKILL.md +0 -211
- package/templates/skills/services/mongodb/SKILL.md +0 -278
- package/templates/skills/services/mysql/SKILL.md +0 -368
- package/templates/skills/services/neo4j/SKILL.md +0 -257
- package/templates/skills/services/oracle/SKILL.md +0 -300
- package/templates/skills/services/postgresql/SKILL.md +0 -336
- package/templates/skills/services/rabbitmq/SKILL.md +0 -296
- package/templates/skills/services/redis/SKILL.md +0 -302
- package/templates/skills/services/s3/SKILL.md +0 -308
- package/templates/skills/services/sqlite/SKILL.md +0 -304
- package/templates/skills/services/sqlserver/SKILL.md +0 -304
- package/templates/skills/workflows/ralph/SETUP.md +0 -228
- package/templates/skills/workflows/ralph/SKILL.md +0 -309
- package/templates/skills/workflows/ralph/install.sh +0 -87
- package/templates/skills/workflows/ralph/manifest.json +0 -158
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Rust coding standards and best practices
|
|
3
|
-
globs: ["**/*.rs"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Rust Rules
|
|
8
|
-
|
|
9
|
-
See `/.rulebook/specs/RUST.md` for full requirements.
|
|
10
|
-
|
|
11
|
-
## Key Rules
|
|
12
|
-
|
|
13
|
-
- Prefer `Result<T, E>` over `unwrap()` / `expect()`
|
|
14
|
-
- Use `thiserror` for library errors, `anyhow` for application errors
|
|
15
|
-
- Minimize `clone()` — prefer borrows and lifetimes
|
|
16
|
-
- Use `clippy` with `#![deny(clippy::all)]`
|
|
17
|
-
- Document public API with `///` doc comments
|
|
18
|
-
- Prefer iterator adapters over manual loops
|
|
19
|
-
|
|
20
|
-
## Error Handling
|
|
21
|
-
|
|
22
|
-
- Propagate errors with `?` operator
|
|
23
|
-
- Define domain error enums with `thiserror`
|
|
24
|
-
- Never `panic!` in library code
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: TypeScript coding standards and best practices
|
|
3
|
-
globs: ["**/*.ts", "**/*.tsx"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# TypeScript Rules
|
|
8
|
-
|
|
9
|
-
See `/.rulebook/specs/TYPESCRIPT.md` for full requirements.
|
|
10
|
-
|
|
11
|
-
## Key Rules
|
|
12
|
-
|
|
13
|
-
- Strict mode enabled — all types must be explicit
|
|
14
|
-
- No `any` without justification comment
|
|
15
|
-
- Use `interface` for public API shapes, `type` for unions/aliases
|
|
16
|
-
- Prefer `async/await` over raw Promises
|
|
17
|
-
- Use `readonly` for immutable data
|
|
18
|
-
- `path.join()` for file paths (never string concatenation)
|
|
19
|
-
- Export only what is needed (avoid barrel re-exports)
|
|
20
|
-
|
|
21
|
-
## Error Handling
|
|
22
|
-
|
|
23
|
-
- Validate at system boundaries (user input, external APIs)
|
|
24
|
-
- Use typed error classes for domain errors
|
|
25
|
-
- Never swallow errors silently
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
<!-- AZURE_BLOB:START -->
|
|
2
|
-
# Azure Blob Storage Instructions
|
|
3
|
-
|
|
4
|
-
**CRITICAL**: Use Azure Blob Storage for object storage, file uploads, static assets, and backup storage in Azure cloud.
|
|
5
|
-
|
|
6
|
-
## Core Features
|
|
7
|
-
|
|
8
|
-
### Connection
|
|
9
|
-
```typescript
|
|
10
|
-
// Using @azure/storage-blob
|
|
11
|
-
import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob'
|
|
12
|
-
|
|
13
|
-
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME || ''
|
|
14
|
-
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY || ''
|
|
15
|
-
|
|
16
|
-
const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey)
|
|
17
|
-
const blobServiceClient = new BlobServiceClient(
|
|
18
|
-
`https://${accountName}.blob.core.windows.net`,
|
|
19
|
-
sharedKeyCredential
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
const containerClient = blobServiceClient.getContainerClient(
|
|
23
|
-
process.env.AZURE_CONTAINER_NAME || 'mycontainer'
|
|
24
|
-
)
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Basic Operations
|
|
28
|
-
```typescript
|
|
29
|
-
// Create container
|
|
30
|
-
await containerClient.createIfNotExists({
|
|
31
|
-
access: 'blob', // 'blob', 'container', or 'private'
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
// Upload blob
|
|
35
|
-
const blockBlobClient = containerClient.getBlockBlobClient('path/to/file.jpg')
|
|
36
|
-
await blockBlobClient.upload(fileBuffer, fileBuffer.length, {
|
|
37
|
-
blobHTTPHeaders: {
|
|
38
|
-
blobContentType: 'image/jpeg',
|
|
39
|
-
},
|
|
40
|
-
metadata: {
|
|
41
|
-
userId: '123',
|
|
42
|
-
originalName: 'photo.jpg',
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// Download blob
|
|
47
|
-
const downloadResponse = await blockBlobClient.download()
|
|
48
|
-
const fileContent = await streamToBuffer(downloadResponse.readableStreamBody)
|
|
49
|
-
|
|
50
|
-
// Delete blob
|
|
51
|
-
await blockBlobClient.delete()
|
|
52
|
-
|
|
53
|
-
// List blobs
|
|
54
|
-
for await (const blob of containerClient.listBlobsFlat()) {
|
|
55
|
-
console.log(blob.name, blob.properties.contentLength)
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Advanced Features
|
|
60
|
-
```typescript
|
|
61
|
-
// Generate SAS URL
|
|
62
|
-
import { generateBlobSASQueryParameters, BlobSASPermissions, StorageSharedKeyCredential } from '@azure/storage-blob'
|
|
63
|
-
|
|
64
|
-
const sasToken = generateBlobSASQueryParameters(
|
|
65
|
-
{
|
|
66
|
-
containerName: 'mycontainer',
|
|
67
|
-
blobName: 'path/to/file.jpg',
|
|
68
|
-
permissions: BlobSASPermissions.parse('r'), // read
|
|
69
|
-
startsOn: new Date(),
|
|
70
|
-
expiresOn: new Date(new Date().valueOf() + 3600 * 1000), // 1 hour
|
|
71
|
-
},
|
|
72
|
-
sharedKeyCredential
|
|
73
|
-
).toString()
|
|
74
|
-
|
|
75
|
-
const sasUrl = `https://${accountName}.blob.core.windows.net/mycontainer/path/to/file.jpg?${sasToken}`
|
|
76
|
-
|
|
77
|
-
// Copy blob
|
|
78
|
-
const sourceBlobClient = containerClient.getBlockBlobClient('source/file.jpg')
|
|
79
|
-
const destBlobClient = containerClient.getBlockBlobClient('dest/file.jpg')
|
|
80
|
-
await destBlobClient.beginCopyFromURL(sourceBlobClient.url)
|
|
81
|
-
|
|
82
|
-
// Set blob metadata
|
|
83
|
-
await blockBlobClient.setMetadata({
|
|
84
|
-
category: 'profile',
|
|
85
|
-
uploadedBy: 'user-123',
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// Get blob properties
|
|
89
|
-
const properties = await blockBlobClient.getProperties()
|
|
90
|
-
console.log(properties.contentType, properties.contentLength, properties.metadata)
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Common Patterns
|
|
94
|
-
|
|
95
|
-
### File Upload Handler
|
|
96
|
-
```typescript
|
|
97
|
-
async function uploadFile(file: Buffer, filename: string, userId: string) {
|
|
98
|
-
const blobName = `users/${userId}/${Date.now()}-${filename}`
|
|
99
|
-
const blobClient = containerClient.getBlockBlobClient(blobName)
|
|
100
|
-
|
|
101
|
-
await blobClient.upload(file, file.length, {
|
|
102
|
-
blobHTTPHeaders: {
|
|
103
|
-
blobContentType: getContentType(filename),
|
|
104
|
-
},
|
|
105
|
-
metadata: {
|
|
106
|
-
userId,
|
|
107
|
-
originalName: filename,
|
|
108
|
-
uploadedAt: new Date().toISOString(),
|
|
109
|
-
},
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
blobName,
|
|
114
|
-
url: blobClient.url,
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Temporary Access URL
|
|
120
|
-
```typescript
|
|
121
|
-
async function generateTemporaryUrl(blobName: string, expiresInMinutes: number = 60) {
|
|
122
|
-
const blobClient = containerClient.getBlockBlobClient(blobName)
|
|
123
|
-
const sasToken = generateBlobSASQueryParameters(
|
|
124
|
-
{
|
|
125
|
-
containerName: containerClient.containerName,
|
|
126
|
-
blobName,
|
|
127
|
-
permissions: BlobSASPermissions.parse('r'),
|
|
128
|
-
expiresOn: new Date(Date.now() + expiresInMinutes * 60 * 1000),
|
|
129
|
-
},
|
|
130
|
-
sharedKeyCredential
|
|
131
|
-
).toString()
|
|
132
|
-
|
|
133
|
-
return `${blobClient.url}?${sasToken}`
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## Best Practices
|
|
138
|
-
|
|
139
|
-
✅ **DO:**
|
|
140
|
-
- Use appropriate access tiers (Hot, Cool, Archive)
|
|
141
|
-
- Set blob metadata for organization
|
|
142
|
-
- Use SAS tokens for temporary access
|
|
143
|
-
- Implement proper error handling
|
|
144
|
-
- Use appropriate content types
|
|
145
|
-
- Enable soft delete for important data
|
|
146
|
-
- Monitor storage usage and costs
|
|
147
|
-
- Use lifecycle management policies
|
|
148
|
-
- Implement retry logic
|
|
149
|
-
- Use connection strings or managed identity
|
|
150
|
-
|
|
151
|
-
❌ **DON'T:**
|
|
152
|
-
- Store sensitive data without encryption
|
|
153
|
-
- Use public access unnecessarily
|
|
154
|
-
- Hardcode credentials
|
|
155
|
-
- Ignore error handling
|
|
156
|
-
- Skip content-type validation
|
|
157
|
-
- Ignore lifecycle policies
|
|
158
|
-
- Skip access logging
|
|
159
|
-
- Use default access levels
|
|
160
|
-
- Ignore cost optimization
|
|
161
|
-
- Store large files without chunking
|
|
162
|
-
|
|
163
|
-
## Configuration
|
|
164
|
-
|
|
165
|
-
### Environment Variables
|
|
166
|
-
```bash
|
|
167
|
-
AZURE_STORAGE_ACCOUNT_NAME=myaccount
|
|
168
|
-
AZURE_STORAGE_ACCOUNT_KEY=your-account-key
|
|
169
|
-
AZURE_CONTAINER_NAME=mycontainer
|
|
170
|
-
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Managed Identity (Recommended)
|
|
174
|
-
```typescript
|
|
175
|
-
import { DefaultAzureCredential } from '@azure/identity'
|
|
176
|
-
|
|
177
|
-
const blobServiceClient = new BlobServiceClient(
|
|
178
|
-
`https://${accountName}.blob.core.windows.net`,
|
|
179
|
-
new DefaultAzureCredential()
|
|
180
|
-
)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
<!-- AZURE_BLOB:END -->
|
|
184
|
-
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
<!-- CASSANDRA:START -->
|
|
2
|
-
# Apache Cassandra Database Instructions
|
|
3
|
-
|
|
4
|
-
**CRITICAL**: Use Cassandra for distributed NoSQL database with high availability, linear scalability, and eventual consistency.
|
|
5
|
-
|
|
6
|
-
## Core Features
|
|
7
|
-
|
|
8
|
-
### Connection
|
|
9
|
-
```typescript
|
|
10
|
-
// Using cassandra-driver
|
|
11
|
-
import { Client } from 'cassandra-driver'
|
|
12
|
-
|
|
13
|
-
const client = new Client({
|
|
14
|
-
contactPoints: (process.env.CASSANDRA_HOSTS || 'localhost').split(','),
|
|
15
|
-
localDataCenter: process.env.CASSANDRA_DATACENTER || 'datacenter1',
|
|
16
|
-
keyspace: process.env.CASSANDRA_KEYSPACE || 'myapp',
|
|
17
|
-
credentials: {
|
|
18
|
-
username: process.env.CASSANDRA_USER || 'cassandra',
|
|
19
|
-
password: process.env.CASSANDRA_PASSWORD || 'cassandra',
|
|
20
|
-
},
|
|
21
|
-
queryOptions: {
|
|
22
|
-
consistency: 1, // ONE, QUORUM, ALL
|
|
23
|
-
prepare: true,
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Basic Operations
|
|
29
|
-
```typescript
|
|
30
|
-
// Create keyspace
|
|
31
|
-
await client.execute(`
|
|
32
|
-
CREATE KEYSPACE IF NOT EXISTS myapp
|
|
33
|
-
WITH REPLICATION = {
|
|
34
|
-
'class': 'SimpleStrategy',
|
|
35
|
-
'replication_factor': 1
|
|
36
|
-
}
|
|
37
|
-
`)
|
|
38
|
-
|
|
39
|
-
// Use keyspace
|
|
40
|
-
await client.execute('USE myapp')
|
|
41
|
-
|
|
42
|
-
// Create table
|
|
43
|
-
await client.execute(`
|
|
44
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
45
|
-
id UUID PRIMARY KEY,
|
|
46
|
-
email TEXT,
|
|
47
|
-
name TEXT,
|
|
48
|
-
created_at TIMESTAMP
|
|
49
|
-
)
|
|
50
|
-
`)
|
|
51
|
-
|
|
52
|
-
// Create index
|
|
53
|
-
await client.execute('CREATE INDEX IF NOT EXISTS ON users (email)')
|
|
54
|
-
|
|
55
|
-
// Insert
|
|
56
|
-
await client.execute(
|
|
57
|
-
'INSERT INTO users (id, email, name, created_at) VALUES (?, ?, ?, ?)',
|
|
58
|
-
[cassandra.types.Uuid.random(), 'john@example.com', 'John Doe', new Date()],
|
|
59
|
-
{ prepare: true }
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
// Select
|
|
63
|
-
const result = await client.execute(
|
|
64
|
-
'SELECT * FROM users WHERE id = ?',
|
|
65
|
-
[userId],
|
|
66
|
-
{ prepare: true }
|
|
67
|
-
)
|
|
68
|
-
const user = result.first()
|
|
69
|
-
|
|
70
|
-
// Update
|
|
71
|
-
await client.execute(
|
|
72
|
-
'UPDATE users SET name = ? WHERE id = ?',
|
|
73
|
-
['Jane Doe', userId],
|
|
74
|
-
{ prepare: true }
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
// Delete
|
|
78
|
-
await client.execute(
|
|
79
|
-
'DELETE FROM users WHERE id = ?',
|
|
80
|
-
[userId],
|
|
81
|
-
{ prepare: true }
|
|
82
|
-
)
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Advanced Features
|
|
86
|
-
```typescript
|
|
87
|
-
// Batch operations
|
|
88
|
-
const queries = [
|
|
89
|
-
{
|
|
90
|
-
query: 'INSERT INTO users (id, email, name) VALUES (?, ?, ?)',
|
|
91
|
-
params: [id1, 'user1@example.com', 'User 1'],
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
query: 'INSERT INTO users (id, email, name) VALUES (?, ?, ?)',
|
|
95
|
-
params: [id2, 'user2@example.com', 'User 2'],
|
|
96
|
-
},
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
await client.batch(queries, { prepare: true })
|
|
100
|
-
|
|
101
|
-
// Collections
|
|
102
|
-
await client.execute(`
|
|
103
|
-
CREATE TABLE IF NOT EXISTS products (
|
|
104
|
-
id UUID PRIMARY KEY,
|
|
105
|
-
name TEXT,
|
|
106
|
-
tags SET<TEXT>,
|
|
107
|
-
metadata MAP<TEXT, TEXT>
|
|
108
|
-
)
|
|
109
|
-
`)
|
|
110
|
-
|
|
111
|
-
await client.execute(
|
|
112
|
-
'UPDATE products SET tags = tags + ? WHERE id = ?',
|
|
113
|
-
[['electronics', 'gadgets'], productId],
|
|
114
|
-
{ prepare: true }
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
// Time-to-Live (TTL)
|
|
118
|
-
await client.execute(
|
|
119
|
-
'INSERT INTO sessions (id, data) VALUES (?, ?) USING TTL 3600',
|
|
120
|
-
[sessionId, sessionData],
|
|
121
|
-
{ prepare: true }
|
|
122
|
-
)
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Common Patterns
|
|
126
|
-
|
|
127
|
-
### Data Modeling
|
|
128
|
-
```typescript
|
|
129
|
-
// Design tables for query patterns
|
|
130
|
-
// Query: Get users by email
|
|
131
|
-
await client.execute(`
|
|
132
|
-
CREATE TABLE users_by_email (
|
|
133
|
-
email TEXT PRIMARY KEY,
|
|
134
|
-
id UUID,
|
|
135
|
-
name TEXT,
|
|
136
|
-
created_at TIMESTAMP
|
|
137
|
-
)
|
|
138
|
-
`)
|
|
139
|
-
|
|
140
|
-
// Query: Get posts by user and date
|
|
141
|
-
await client.execute(`
|
|
142
|
-
CREATE TABLE posts_by_user (
|
|
143
|
-
user_id UUID,
|
|
144
|
-
created_at TIMESTAMP,
|
|
145
|
-
post_id UUID,
|
|
146
|
-
title TEXT,
|
|
147
|
-
content TEXT,
|
|
148
|
-
PRIMARY KEY (user_id, created_at, post_id)
|
|
149
|
-
) WITH CLUSTERING ORDER BY (created_at DESC)
|
|
150
|
-
`)
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Consistency Levels
|
|
154
|
-
```typescript
|
|
155
|
-
// Read with QUORUM consistency
|
|
156
|
-
const result = await client.execute(
|
|
157
|
-
'SELECT * FROM users WHERE id = ?',
|
|
158
|
-
[userId],
|
|
159
|
-
{
|
|
160
|
-
consistency: 2, // QUORUM
|
|
161
|
-
prepare: true,
|
|
162
|
-
}
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
// Write with ALL consistency (strongest)
|
|
166
|
-
await client.execute(
|
|
167
|
-
'INSERT INTO users (id, email, name) VALUES (?, ?, ?)',
|
|
168
|
-
[id, email, name],
|
|
169
|
-
{
|
|
170
|
-
consistency: 3, // ALL
|
|
171
|
-
prepare: true,
|
|
172
|
-
}
|
|
173
|
-
)
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Best Practices
|
|
177
|
-
|
|
178
|
-
✅ **DO:**
|
|
179
|
-
- Design tables for query patterns (denormalize)
|
|
180
|
-
- Use appropriate partition keys
|
|
181
|
-
- Use clustering keys for sorting
|
|
182
|
-
- Create secondary indexes sparingly
|
|
183
|
-
- Use prepared statements
|
|
184
|
-
- Set appropriate consistency levels
|
|
185
|
-
- Use TTL for time-based data
|
|
186
|
-
- Monitor cluster health
|
|
187
|
-
- Use batch operations carefully
|
|
188
|
-
- Implement retry logic
|
|
189
|
-
|
|
190
|
-
❌ **DON'T:**
|
|
191
|
-
- Use secondary indexes on high-cardinality columns
|
|
192
|
-
- Create too many secondary indexes
|
|
193
|
-
- Use ALL consistency for all operations
|
|
194
|
-
- Store large values (> 1MB)
|
|
195
|
-
- Skip error handling
|
|
196
|
-
- Ignore cluster topology
|
|
197
|
-
- Hardcode contact points
|
|
198
|
-
- Use SELECT * in production
|
|
199
|
-
- Ignore data modeling best practices
|
|
200
|
-
- Skip monitoring
|
|
201
|
-
|
|
202
|
-
## Configuration
|
|
203
|
-
|
|
204
|
-
### Environment Variables
|
|
205
|
-
```bash
|
|
206
|
-
CASSANDRA_HOSTS=localhost
|
|
207
|
-
CASSANDRA_HOSTS=node1:9042,node2:9042,node3:9042
|
|
208
|
-
CASSANDRA_DATACENTER=datacenter1
|
|
209
|
-
CASSANDRA_KEYSPACE=myapp
|
|
210
|
-
CASSANDRA_USER=cassandra
|
|
211
|
-
CASSANDRA_PASSWORD=securepassword
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Docker Compose
|
|
215
|
-
```yaml
|
|
216
|
-
services:
|
|
217
|
-
cassandra:
|
|
218
|
-
image: cassandra:4
|
|
219
|
-
ports:
|
|
220
|
-
- "9042:9042"
|
|
221
|
-
environment:
|
|
222
|
-
CASSANDRA_CLUSTER_NAME: my-cluster
|
|
223
|
-
CASSANDRA_DC: datacenter1
|
|
224
|
-
CASSANDRA_RACK: rack1
|
|
225
|
-
CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch
|
|
226
|
-
volumes:
|
|
227
|
-
- cassandra_data:/var/lib/cassandra
|
|
228
|
-
healthcheck:
|
|
229
|
-
test: ["CMD-SHELL", "nodetool status | grep -E '^UN' || exit 1"]
|
|
230
|
-
interval: 30s
|
|
231
|
-
timeout: 10s
|
|
232
|
-
retries: 5
|
|
233
|
-
|
|
234
|
-
volumes:
|
|
235
|
-
cassandra_data:
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
<!-- CASSANDRA:END -->
|
|
239
|
-
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<!-- DATADOG:START -->
|
|
2
|
-
# Datadog — APM and Monitoring
|
|
3
|
-
|
|
4
|
-
## Initialization
|
|
5
|
-
- Import `dd-trace` as the FIRST import in application entry point
|
|
6
|
-
- Configure via environment variables: `DD_AGENT_HOST`, `DD_TRACE_AGENT_PORT`, `DD_ENV`, `DD_SERVICE`, `DD_VERSION`
|
|
7
|
-
|
|
8
|
-
## Tracing
|
|
9
|
-
- Use automatic instrumentation for Express, pg, Redis, etc.
|
|
10
|
-
- Add manual traces for business-critical operations:
|
|
11
|
-
```typescript
|
|
12
|
-
const tracer = require('dd-trace');
|
|
13
|
-
const span = tracer.startSpan('operation.name');
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Logs
|
|
17
|
-
- Inject trace IDs into log records for correlation:
|
|
18
|
-
```typescript
|
|
19
|
-
const span = tracer.scope().active();
|
|
20
|
-
if (span) log.info({ dd: { trace_id: span.context().toTraceId(), span_id: span.context().toSpanId() }, message });
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Custom Metrics
|
|
24
|
-
- Use `dogstatsd-client` for custom metrics: counters, gauges, histograms
|
|
25
|
-
- Tag metrics with `env`, `service`, `version` for consistent filtering
|
|
26
|
-
<!-- DATADOG:END -->
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
<!-- DOCKER:START -->
|
|
2
|
-
# Docker Instructions
|
|
3
|
-
|
|
4
|
-
**CRITICAL**: Follow these Docker best practices for all container builds.
|
|
5
|
-
|
|
6
|
-
## Build Patterns
|
|
7
|
-
|
|
8
|
-
### Multi-Stage Builds
|
|
9
|
-
Use multi-stage builds to minimize final image size and separate build-time dependencies from runtime:
|
|
10
|
-
|
|
11
|
-
```dockerfile
|
|
12
|
-
FROM node:20-alpine AS builder
|
|
13
|
-
WORKDIR /app
|
|
14
|
-
COPY package*.json ./
|
|
15
|
-
RUN npm ci
|
|
16
|
-
COPY . .
|
|
17
|
-
RUN npm run build
|
|
18
|
-
|
|
19
|
-
FROM node:20-alpine AS runtime
|
|
20
|
-
RUN adduser -D appuser
|
|
21
|
-
USER appuser
|
|
22
|
-
WORKDIR /app
|
|
23
|
-
COPY --from=builder /app/dist ./dist
|
|
24
|
-
COPY --from=builder /app/node_modules ./node_modules
|
|
25
|
-
COPY --from=builder /app/package.json ./
|
|
26
|
-
HEALTHCHECK --interval=30s --timeout=3s CMD node -e "require('http').get('http://localhost:3000/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"
|
|
27
|
-
CMD ["node", "dist/index.js"]
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Base Image Selection
|
|
31
|
-
- Pin base image versions: `node:20-alpine` not `node:latest`
|
|
32
|
-
- Prefer `-alpine` or `-slim` variants for smaller images
|
|
33
|
-
- Use official images from Docker Hub verified publishers
|
|
34
|
-
|
|
35
|
-
## Security Requirements
|
|
36
|
-
|
|
37
|
-
### Non-Root User
|
|
38
|
-
ALL containers MUST run as a non-root user:
|
|
39
|
-
```dockerfile
|
|
40
|
-
RUN adduser -D appuser
|
|
41
|
-
USER appuser
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Secrets
|
|
45
|
-
- NEVER copy secrets (`.env`, credentials, keys) into image layers
|
|
46
|
-
- Use Docker secrets or runtime environment variables instead
|
|
47
|
-
- Scan images with `docker scout cves` or `trivy image` before pushing
|
|
48
|
-
- Add `--no-cache` to package install commands to reduce attack surface
|
|
49
|
-
|
|
50
|
-
### Image Scanning
|
|
51
|
-
```bash
|
|
52
|
-
# Docker Scout (built-in)
|
|
53
|
-
docker scout cves <image>
|
|
54
|
-
|
|
55
|
-
# Trivy
|
|
56
|
-
trivy image <image>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Required Instructions
|
|
60
|
-
|
|
61
|
-
### HEALTHCHECK
|
|
62
|
-
ALL production images MUST include a HEALTHCHECK:
|
|
63
|
-
```dockerfile
|
|
64
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
|
|
65
|
-
CMD curl -f http://localhost:3000/health || exit 1
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### .dockerignore Requirements
|
|
69
|
-
Every Docker project MUST have a `.dockerignore` file containing at minimum:
|
|
70
|
-
```
|
|
71
|
-
.git
|
|
72
|
-
node_modules
|
|
73
|
-
dist
|
|
74
|
-
coverage
|
|
75
|
-
*.log
|
|
76
|
-
.env*
|
|
77
|
-
.DS_Store
|
|
78
|
-
*.md
|
|
79
|
-
.vscode
|
|
80
|
-
.idea
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Common Patterns
|
|
84
|
-
|
|
85
|
-
### Layer Caching
|
|
86
|
-
Order Dockerfile instructions from least-changing to most-changing:
|
|
87
|
-
```dockerfile
|
|
88
|
-
# 1. Base image (rarely changes)
|
|
89
|
-
FROM node:20-alpine
|
|
90
|
-
|
|
91
|
-
# 2. System dependencies (changes rarely)
|
|
92
|
-
RUN apk add --no-cache curl
|
|
93
|
-
|
|
94
|
-
# 3. Package files (changes when deps change)
|
|
95
|
-
COPY package*.json ./
|
|
96
|
-
RUN npm ci --only=production
|
|
97
|
-
|
|
98
|
-
# 4. Application code (changes frequently)
|
|
99
|
-
COPY . .
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Production Optimization
|
|
103
|
-
```dockerfile
|
|
104
|
-
# Use npm ci for deterministic installs
|
|
105
|
-
RUN npm ci --only=production
|
|
106
|
-
|
|
107
|
-
# Remove unnecessary files
|
|
108
|
-
RUN rm -rf /tmp/* /var/cache/apk/*
|
|
109
|
-
|
|
110
|
-
# Set NODE_ENV
|
|
111
|
-
ENV NODE_ENV=production
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Best Practices
|
|
115
|
-
|
|
116
|
-
- Use `.dockerignore` to exclude unnecessary files from build context
|
|
117
|
-
- One process per container (do not run multiple services in one container)
|
|
118
|
-
- Use `COPY` over `ADD` unless extracting archives
|
|
119
|
-
- Combine RUN commands to reduce layers: `RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*`
|
|
120
|
-
- Set explicit `WORKDIR` instead of `RUN cd`
|
|
121
|
-
- Use `EXPOSE` to document listening ports
|
|
122
|
-
- Tag images with semantic versions, not just `latest`
|
|
123
|
-
|
|
124
|
-
<!-- DOCKER:END -->
|