@hivehub/rulebook 1.2.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/LICENSE +191 -0
- package/README.md +539 -0
- package/dist/agents/claude-code.d.ts +69 -0
- package/dist/agents/claude-code.d.ts.map +1 -0
- package/dist/agents/claude-code.js +180 -0
- package/dist/agents/claude-code.js.map +1 -0
- package/dist/agents/cursor-agent.d.ts +184 -0
- package/dist/agents/cursor-agent.d.ts.map +1 -0
- package/dist/agents/cursor-agent.js +299 -0
- package/dist/agents/cursor-agent.js.map +1 -0
- package/dist/agents/gemini-cli.d.ts +69 -0
- package/dist/agents/gemini-cli.d.ts.map +1 -0
- package/dist/agents/gemini-cli.js +180 -0
- package/dist/agents/gemini-cli.js.map +1 -0
- package/dist/cli/commands.d.ts +57 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +1370 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/docs-prompts.d.ts +3 -0
- package/dist/cli/docs-prompts.d.ts.map +1 -0
- package/dist/cli/docs-prompts.js +45 -0
- package/dist/cli/docs-prompts.js.map +1 -0
- package/dist/cli/prompts.d.ts +6 -0
- package/dist/cli/prompts.d.ts.map +1 -0
- package/dist/cli/prompts.js +376 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/core/agent-manager.d.ts +89 -0
- package/dist/core/agent-manager.d.ts.map +1 -0
- package/dist/core/agent-manager.js +546 -0
- package/dist/core/agent-manager.js.map +1 -0
- package/dist/core/auto-fixer.d.ts +14 -0
- package/dist/core/auto-fixer.d.ts.map +1 -0
- package/dist/core/auto-fixer.js +207 -0
- package/dist/core/auto-fixer.js.map +1 -0
- package/dist/core/changelog-generator.d.ts +44 -0
- package/dist/core/changelog-generator.d.ts.map +1 -0
- package/dist/core/changelog-generator.js +222 -0
- package/dist/core/changelog-generator.js.map +1 -0
- package/dist/core/cli-bridge.d.ts +113 -0
- package/dist/core/cli-bridge.d.ts.map +1 -0
- package/dist/core/cli-bridge.js +1094 -0
- package/dist/core/cli-bridge.js.map +1 -0
- package/dist/core/config-manager.d.ts +65 -0
- package/dist/core/config-manager.d.ts.map +1 -0
- package/dist/core/config-manager.js +266 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/coverage-checker.d.ts +14 -0
- package/dist/core/coverage-checker.d.ts.map +1 -0
- package/dist/core/coverage-checker.js +176 -0
- package/dist/core/coverage-checker.js.map +1 -0
- package/dist/core/custom-templates.d.ts +27 -0
- package/dist/core/custom-templates.d.ts.map +1 -0
- package/dist/core/custom-templates.js +122 -0
- package/dist/core/custom-templates.js.map +1 -0
- package/dist/core/dependency-checker.d.ts +21 -0
- package/dist/core/dependency-checker.d.ts.map +1 -0
- package/dist/core/dependency-checker.js +247 -0
- package/dist/core/dependency-checker.js.map +1 -0
- package/dist/core/detector.d.ts +3 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/detector.js +1443 -0
- package/dist/core/detector.js.map +1 -0
- package/dist/core/docs-generator.d.ts +9 -0
- package/dist/core/docs-generator.d.ts.map +1 -0
- package/dist/core/docs-generator.js +531 -0
- package/dist/core/docs-generator.js.map +1 -0
- package/dist/core/generator.d.ts +16 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/dist/core/generator.js +561 -0
- package/dist/core/generator.js.map +1 -0
- package/dist/core/gitignore-generator.d.ts +13 -0
- package/dist/core/gitignore-generator.d.ts.map +1 -0
- package/dist/core/gitignore-generator.js +307 -0
- package/dist/core/gitignore-generator.js.map +1 -0
- package/dist/core/health-scorer.d.ts +22 -0
- package/dist/core/health-scorer.d.ts.map +1 -0
- package/dist/core/health-scorer.js +395 -0
- package/dist/core/health-scorer.js.map +1 -0
- package/dist/core/logger.d.ts +116 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +289 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/merger.d.ts +6 -0
- package/dist/core/merger.d.ts.map +1 -0
- package/dist/core/merger.js +131 -0
- package/dist/core/merger.js.map +1 -0
- package/dist/core/migrator.d.ts +19 -0
- package/dist/core/migrator.d.ts.map +1 -0
- package/dist/core/migrator.js +102 -0
- package/dist/core/migrator.js.map +1 -0
- package/dist/core/minimal-scaffolder.d.ts +8 -0
- package/dist/core/minimal-scaffolder.d.ts.map +1 -0
- package/dist/core/minimal-scaffolder.js +51 -0
- package/dist/core/minimal-scaffolder.js.map +1 -0
- package/dist/core/modern-console-new.d.ts +81 -0
- package/dist/core/modern-console-new.d.ts.map +1 -0
- package/dist/core/modern-console-new.js +340 -0
- package/dist/core/modern-console-new.js.map +1 -0
- package/dist/core/modern-console.d.ts +99 -0
- package/dist/core/modern-console.d.ts.map +1 -0
- package/dist/core/modern-console.js +568 -0
- package/dist/core/modern-console.js.map +1 -0
- package/dist/core/openspec-manager.d.ts +133 -0
- package/dist/core/openspec-manager.d.ts.map +1 -0
- package/dist/core/openspec-manager.js +605 -0
- package/dist/core/openspec-manager.js.map +1 -0
- package/dist/core/openspec-migrator.d.ts +27 -0
- package/dist/core/openspec-migrator.d.ts.map +1 -0
- package/dist/core/openspec-migrator.js +255 -0
- package/dist/core/openspec-migrator.js.map +1 -0
- package/dist/core/task-manager.d.ts +65 -0
- package/dist/core/task-manager.d.ts.map +1 -0
- package/dist/core/task-manager.js +318 -0
- package/dist/core/task-manager.js.map +1 -0
- package/dist/core/test-task-manager.d.ts +49 -0
- package/dist/core/test-task-manager.d.ts.map +1 -0
- package/dist/core/test-task-manager.js +121 -0
- package/dist/core/test-task-manager.js.map +1 -0
- package/dist/core/validator.d.ts +21 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +177 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/core/version-bumper.d.ts +19 -0
- package/dist/core/version-bumper.d.ts.map +1 -0
- package/dist/core/version-bumper.js +180 -0
- package/dist/core/version-bumper.js.map +1 -0
- package/dist/core/watcher.d.ts +9 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +22 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/core/workflow-generator.d.ts +10 -0
- package/dist/core/workflow-generator.d.ts.map +1 -0
- package/dist/core/workflow-generator.js +279 -0
- package/dist/core/workflow-generator.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +159 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers/archive-task.d.ts +17 -0
- package/dist/mcp/handlers/archive-task.d.ts.map +1 -0
- package/dist/mcp/handlers/archive-task.js +36 -0
- package/dist/mcp/handlers/archive-task.js.map +1 -0
- package/dist/mcp/handlers/create-task.d.ts +17 -0
- package/dist/mcp/handlers/create-task.d.ts.map +1 -0
- package/dist/mcp/handlers/create-task.js +56 -0
- package/dist/mcp/handlers/create-task.js.map +1 -0
- package/dist/mcp/handlers/list-tasks.d.ts +22 -0
- package/dist/mcp/handlers/list-tasks.d.ts.map +1 -0
- package/dist/mcp/handlers/list-tasks.js +42 -0
- package/dist/mcp/handlers/list-tasks.js.map +1 -0
- package/dist/mcp/handlers/show-task.d.ts +25 -0
- package/dist/mcp/handlers/show-task.d.ts.map +1 -0
- package/dist/mcp/handlers/show-task.js +43 -0
- package/dist/mcp/handlers/show-task.js.map +1 -0
- package/dist/mcp/handlers/update-task.d.ts +17 -0
- package/dist/mcp/handlers/update-task.d.ts.map +1 -0
- package/dist/mcp/handlers/update-task.js +35 -0
- package/dist/mcp/handlers/update-task.js.map +1 -0
- package/dist/mcp/handlers/validate-task.d.ts +15 -0
- package/dist/mcp/handlers/validate-task.d.ts.map +1 -0
- package/dist/mcp/handlers/validate-task.js +27 -0
- package/dist/mcp/handlers/validate-task.js.map +1 -0
- package/dist/mcp/rulebook-config.d.ts +22 -0
- package/dist/mcp/rulebook-config.d.ts.map +1 -0
- package/dist/mcp/rulebook-config.js +65 -0
- package/dist/mcp/rulebook-config.js.map +1 -0
- package/dist/mcp/rulebook-server.d.ts +4 -0
- package/dist/mcp/rulebook-server.d.ts.map +1 -0
- package/dist/mcp/rulebook-server.js +246 -0
- package/dist/mcp/rulebook-server.js.map +1 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/file-system.d.ts +9 -0
- package/dist/utils/file-system.d.ts.map +1 -0
- package/dist/utils/file-system.js +51 -0
- package/dist/utils/file-system.js.map +1 -0
- package/dist/utils/git-hooks.d.ts +8 -0
- package/dist/utils/git-hooks.d.ts.map +1 -0
- package/dist/utils/git-hooks.js +440 -0
- package/dist/utils/git-hooks.js.map +1 -0
- package/dist/utils/rulesignore.d.ts +9 -0
- package/dist/utils/rulesignore.d.ts.map +1 -0
- package/dist/utils/rulesignore.js +42 -0
- package/dist/utils/rulesignore.js.map +1 -0
- package/package.json +106 -0
- package/templates/cli/AIDER.md +49 -0
- package/templates/cli/AMAZON_Q.md +25 -0
- package/templates/cli/AUGGIE.md +32 -0
- package/templates/cli/CLAUDE.md +32 -0
- package/templates/cli/CLAUDE_CODE.md +35 -0
- package/templates/cli/CLINE.md +32 -0
- package/templates/cli/CODEBUDDY.md +20 -0
- package/templates/cli/CODEIUM.md +20 -0
- package/templates/cli/CODEX.md +21 -0
- package/templates/cli/CONTINUE.md +34 -0
- package/templates/cli/CURSOR_CLI.md +28 -0
- package/templates/cli/FACTORY.md +18 -0
- package/templates/cli/GEMINI.md +35 -0
- package/templates/cli/KILOCODE.md +18 -0
- package/templates/cli/OPENCODE.md +18 -0
- package/templates/cli/_GENERIC_TEMPLATE.md +29 -0
- package/templates/commands/rulebook-task-apply.md +67 -0
- package/templates/commands/rulebook-task-archive.md +70 -0
- package/templates/commands/rulebook-task-create.md +93 -0
- package/templates/commands/rulebook-task-list.md +42 -0
- package/templates/commands/rulebook-task-show.md +52 -0
- package/templates/commands/rulebook-task-validate.md +53 -0
- package/templates/core/AGENT_AUTOMATION.md +184 -0
- package/templates/core/DAG.md +304 -0
- package/templates/core/DOCUMENTATION_RULES.md +37 -0
- package/templates/core/QUALITY_ENFORCEMENT.md +68 -0
- package/templates/core/RULEBOOK.md +1874 -0
- package/templates/frameworks/ANGULAR.md +36 -0
- package/templates/frameworks/DJANGO.md +83 -0
- package/templates/frameworks/ELECTRON.md +147 -0
- package/templates/frameworks/FLASK.md +38 -0
- package/templates/frameworks/FLUTTER.md +55 -0
- package/templates/frameworks/JQUERY.md +32 -0
- package/templates/frameworks/LARAVEL.md +38 -0
- package/templates/frameworks/NESTJS.md +43 -0
- package/templates/frameworks/NEXTJS.md +127 -0
- package/templates/frameworks/NUXT.md +40 -0
- package/templates/frameworks/RAILS.md +66 -0
- package/templates/frameworks/REACT.md +38 -0
- package/templates/frameworks/REACT_NATIVE.md +47 -0
- package/templates/frameworks/SPRING.md +39 -0
- package/templates/frameworks/SYMFONY.md +36 -0
- package/templates/frameworks/VUE.md +36 -0
- package/templates/frameworks/ZEND.md +35 -0
- package/templates/git/CI_CD_PATTERNS.md +661 -0
- package/templates/git/GITHUB_ACTIONS.md +728 -0
- package/templates/git/GITLAB_CI.md +730 -0
- package/templates/git/GIT_WORKFLOW.md +1157 -0
- package/templates/git/SECRETS_MANAGEMENT.md +585 -0
- package/templates/hooks/COMMIT_MSG.md +530 -0
- package/templates/hooks/POST_CHECKOUT.md +546 -0
- package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -0
- package/templates/hooks/PRE_COMMIT.md +414 -0
- package/templates/hooks/PRE_PUSH.md +601 -0
- package/templates/hooks/csharp-pre-commit.sh +23 -0
- package/templates/hooks/csharp-pre-push.sh +23 -0
- package/templates/hooks/dart-pre-commit.sh +30 -0
- package/templates/hooks/dart-pre-push.sh +25 -0
- package/templates/hooks/elixir-pre-commit.sh +32 -0
- package/templates/hooks/elixir-pre-push.sh +31 -0
- package/templates/hooks/erlang-pre-commit.sh +30 -0
- package/templates/hooks/erlang-pre-push.sh +37 -0
- package/templates/hooks/go-pre-commit.sh +40 -0
- package/templates/hooks/go-pre-push.sh +31 -0
- package/templates/hooks/haskell-pre-commit.sh +41 -0
- package/templates/hooks/haskell-pre-push.sh +37 -0
- package/templates/hooks/java-pre-commit.sh +34 -0
- package/templates/hooks/java-pre-push.sh +24 -0
- package/templates/hooks/kotlin-pre-commit.sh +32 -0
- package/templates/hooks/kotlin-pre-push.sh +16 -0
- package/templates/hooks/php-pre-commit.sh +36 -0
- package/templates/hooks/php-pre-push.sh +26 -0
- package/templates/hooks/python-pre-commit.sh +51 -0
- package/templates/hooks/python-pre-push.sh +25 -0
- package/templates/hooks/ruby-pre-commit.sh +33 -0
- package/templates/hooks/ruby-pre-push.sh +32 -0
- package/templates/hooks/rust-pre-commit.sh +30 -0
- package/templates/hooks/rust-pre-push.sh +30 -0
- package/templates/hooks/scala-pre-commit.sh +32 -0
- package/templates/hooks/scala-pre-push.sh +24 -0
- package/templates/hooks/swift-pre-commit.sh +25 -0
- package/templates/hooks/swift-pre-push.sh +23 -0
- package/templates/hooks/typescript-pre-commit.sh +37 -0
- package/templates/hooks/typescript-pre-push.sh +36 -0
- package/templates/ides/COPILOT.md +37 -0
- package/templates/ides/CURSOR.md +43 -0
- package/templates/ides/JETBRAINS_AI.md +35 -0
- package/templates/ides/REPLIT.md +36 -0
- package/templates/ides/TABNINE.md +29 -0
- package/templates/ides/VSCODE.md +40 -0
- package/templates/ides/WINDSURF.md +36 -0
- package/templates/ides/ZED.md +32 -0
- package/templates/languages/ADA.md +58 -0
- package/templates/languages/C.md +333 -0
- package/templates/languages/CPP.md +743 -0
- package/templates/languages/CSHARP.md +417 -0
- package/templates/languages/DART.md +332 -0
- package/templates/languages/ELIXIR.md +454 -0
- package/templates/languages/ERLANG.md +361 -0
- package/templates/languages/GO.md +645 -0
- package/templates/languages/HASKELL.md +177 -0
- package/templates/languages/JAVA.md +607 -0
- package/templates/languages/JAVASCRIPT.md +631 -0
- package/templates/languages/JULIA.md +97 -0
- package/templates/languages/KOTLIN.md +511 -0
- package/templates/languages/LISP.md +100 -0
- package/templates/languages/LUA.md +74 -0
- package/templates/languages/OBJECTIVEC.md +90 -0
- package/templates/languages/PHP.md +416 -0
- package/templates/languages/PYTHON.md +682 -0
- package/templates/languages/R.md +350 -0
- package/templates/languages/RUBY.md +421 -0
- package/templates/languages/RUST.md +477 -0
- package/templates/languages/SAS.md +73 -0
- package/templates/languages/SCALA.md +348 -0
- package/templates/languages/SOLIDITY.md +580 -0
- package/templates/languages/SQL.md +137 -0
- package/templates/languages/SWIFT.md +466 -0
- package/templates/languages/TYPESCRIPT.md +591 -0
- package/templates/languages/ZIG.md +265 -0
- package/templates/modules/ATLASSIAN.md +255 -0
- package/templates/modules/CONTEXT7.md +54 -0
- package/templates/modules/FIGMA.md +267 -0
- package/templates/modules/GITHUB_MCP.md +64 -0
- package/templates/modules/GRAFANA.md +328 -0
- package/templates/modules/NOTION.md +247 -0
- package/templates/modules/PLAYWRIGHT.md +90 -0
- package/templates/modules/RULEBOOK_MCP.md +156 -0
- package/templates/modules/SERENA.md +337 -0
- package/templates/modules/SUPABASE.md +223 -0
- package/templates/modules/SYNAP.md +69 -0
- package/templates/modules/VECTORIZER.md +63 -0
- package/templates/services/AZURE_BLOB.md +184 -0
- package/templates/services/CASSANDRA.md +239 -0
- package/templates/services/DYNAMODB.md +308 -0
- package/templates/services/ELASTICSEARCH.md +347 -0
- package/templates/services/GCS.md +178 -0
- package/templates/services/INFLUXDB.md +265 -0
- package/templates/services/KAFKA.md +341 -0
- package/templates/services/MARIADB.md +183 -0
- package/templates/services/MEMCACHED.md +242 -0
- package/templates/services/MINIO.md +201 -0
- package/templates/services/MONGODB.md +268 -0
- package/templates/services/MYSQL.md +358 -0
- package/templates/services/NEO4J.md +247 -0
- package/templates/services/ORACLE.md +290 -0
- package/templates/services/POSTGRESQL.md +326 -0
- package/templates/services/RABBITMQ.md +286 -0
- package/templates/services/REDIS.md +292 -0
- package/templates/services/S3.md +298 -0
- package/templates/services/SQLITE.md +294 -0
- package/templates/services/SQLSERVER.md +294 -0
- package/templates/workflows/codespell.yml +31 -0
- package/templates/workflows/cpp-lint.yml +47 -0
- package/templates/workflows/cpp-publish.yml +119 -0
- package/templates/workflows/cpp-test.yml +77 -0
- package/templates/workflows/dotnet-lint.yml +29 -0
- package/templates/workflows/dotnet-publish.yml +40 -0
- package/templates/workflows/dotnet-test.yml +41 -0
- package/templates/workflows/elixir-lint.yml +45 -0
- package/templates/workflows/elixir-publish.yml +49 -0
- package/templates/workflows/elixir-test.yml +54 -0
- package/templates/workflows/erlang-lint.yml +47 -0
- package/templates/workflows/erlang-test.yml +62 -0
- package/templates/workflows/go-lint.yml +39 -0
- package/templates/workflows/go-publish.yml +95 -0
- package/templates/workflows/go-test.yml +59 -0
- package/templates/workflows/java-lint.yml +60 -0
- package/templates/workflows/java-publish.yml +120 -0
- package/templates/workflows/java-test.yml +85 -0
- package/templates/workflows/kotlin-lint.yml +34 -0
- package/templates/workflows/kotlin-publish.yml +56 -0
- package/templates/workflows/kotlin-test.yml +48 -0
- package/templates/workflows/php-lint.yml +39 -0
- package/templates/workflows/php-publish.yml +50 -0
- package/templates/workflows/php-test.yml +54 -0
- package/templates/workflows/python-lint.yml +47 -0
- package/templates/workflows/python-publish.yml +91 -0
- package/templates/workflows/python-test.yml +59 -0
- package/templates/workflows/rust-lint.yml +54 -0
- package/templates/workflows/rust-publish.yml +66 -0
- package/templates/workflows/rust-test.yml +75 -0
- package/templates/workflows/solidity-lint.yml +41 -0
- package/templates/workflows/solidity-test.yml +47 -0
- package/templates/workflows/swift-lint.yml +32 -0
- package/templates/workflows/swift-publish.yml +58 -0
- package/templates/workflows/swift-test.yml +44 -0
- package/templates/workflows/typescript-lint.yml +61 -0
- package/templates/workflows/typescript-publish.yml +60 -0
- package/templates/workflows/typescript-test.yml +73 -0
- package/templates/workflows/zig-lint.yml +27 -0
- package/templates/workflows/zig-test.yml +40 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
<!-- SQLITE:START -->
|
|
2
|
+
# SQLite Database Instructions
|
|
3
|
+
|
|
4
|
+
**CRITICAL**: Use SQLite for embedded databases, local storage, development, and small-scale applications with zero configuration.
|
|
5
|
+
|
|
6
|
+
## Core Features
|
|
7
|
+
|
|
8
|
+
### Connection
|
|
9
|
+
```typescript
|
|
10
|
+
// Using better-sqlite3 (synchronous, faster)
|
|
11
|
+
import Database from 'better-sqlite3'
|
|
12
|
+
|
|
13
|
+
const db = new Database(process.env.DB_PATH || './database.db', {
|
|
14
|
+
verbose: process.env.NODE_ENV === 'development' ? console.log : undefined,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Using sqlite3 (asynchronous)
|
|
18
|
+
import sqlite3 from 'sqlite3'
|
|
19
|
+
|
|
20
|
+
const db = new sqlite3.Database(process.env.DB_PATH || './database.db', (err) => {
|
|
21
|
+
if (err) {
|
|
22
|
+
console.error('Error opening database', err)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// Using better-sqlite3 with WAL mode (recommended)
|
|
27
|
+
const db = new Database('./database.db')
|
|
28
|
+
db.pragma('journal_mode = WAL') // Write-Ahead Logging
|
|
29
|
+
db.pragma('foreign_keys = ON') // Enable foreign keys
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Basic Queries
|
|
33
|
+
```typescript
|
|
34
|
+
// Using better-sqlite3 (synchronous)
|
|
35
|
+
// SELECT
|
|
36
|
+
const stmt = db.prepare('SELECT * FROM users WHERE id = ?')
|
|
37
|
+
const user = stmt.get(userId)
|
|
38
|
+
|
|
39
|
+
// INSERT
|
|
40
|
+
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
|
|
41
|
+
const info = insert.run('John Doe', 'john@example.com')
|
|
42
|
+
const newId = info.lastInsertRowid
|
|
43
|
+
|
|
44
|
+
// UPDATE
|
|
45
|
+
const update = db.prepare('UPDATE users SET name = ? WHERE id = ?')
|
|
46
|
+
update.run('Jane Doe', userId)
|
|
47
|
+
|
|
48
|
+
// DELETE
|
|
49
|
+
const del = db.prepare('DELETE FROM users WHERE id = ?')
|
|
50
|
+
del.run(userId)
|
|
51
|
+
|
|
52
|
+
// Using sqlite3 (asynchronous)
|
|
53
|
+
db.get('SELECT * FROM users WHERE id = ?', [userId], (err, row) => {
|
|
54
|
+
if (err) throw err
|
|
55
|
+
console.log(row)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['John Doe', 'john@example.com'], function(err) {
|
|
59
|
+
if (err) throw err
|
|
60
|
+
console.log('Inserted with ID:', this.lastID)
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Transactions
|
|
65
|
+
```typescript
|
|
66
|
+
// Using better-sqlite3
|
|
67
|
+
const insertUser = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
|
|
68
|
+
const insertPost = db.prepare('INSERT INTO posts (user_id, title) VALUES (?, ?)')
|
|
69
|
+
|
|
70
|
+
const insertUserAndPost = db.transaction((userName, userEmail, postTitle) => {
|
|
71
|
+
const userInfo = insertUser.run(userName, userEmail)
|
|
72
|
+
const userId = userInfo.lastInsertRowid
|
|
73
|
+
insertPost.run(userId, postTitle)
|
|
74
|
+
return userId
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const userId = insertUserAndPost('John Doe', 'john@example.com', 'First Post')
|
|
78
|
+
|
|
79
|
+
// Using sqlite3
|
|
80
|
+
db.serialize(() => {
|
|
81
|
+
db.run('BEGIN TRANSACTION')
|
|
82
|
+
db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com'], function(err) {
|
|
83
|
+
if (err) {
|
|
84
|
+
db.run('ROLLBACK')
|
|
85
|
+
throw err
|
|
86
|
+
}
|
|
87
|
+
const userId = this.lastID
|
|
88
|
+
db.run('INSERT INTO posts (user_id, title) VALUES (?, ?)', [userId, 'Post'], (err) => {
|
|
89
|
+
if (err) {
|
|
90
|
+
db.run('ROLLBACK')
|
|
91
|
+
throw err
|
|
92
|
+
}
|
|
93
|
+
db.run('COMMIT')
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Advanced Features
|
|
100
|
+
```typescript
|
|
101
|
+
// JSON operations (SQLite 3.38+)
|
|
102
|
+
const result = db.prepare(`
|
|
103
|
+
SELECT
|
|
104
|
+
id,
|
|
105
|
+
name,
|
|
106
|
+
json_extract(metadata, '$.category') AS category
|
|
107
|
+
FROM products
|
|
108
|
+
WHERE json_extract(metadata, '$.category') = ?
|
|
109
|
+
`).get('electronics')
|
|
110
|
+
|
|
111
|
+
// Full-text search (FTS5)
|
|
112
|
+
db.exec(`
|
|
113
|
+
CREATE VIRTUAL TABLE articles_fts USING fts5(
|
|
114
|
+
title,
|
|
115
|
+
content,
|
|
116
|
+
content_rowid=id
|
|
117
|
+
)
|
|
118
|
+
`)
|
|
119
|
+
|
|
120
|
+
const results = db.prepare(`
|
|
121
|
+
SELECT * FROM articles_fts
|
|
122
|
+
WHERE articles_fts MATCH ?
|
|
123
|
+
`).all('search term')
|
|
124
|
+
|
|
125
|
+
// Window functions (SQLite 3.25+)
|
|
126
|
+
const result = db.prepare(`
|
|
127
|
+
SELECT
|
|
128
|
+
name,
|
|
129
|
+
salary,
|
|
130
|
+
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank
|
|
131
|
+
FROM employees
|
|
132
|
+
`).all()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Common Patterns
|
|
136
|
+
|
|
137
|
+
### Prepared Statements
|
|
138
|
+
```typescript
|
|
139
|
+
// Reuse prepared statements for better performance
|
|
140
|
+
const getUserById = db.prepare('SELECT * FROM users WHERE id = ?')
|
|
141
|
+
const getUserByEmail = db.prepare('SELECT * FROM users WHERE email = ?')
|
|
142
|
+
|
|
143
|
+
// Use in functions
|
|
144
|
+
function getUser(id: number) {
|
|
145
|
+
return getUserById.get(id)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function findUserByEmail(email: string) {
|
|
149
|
+
return getUserByEmail.get(email)
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Batch Operations
|
|
154
|
+
```typescript
|
|
155
|
+
// Insert multiple rows efficiently
|
|
156
|
+
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
|
|
157
|
+
const insertMany = db.transaction((users) => {
|
|
158
|
+
for (const user of users) {
|
|
159
|
+
insert.run(user.name, user.email)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
insertMany([
|
|
164
|
+
{ name: 'User 1', email: 'user1@example.com' },
|
|
165
|
+
{ name: 'User 2', email: 'user2@example.com' },
|
|
166
|
+
])
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Migrations
|
|
170
|
+
```typescript
|
|
171
|
+
// Simple migration system
|
|
172
|
+
const migrations = [
|
|
173
|
+
`CREATE TABLE IF NOT EXISTS users (
|
|
174
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
175
|
+
name TEXT NOT NULL,
|
|
176
|
+
email TEXT UNIQUE NOT NULL,
|
|
177
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
178
|
+
)`,
|
|
179
|
+
`CREATE TABLE IF NOT EXISTS posts (
|
|
180
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
181
|
+
user_id INTEGER NOT NULL,
|
|
182
|
+
title TEXT NOT NULL,
|
|
183
|
+
content TEXT,
|
|
184
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
185
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
186
|
+
)`,
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
db.exec('BEGIN TRANSACTION')
|
|
190
|
+
try {
|
|
191
|
+
for (const migration of migrations) {
|
|
192
|
+
db.exec(migration)
|
|
193
|
+
}
|
|
194
|
+
db.exec('COMMIT')
|
|
195
|
+
} catch (error) {
|
|
196
|
+
db.exec('ROLLBACK')
|
|
197
|
+
throw error
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Best Practices
|
|
202
|
+
|
|
203
|
+
✅ **DO:**
|
|
204
|
+
- Use WAL mode for better concurrency
|
|
205
|
+
- Enable foreign keys
|
|
206
|
+
- Use prepared statements
|
|
207
|
+
- Use transactions for multiple operations
|
|
208
|
+
- Create indexes on frequently queried columns
|
|
209
|
+
- Use appropriate data types (TEXT, INTEGER, REAL, BLOB)
|
|
210
|
+
- Backup database regularly
|
|
211
|
+
- Use connection pooling (better-sqlite3 handles this)
|
|
212
|
+
- Monitor database size
|
|
213
|
+
- Use VACUUM periodically
|
|
214
|
+
|
|
215
|
+
❌ **DON'T:**
|
|
216
|
+
- Use for high-concurrency write scenarios
|
|
217
|
+
- Store large binary data (use external storage)
|
|
218
|
+
- Skip error handling
|
|
219
|
+
- Use string concatenation for queries
|
|
220
|
+
- Ignore database size limits
|
|
221
|
+
- Skip indexes on foreign keys
|
|
222
|
+
- Hardcode database paths
|
|
223
|
+
- Ignore transaction boundaries
|
|
224
|
+
- Use synchronous operations in async contexts (better-sqlite3 is fine)
|
|
225
|
+
- Skip backups
|
|
226
|
+
|
|
227
|
+
## Configuration
|
|
228
|
+
|
|
229
|
+
### Environment Variables
|
|
230
|
+
```bash
|
|
231
|
+
DB_PATH=./database.db
|
|
232
|
+
DB_PATH=/var/lib/myapp/database.db
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Initialization
|
|
236
|
+
```typescript
|
|
237
|
+
// Initialize database with schema
|
|
238
|
+
const db = new Database('./database.db')
|
|
239
|
+
|
|
240
|
+
db.pragma('journal_mode = WAL')
|
|
241
|
+
db.pragma('foreign_keys = ON')
|
|
242
|
+
db.pragma('synchronous = NORMAL')
|
|
243
|
+
db.pragma('cache_size = 10000')
|
|
244
|
+
db.pragma('temp_store = MEMORY')
|
|
245
|
+
|
|
246
|
+
// Create tables
|
|
247
|
+
db.exec(`
|
|
248
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
249
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
250
|
+
name TEXT NOT NULL,
|
|
251
|
+
email TEXT UNIQUE NOT NULL,
|
|
252
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)
|
|
256
|
+
`)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Integration with Development
|
|
260
|
+
|
|
261
|
+
### Testing
|
|
262
|
+
```typescript
|
|
263
|
+
// Use in-memory database for tests
|
|
264
|
+
const testDb = new Database(':memory:')
|
|
265
|
+
|
|
266
|
+
// Or use separate test database
|
|
267
|
+
const testDb = new Database('./test.db')
|
|
268
|
+
|
|
269
|
+
// Clean up after tests
|
|
270
|
+
afterEach(() => {
|
|
271
|
+
testDb.exec('DELETE FROM users')
|
|
272
|
+
testDb.exec('DELETE FROM posts')
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
afterAll(() => {
|
|
276
|
+
testDb.close()
|
|
277
|
+
// Optionally delete test database file
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Health Checks
|
|
282
|
+
```typescript
|
|
283
|
+
function checkDatabaseHealth(): boolean {
|
|
284
|
+
try {
|
|
285
|
+
db.prepare('SELECT 1').get()
|
|
286
|
+
return true
|
|
287
|
+
} catch {
|
|
288
|
+
return false
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
<!-- SQLITE:END -->
|
|
294
|
+
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
<!-- SQLSERVER:START -->
|
|
2
|
+
# SQL Server Database Instructions
|
|
3
|
+
|
|
4
|
+
**CRITICAL**: Use SQL Server for enterprise relational data storage with advanced features, high availability, and Windows integration.
|
|
5
|
+
|
|
6
|
+
## Core Features
|
|
7
|
+
|
|
8
|
+
### Connection
|
|
9
|
+
```typescript
|
|
10
|
+
// Using mssql (Node.js)
|
|
11
|
+
import sql from 'mssql'
|
|
12
|
+
|
|
13
|
+
const pool = await sql.connect({
|
|
14
|
+
server: process.env.DB_HOST || 'localhost',
|
|
15
|
+
port: parseInt(process.env.DB_PORT || '1433'),
|
|
16
|
+
database: process.env.DB_NAME || 'myapp',
|
|
17
|
+
user: process.env.DB_USER,
|
|
18
|
+
password: process.env.DB_PASSWORD,
|
|
19
|
+
options: {
|
|
20
|
+
encrypt: process.env.NODE_ENV === 'production',
|
|
21
|
+
trustServerCertificate: process.env.NODE_ENV !== 'production',
|
|
22
|
+
enableArithAbort: true,
|
|
23
|
+
connectionTimeout: 30000,
|
|
24
|
+
requestTimeout: 30000,
|
|
25
|
+
},
|
|
26
|
+
pool: {
|
|
27
|
+
max: 10,
|
|
28
|
+
min: 0,
|
|
29
|
+
idleTimeoutMillis: 30000,
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Using tedious (lower level)
|
|
34
|
+
import { Connection } from 'tedious'
|
|
35
|
+
|
|
36
|
+
const connection = new Connection({
|
|
37
|
+
server: process.env.DB_HOST || 'localhost',
|
|
38
|
+
authentication: {
|
|
39
|
+
type: 'default',
|
|
40
|
+
options: {
|
|
41
|
+
userName: process.env.DB_USER,
|
|
42
|
+
password: process.env.DB_PASSWORD,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
options: {
|
|
46
|
+
encrypt: true,
|
|
47
|
+
database: process.env.DB_NAME,
|
|
48
|
+
trustServerCertificate: true,
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Basic Queries
|
|
54
|
+
```typescript
|
|
55
|
+
// SELECT
|
|
56
|
+
const result = await pool.request()
|
|
57
|
+
.input('userId', sql.Int, userId)
|
|
58
|
+
.query('SELECT * FROM Users WHERE Id = @userId')
|
|
59
|
+
const users = result.recordset
|
|
60
|
+
|
|
61
|
+
// INSERT
|
|
62
|
+
const result = await pool.request()
|
|
63
|
+
.input('name', sql.NVarChar, 'John Doe')
|
|
64
|
+
.input('email', sql.NVarChar, 'john@example.com')
|
|
65
|
+
.query('INSERT INTO Users (Name, Email) OUTPUT INSERTED.* VALUES (@name, @email)')
|
|
66
|
+
const newUser = result.recordset[0]
|
|
67
|
+
|
|
68
|
+
// UPDATE
|
|
69
|
+
const result = await pool.request()
|
|
70
|
+
.input('id', sql.Int, userId)
|
|
71
|
+
.input('name', sql.NVarChar, 'Jane Doe')
|
|
72
|
+
.query('UPDATE Users SET Name = @name WHERE Id = @id')
|
|
73
|
+
|
|
74
|
+
// DELETE
|
|
75
|
+
await pool.request()
|
|
76
|
+
.input('id', sql.Int, userId)
|
|
77
|
+
.query('DELETE FROM Users WHERE Id = @id')
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Transactions
|
|
81
|
+
```typescript
|
|
82
|
+
const transaction = new sql.Transaction(pool)
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
await transaction.begin()
|
|
86
|
+
|
|
87
|
+
const request = new sql.Request(transaction)
|
|
88
|
+
await request
|
|
89
|
+
.input('userId', sql.Int, userId)
|
|
90
|
+
.input('amount', sql.Decimal(18, 2), 1000)
|
|
91
|
+
.query('INSERT INTO Accounts (UserId, Balance) VALUES (@userId, @amount)')
|
|
92
|
+
|
|
93
|
+
await request
|
|
94
|
+
.input('accountId', sql.Int, accountId)
|
|
95
|
+
.input('amount', sql.Decimal(18, 2), 1000)
|
|
96
|
+
.query('INSERT INTO Transactions (AccountId, Amount) VALUES (@accountId, @amount)')
|
|
97
|
+
|
|
98
|
+
await transaction.commit()
|
|
99
|
+
} catch (error) {
|
|
100
|
+
await transaction.rollback()
|
|
101
|
+
throw error
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Advanced Features
|
|
106
|
+
```typescript
|
|
107
|
+
// Stored procedures
|
|
108
|
+
const result = await pool.request()
|
|
109
|
+
.input('userId', sql.Int, userId)
|
|
110
|
+
.execute('sp_GetUserDetails')
|
|
111
|
+
|
|
112
|
+
// JSON operations (SQL Server 2016+)
|
|
113
|
+
const result = await pool.request()
|
|
114
|
+
.query(`
|
|
115
|
+
SELECT
|
|
116
|
+
Id,
|
|
117
|
+
Name,
|
|
118
|
+
JSON_VALUE(Metadata, '$.category') AS Category
|
|
119
|
+
FROM Products
|
|
120
|
+
WHERE JSON_VALUE(Metadata, '$.category') = 'electronics'
|
|
121
|
+
`)
|
|
122
|
+
|
|
123
|
+
// Full-text search
|
|
124
|
+
const result = await pool.request()
|
|
125
|
+
.input('searchTerm', sql.NVarChar, 'search term')
|
|
126
|
+
.query(`
|
|
127
|
+
SELECT * FROM Articles
|
|
128
|
+
WHERE CONTAINS(Content, @searchTerm)
|
|
129
|
+
`)
|
|
130
|
+
|
|
131
|
+
// Window functions
|
|
132
|
+
const result = await pool.request()
|
|
133
|
+
.query(`
|
|
134
|
+
SELECT
|
|
135
|
+
Name,
|
|
136
|
+
Salary,
|
|
137
|
+
ROW_NUMBER() OVER (PARTITION BY DepartmentId ORDER BY Salary DESC) AS Rank
|
|
138
|
+
FROM Employees
|
|
139
|
+
`)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Common Patterns
|
|
143
|
+
|
|
144
|
+
### Connection Pooling
|
|
145
|
+
```typescript
|
|
146
|
+
let pool: sql.ConnectionPool | null = null
|
|
147
|
+
|
|
148
|
+
export async function getPool(): Promise<sql.ConnectionPool> {
|
|
149
|
+
if (!pool) {
|
|
150
|
+
pool = await sql.connect({
|
|
151
|
+
// ... config
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
pool.on('error', (err) => {
|
|
155
|
+
console.error('SQL Server pool error', err)
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
return pool
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Graceful shutdown
|
|
162
|
+
process.on('SIGINT', async () => {
|
|
163
|
+
if (pool) {
|
|
164
|
+
await pool.close()
|
|
165
|
+
}
|
|
166
|
+
process.exit(0)
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Parameterized Queries
|
|
171
|
+
```typescript
|
|
172
|
+
// Always use parameters to prevent SQL injection
|
|
173
|
+
// ❌ WRONG
|
|
174
|
+
await pool.request().query(`SELECT * FROM Users WHERE Email = '${email}'`)
|
|
175
|
+
|
|
176
|
+
// ✅ CORRECT
|
|
177
|
+
await pool.request()
|
|
178
|
+
.input('email', sql.NVarChar, email)
|
|
179
|
+
.query('SELECT * FROM Users WHERE Email = @email')
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Error Handling
|
|
183
|
+
```typescript
|
|
184
|
+
try {
|
|
185
|
+
const result = await pool.request()
|
|
186
|
+
.input('id', sql.Int, userId)
|
|
187
|
+
.query('SELECT * FROM Users WHERE Id = @id')
|
|
188
|
+
|
|
189
|
+
if (result.recordset.length === 0) {
|
|
190
|
+
throw new Error('User not found')
|
|
191
|
+
}
|
|
192
|
+
return result.recordset[0]
|
|
193
|
+
} catch (error: any) {
|
|
194
|
+
if (error.number === 2627) { // Unique constraint violation
|
|
195
|
+
throw new Error('Duplicate entry')
|
|
196
|
+
}
|
|
197
|
+
if (error.number === 547) { // Foreign key constraint violation
|
|
198
|
+
throw new Error('Referenced record does not exist')
|
|
199
|
+
}
|
|
200
|
+
throw error
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Best Practices
|
|
205
|
+
|
|
206
|
+
✅ **DO:**
|
|
207
|
+
- Use connection pooling (10-20 connections)
|
|
208
|
+
- Always use parameterized queries (@param)
|
|
209
|
+
- Use transactions for multi-step operations
|
|
210
|
+
- Create indexes on frequently queried columns
|
|
211
|
+
- Use appropriate data types (NVarChar for Unicode)
|
|
212
|
+
- Enable encryption in production
|
|
213
|
+
- Use stored procedures for complex logic
|
|
214
|
+
- Monitor connection pool usage
|
|
215
|
+
- Use appropriate timeout values
|
|
216
|
+
- Implement retry logic for transient errors
|
|
217
|
+
|
|
218
|
+
❌ **DON'T:**
|
|
219
|
+
- Use string concatenation for queries (SQL injection risk)
|
|
220
|
+
- Create too many connections
|
|
221
|
+
- Skip error handling
|
|
222
|
+
- Ignore connection pool limits
|
|
223
|
+
- Use SELECT * in production
|
|
224
|
+
- Skip indexes on foreign keys
|
|
225
|
+
- Hardcode connection strings
|
|
226
|
+
- Skip encryption in production
|
|
227
|
+
- Ignore query performance
|
|
228
|
+
- Use synchronous operations
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
### Environment Variables
|
|
233
|
+
```bash
|
|
234
|
+
DB_HOST=localhost
|
|
235
|
+
DB_PORT=1433
|
|
236
|
+
DB_NAME=myapp
|
|
237
|
+
DB_USER=sa
|
|
238
|
+
DB_PASSWORD=securepassword
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Docker Compose
|
|
242
|
+
```yaml
|
|
243
|
+
services:
|
|
244
|
+
sqlserver:
|
|
245
|
+
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
246
|
+
ports:
|
|
247
|
+
- "1433:1433"
|
|
248
|
+
environment:
|
|
249
|
+
ACCEPT_EULA: Y
|
|
250
|
+
SA_PASSWORD: securepassword
|
|
251
|
+
MSSQL_PID: Developer
|
|
252
|
+
volumes:
|
|
253
|
+
- sqlserver_data:/var/opt/mssql
|
|
254
|
+
healthcheck:
|
|
255
|
+
test: ["CMD-SHELL", "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P securepassword -Q 'SELECT 1' || exit 1"]
|
|
256
|
+
interval: 10s
|
|
257
|
+
timeout: 5s
|
|
258
|
+
retries: 5
|
|
259
|
+
|
|
260
|
+
volumes:
|
|
261
|
+
sqlserver_data:
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Integration with Development
|
|
265
|
+
|
|
266
|
+
### Testing
|
|
267
|
+
```typescript
|
|
268
|
+
// Use test database
|
|
269
|
+
const testPool = await sql.connect({
|
|
270
|
+
database: 'myapp_test',
|
|
271
|
+
// ... config
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
// Clean up after tests
|
|
275
|
+
afterEach(async () => {
|
|
276
|
+
await testPool.request().query('DELETE FROM Users')
|
|
277
|
+
await testPool.request().query('DELETE FROM Posts')
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Health Checks
|
|
282
|
+
```typescript
|
|
283
|
+
async function checkDatabaseHealth(): Promise<boolean> {
|
|
284
|
+
try {
|
|
285
|
+
const result = await pool.request().query('SELECT 1 AS Health')
|
|
286
|
+
return result.recordset.length > 0
|
|
287
|
+
} catch {
|
|
288
|
+
return false
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
<!-- SQLSERVER:END -->
|
|
294
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Codespell
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master, main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master, main, develop ]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
codespell:
|
|
14
|
+
name: Check for spelling errors
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Install Codespell
|
|
22
|
+
run: python -m pip install --upgrade 'codespell[toml]'
|
|
23
|
+
|
|
24
|
+
- name: Run Codespell
|
|
25
|
+
run: |
|
|
26
|
+
codespell \
|
|
27
|
+
--skip="*.lock,*.json,*.map,*.yaml,*.yml,*.csv,*.bib,target,node_modules,.git,dist,venv,build,benchmarks,coverage" \
|
|
28
|
+
--ignore-words-list="crate,ser,deser,upToDate,optIn,shouldBe,Bloc"
|
|
29
|
+
# MONOREPO NOTE: Add multilingual stopwords to ignore-words-list if needed
|
|
30
|
+
# Example: --ignore-words-list="crate,ser,deser,meu,oder,ist,alle" (Portuguese,German,etc)
|
|
31
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: C++ Lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master, main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ '**' ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v5
|
|
15
|
+
|
|
16
|
+
- name: Install dependencies
|
|
17
|
+
run: |
|
|
18
|
+
sudo apt-get update
|
|
19
|
+
sudo apt-get install -y clang-format-15 clang-tidy-15 cppcheck cmake ninja-build
|
|
20
|
+
|
|
21
|
+
- name: Check formatting
|
|
22
|
+
run: |
|
|
23
|
+
find src include tests -name '*.cpp' -o -name '*.hpp' -o -name '*.h' | \
|
|
24
|
+
xargs clang-format-15 --dry-run --Werror
|
|
25
|
+
|
|
26
|
+
- name: Configure CMake (for compile commands)
|
|
27
|
+
run: cmake -B build -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
28
|
+
|
|
29
|
+
- name: Run clang-tidy
|
|
30
|
+
run: |
|
|
31
|
+
find src -name '*.cpp' | \
|
|
32
|
+
xargs clang-tidy-15 -p build --warnings-as-errors='*'
|
|
33
|
+
|
|
34
|
+
- name: Run cppcheck
|
|
35
|
+
run: |
|
|
36
|
+
cppcheck --enable=all --error-exitcode=1 \
|
|
37
|
+
--suppress=missingIncludeSystem \
|
|
38
|
+
--suppress=unmatchedSuppression \
|
|
39
|
+
--inline-suppr \
|
|
40
|
+
-I include \
|
|
41
|
+
src/ tests/
|
|
42
|
+
|
|
43
|
+
- name: Build with warnings as errors
|
|
44
|
+
run: |
|
|
45
|
+
cmake -B build -G Ninja -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic -Werror"
|
|
46
|
+
cmake --build build
|
|
47
|
+
|