@hivehub/rulebook 2.0.0 → 3.0.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/README.md +779 -654
- package/dist/cli/commands.d.ts +22 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +291 -8
- package/dist/cli/commands.js.map +1 -1
- package/dist/core/claude-mcp.d.ts +32 -0
- package/dist/core/claude-mcp.d.ts.map +1 -0
- package/dist/core/claude-mcp.js +92 -0
- package/dist/core/claude-mcp.js.map +1 -0
- package/dist/core/config-manager.d.ts.map +1 -1
- package/dist/core/config-manager.js +27 -6
- package/dist/core/config-manager.js.map +1 -1
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +98 -49
- package/dist/core/generator.js.map +1 -1
- package/dist/core/migrator.d.ts +13 -0
- package/dist/core/migrator.d.ts.map +1 -1
- package/dist/core/migrator.js +76 -9
- package/dist/core/migrator.js.map +1 -1
- package/dist/core/openspec-migrator.d.ts +1 -1
- package/dist/core/openspec-migrator.d.ts.map +1 -1
- package/dist/core/openspec-migrator.js +14 -7
- package/dist/core/openspec-migrator.js.map +1 -1
- package/dist/core/workflow-generator.js +297 -176
- package/dist/core/workflow-generator.js.map +1 -1
- package/dist/index.js +40 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +255 -74
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/hnsw-index.d.ts +63 -0
- package/dist/memory/hnsw-index.d.ts.map +1 -0
- package/dist/memory/hnsw-index.js +421 -0
- package/dist/memory/hnsw-index.js.map +1 -0
- package/dist/memory/memory-cache.d.ts +33 -0
- package/dist/memory/memory-cache.d.ts.map +1 -0
- package/dist/memory/memory-cache.js +85 -0
- package/dist/memory/memory-cache.js.map +1 -0
- package/dist/memory/memory-hooks.d.ts +42 -0
- package/dist/memory/memory-hooks.d.ts.map +1 -0
- package/dist/memory/memory-hooks.js +193 -0
- package/dist/memory/memory-hooks.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +55 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +209 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/memory/memory-search.d.ts +42 -0
- package/dist/memory/memory-search.d.ts.map +1 -0
- package/dist/memory/memory-search.js +166 -0
- package/dist/memory/memory-search.js.map +1 -0
- package/dist/memory/memory-store.d.ts +59 -0
- package/dist/memory/memory-store.d.ts.map +1 -0
- package/dist/memory/memory-store.js +394 -0
- package/dist/memory/memory-store.js.map +1 -0
- package/dist/memory/memory-types.d.ts +69 -0
- package/dist/memory/memory-types.d.ts.map +1 -0
- package/dist/memory/memory-types.js +7 -0
- package/dist/memory/memory-types.js.map +1 -0
- package/dist/memory/memory-vectorizer.d.ts +29 -0
- package/dist/memory/memory-vectorizer.d.ts.map +1 -0
- package/dist/memory/memory-vectorizer.js +104 -0
- package/dist/memory/memory-vectorizer.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +107 -106
- package/templates/cli/CLAUDE_CODE.md +114 -13
- package/templates/commands/rulebook-memory-save.md +48 -0
- package/templates/commands/rulebook-memory-search.md +47 -0
- package/templates/commands/rulebook-task-apply.md +2 -2
- package/templates/commands/rulebook-task-archive.md +2 -2
- package/templates/commands/rulebook-task-create.md +2 -2
- package/templates/commands/rulebook-task-list.md +2 -2
- package/templates/commands/rulebook-task-show.md +2 -2
- package/templates/commands/rulebook-task-validate.md +2 -2
- package/templates/git/CI_CD_PATTERNS.md +4 -4
- package/templates/git/GITHUB_ACTIONS.md +3 -3
- package/templates/git/GITLAB_CI.md +4 -4
- package/templates/git/SECRETS_MANAGEMENT.md +4 -4
- package/templates/hooks/COMMIT_MSG.md +4 -4
- package/templates/hooks/POST_CHECKOUT.md +3 -3
- package/templates/hooks/PREPARE_COMMIT_MSG.md +3 -3
- package/templates/hooks/PRE_COMMIT.md +4 -4
- package/templates/hooks/PRE_PUSH.md +4 -4
- package/templates/modules/MEMORY.md +63 -0
- package/templates/skills/cli/aider/SKILL.md +59 -0
- package/templates/skills/cli/amazon-q/SKILL.md +35 -0
- package/templates/skills/cli/auggie/SKILL.md +42 -0
- package/templates/skills/cli/claude/SKILL.md +42 -0
- package/templates/skills/cli/claude-code/SKILL.md +146 -0
- package/templates/skills/cli/cline/SKILL.md +42 -0
- package/templates/skills/cli/codebuddy/SKILL.md +30 -0
- package/templates/skills/cli/codeium/SKILL.md +30 -0
- package/templates/skills/cli/codex/SKILL.md +31 -0
- package/templates/skills/cli/continue/SKILL.md +44 -0
- package/templates/skills/cli/cursor-cli/SKILL.md +38 -0
- package/templates/skills/cli/factory/SKILL.md +28 -0
- package/templates/skills/cli/gemini/SKILL.md +45 -0
- package/templates/skills/cli/kilocode/SKILL.md +28 -0
- package/templates/skills/cli/opencode/SKILL.md +28 -0
- package/templates/skills/core/agent-automation/SKILL.md +194 -0
- package/templates/skills/core/dag/SKILL.md +314 -0
- package/templates/skills/core/documentation-rules/SKILL.md +47 -0
- package/templates/skills/core/quality-enforcement/SKILL.md +78 -0
- package/templates/skills/frameworks/angular/SKILL.md +46 -0
- package/templates/skills/frameworks/django/SKILL.md +93 -0
- package/templates/skills/frameworks/electron/SKILL.md +157 -0
- package/templates/skills/frameworks/flask/SKILL.md +48 -0
- package/templates/skills/frameworks/flutter/SKILL.md +65 -0
- package/templates/skills/frameworks/jquery/SKILL.md +42 -0
- package/templates/skills/frameworks/laravel/SKILL.md +48 -0
- package/templates/skills/frameworks/nestjs/SKILL.md +53 -0
- package/templates/skills/frameworks/nextjs/SKILL.md +137 -0
- package/templates/skills/frameworks/nuxt/SKILL.md +50 -0
- package/templates/skills/frameworks/rails/SKILL.md +76 -0
- package/templates/skills/frameworks/react/SKILL.md +48 -0
- package/templates/skills/frameworks/react-native/SKILL.md +57 -0
- package/templates/skills/frameworks/spring/SKILL.md +49 -0
- package/templates/skills/frameworks/symfony/SKILL.md +46 -0
- package/templates/skills/frameworks/vue/SKILL.md +46 -0
- package/templates/skills/frameworks/zend/SKILL.md +45 -0
- package/templates/skills/ides/copilot/SKILL.md +47 -0
- package/templates/skills/ides/cursor/SKILL.md +53 -0
- package/templates/skills/ides/jetbrains-ai/SKILL.md +45 -0
- package/templates/skills/ides/replit/SKILL.md +46 -0
- package/templates/skills/ides/tabnine/SKILL.md +39 -0
- package/templates/skills/ides/vscode/SKILL.md +50 -0
- package/templates/skills/ides/windsurf/SKILL.md +46 -0
- package/templates/skills/ides/zed/SKILL.md +42 -0
- package/templates/skills/languages/ada/SKILL.md +68 -0
- package/templates/skills/languages/c/SKILL.md +343 -0
- package/templates/skills/languages/cpp/SKILL.md +753 -0
- package/templates/skills/languages/csharp/SKILL.md +427 -0
- package/templates/skills/languages/dart/SKILL.md +342 -0
- package/templates/skills/languages/elixir/SKILL.md +464 -0
- package/templates/skills/languages/erlang/SKILL.md +371 -0
- package/templates/skills/languages/go/SKILL.md +655 -0
- package/templates/skills/languages/haskell/SKILL.md +187 -0
- package/templates/skills/languages/java/SKILL.md +617 -0
- package/templates/skills/languages/javascript/SKILL.md +641 -0
- package/templates/skills/languages/julia/SKILL.md +107 -0
- package/templates/skills/languages/kotlin/SKILL.md +521 -0
- package/templates/skills/languages/lisp/SKILL.md +110 -0
- package/templates/skills/languages/lua/SKILL.md +84 -0
- package/templates/skills/languages/objectivec/SKILL.md +100 -0
- package/templates/skills/languages/php/SKILL.md +426 -0
- package/templates/skills/languages/python/SKILL.md +692 -0
- package/templates/skills/languages/r/SKILL.md +360 -0
- package/templates/skills/languages/ruby/SKILL.md +431 -0
- package/templates/skills/languages/rust/SKILL.md +487 -0
- package/templates/skills/languages/sas/SKILL.md +83 -0
- package/templates/skills/languages/scala/SKILL.md +358 -0
- package/templates/skills/languages/solidity/SKILL.md +590 -0
- package/templates/skills/languages/sql/SKILL.md +147 -0
- package/templates/skills/languages/swift/SKILL.md +476 -0
- package/templates/skills/languages/zig/SKILL.md +275 -0
- package/templates/skills/modules/atlassian/SKILL.md +265 -0
- package/templates/skills/modules/context7/SKILL.md +64 -0
- package/templates/skills/modules/figma/SKILL.md +277 -0
- package/templates/skills/modules/github-mcp/SKILL.md +74 -0
- package/templates/skills/modules/grafana/SKILL.md +338 -0
- package/templates/skills/modules/memory/SKILL.md +73 -0
- package/templates/skills/modules/notion/SKILL.md +257 -0
- package/templates/skills/modules/playwright/SKILL.md +100 -0
- package/templates/skills/modules/rulebook-mcp/SKILL.md +166 -0
- package/templates/skills/modules/serena/SKILL.md +347 -0
- package/templates/skills/modules/supabase/SKILL.md +233 -0
- package/templates/skills/modules/synap/SKILL.md +79 -0
- package/templates/skills/modules/vectorizer/SKILL.md +73 -0
- package/templates/skills/services/azure-blob/SKILL.md +194 -0
- package/templates/skills/services/cassandra/SKILL.md +249 -0
- package/templates/skills/services/dynamodb/SKILL.md +318 -0
- package/templates/skills/services/elasticsearch/SKILL.md +357 -0
- package/templates/skills/services/gcs/SKILL.md +188 -0
- package/templates/skills/services/influxdb/SKILL.md +275 -0
- package/templates/skills/services/kafka/SKILL.md +351 -0
- package/templates/skills/services/mariadb/SKILL.md +193 -0
- package/templates/skills/services/memcached/SKILL.md +252 -0
- package/templates/skills/services/minio/SKILL.md +211 -0
- package/templates/skills/services/mongodb/SKILL.md +278 -0
- package/templates/skills/services/mysql/SKILL.md +368 -0
- package/templates/skills/services/neo4j/SKILL.md +257 -0
- package/templates/skills/services/oracle/SKILL.md +300 -0
- package/templates/skills/services/postgresql/SKILL.md +336 -0
- package/templates/skills/services/rabbitmq/SKILL.md +296 -0
- package/templates/skills/services/redis/SKILL.md +302 -0
- package/templates/skills/services/s3/SKILL.md +308 -0
- package/templates/skills/services/sqlite/SKILL.md +304 -0
- package/templates/skills/services/sqlserver/SKILL.md +304 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Google Cloud Storage"
|
|
3
|
+
description: "Use Google Cloud Storage for object storage, file uploads, static assets, and backup storage in GCP."
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
category: "services"
|
|
6
|
+
author: "Rulebook"
|
|
7
|
+
tags: ["services", "storage"]
|
|
8
|
+
dependencies: []
|
|
9
|
+
conflicts: []
|
|
10
|
+
---
|
|
11
|
+
<!-- GCS:START -->
|
|
12
|
+
# Google Cloud Storage Instructions
|
|
13
|
+
|
|
14
|
+
**CRITICAL**: Use Google Cloud Storage for object storage, file uploads, static assets, and backup storage in GCP.
|
|
15
|
+
|
|
16
|
+
## Core Features
|
|
17
|
+
|
|
18
|
+
### Connection
|
|
19
|
+
```typescript
|
|
20
|
+
// Using @google-cloud/storage
|
|
21
|
+
import { Storage } from '@google-cloud/storage'
|
|
22
|
+
|
|
23
|
+
const storage = new Storage({
|
|
24
|
+
projectId: process.env.GCP_PROJECT_ID,
|
|
25
|
+
keyFilename: process.env.GCP_KEY_FILE, // Path to service account key
|
|
26
|
+
// Or use credentials object
|
|
27
|
+
credentials: {
|
|
28
|
+
client_email: process.env.GCP_CLIENT_EMAIL,
|
|
29
|
+
private_key: process.env.GCP_PRIVATE_KEY?.replace(/\\n/g, '\n'),
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const bucket = storage.bucket(process.env.GCS_BUCKET_NAME || 'my-bucket')
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Basic Operations
|
|
37
|
+
```typescript
|
|
38
|
+
// Upload file
|
|
39
|
+
const file = bucket.file('path/to/file.jpg')
|
|
40
|
+
await file.save(fileBuffer, {
|
|
41
|
+
metadata: {
|
|
42
|
+
contentType: 'image/jpeg',
|
|
43
|
+
metadata: {
|
|
44
|
+
userId: '123',
|
|
45
|
+
originalName: 'photo.jpg',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// Download file
|
|
51
|
+
const [fileContent] = await file.download()
|
|
52
|
+
|
|
53
|
+
// Delete file
|
|
54
|
+
await file.delete()
|
|
55
|
+
|
|
56
|
+
// List files
|
|
57
|
+
const [files] = await bucket.getFiles({
|
|
58
|
+
prefix: 'uploads/',
|
|
59
|
+
maxResults: 100,
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Advanced Features
|
|
64
|
+
```typescript
|
|
65
|
+
// Generate signed URL
|
|
66
|
+
const [url] = await file.getSignedUrl({
|
|
67
|
+
action: 'read',
|
|
68
|
+
expires: Date.now() + 3600 * 1000, // 1 hour
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Generate signed URL for upload
|
|
72
|
+
const [uploadUrl] = await file.getSignedUrl({
|
|
73
|
+
action: 'write',
|
|
74
|
+
expires: Date.now() + 3600 * 1000,
|
|
75
|
+
contentType: 'image/jpeg',
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// Copy file
|
|
79
|
+
const sourceFile = bucket.file('source/file.jpg')
|
|
80
|
+
const destFile = bucket.file('dest/file.jpg')
|
|
81
|
+
await sourceFile.copy(destFile)
|
|
82
|
+
|
|
83
|
+
// Set metadata
|
|
84
|
+
await file.setMetadata({
|
|
85
|
+
metadata: {
|
|
86
|
+
category: 'profile',
|
|
87
|
+
uploadedBy: 'user-123',
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Get metadata
|
|
92
|
+
const [metadata] = await file.getMetadata()
|
|
93
|
+
console.log(metadata.contentType, metadata.size, metadata.metadata)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Common Patterns
|
|
97
|
+
|
|
98
|
+
### File Upload Handler
|
|
99
|
+
```typescript
|
|
100
|
+
async function uploadFile(file: Buffer, filename: string, userId: string) {
|
|
101
|
+
const filePath = `users/${userId}/${Date.now()}-${filename}`
|
|
102
|
+
const file = bucket.file(filePath)
|
|
103
|
+
|
|
104
|
+
await file.save(file, {
|
|
105
|
+
metadata: {
|
|
106
|
+
contentType: getContentType(filename),
|
|
107
|
+
metadata: {
|
|
108
|
+
userId,
|
|
109
|
+
originalName: filename,
|
|
110
|
+
uploadedAt: new Date().toISOString(),
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
await file.makePublic() // Or use signed URLs
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
filePath,
|
|
119
|
+
publicUrl: file.publicUrl(),
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Temporary Access URL
|
|
125
|
+
```typescript
|
|
126
|
+
async function generateTemporaryUrl(filePath: string, expiresInMinutes: number = 60) {
|
|
127
|
+
const file = bucket.file(filePath)
|
|
128
|
+
const [url] = await file.getSignedUrl({
|
|
129
|
+
action: 'read',
|
|
130
|
+
expires: Date.now() + expiresInMinutes * 60 * 1000,
|
|
131
|
+
})
|
|
132
|
+
return url
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Best Practices
|
|
137
|
+
|
|
138
|
+
✅ **DO:**
|
|
139
|
+
- Use appropriate storage classes (Standard, Nearline, Coldline, Archive)
|
|
140
|
+
- Set blob metadata for organization
|
|
141
|
+
- Use signed URLs for temporary access
|
|
142
|
+
- Implement proper error handling
|
|
143
|
+
- Use appropriate content types
|
|
144
|
+
- Enable versioning for important data
|
|
145
|
+
- Monitor storage usage and costs
|
|
146
|
+
- Use lifecycle management policies
|
|
147
|
+
- Implement retry logic
|
|
148
|
+
- Use service account credentials
|
|
149
|
+
|
|
150
|
+
❌ **DON'T:**
|
|
151
|
+
- Store sensitive data without encryption
|
|
152
|
+
- Make files public unnecessarily
|
|
153
|
+
- Hardcode credentials
|
|
154
|
+
- Ignore error handling
|
|
155
|
+
- Skip content-type validation
|
|
156
|
+
- Ignore lifecycle policies
|
|
157
|
+
- Skip access logging
|
|
158
|
+
- Use default permissions
|
|
159
|
+
- Ignore cost optimization
|
|
160
|
+
- Store large files without chunking
|
|
161
|
+
|
|
162
|
+
## Configuration
|
|
163
|
+
|
|
164
|
+
### Environment Variables
|
|
165
|
+
```bash
|
|
166
|
+
GCP_PROJECT_ID=my-project
|
|
167
|
+
GCP_KEY_FILE=/path/to/service-account-key.json
|
|
168
|
+
GCP_CLIENT_EMAIL=service-account@project.iam.gserviceaccount.com
|
|
169
|
+
GCP_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n..."
|
|
170
|
+
GCS_BUCKET_NAME=my-bucket
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Service Account Key
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"type": "service_account",
|
|
177
|
+
"project_id": "my-project",
|
|
178
|
+
"private_key_id": "...",
|
|
179
|
+
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
|
|
180
|
+
"client_email": "service-account@project.iam.gserviceaccount.com",
|
|
181
|
+
"client_id": "...",
|
|
182
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
|
183
|
+
"token_uri": "https://oauth2.googleapis.com/token"
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
<!-- GCS:END -->
|
|
188
|
+
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "InfluxDB"
|
|
3
|
+
description: "Use InfluxDB for time-series data, metrics, IoT data, and real-time analytics with high write throughput."
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
category: "services"
|
|
6
|
+
author: "Rulebook"
|
|
7
|
+
tags: ["services", "database"]
|
|
8
|
+
dependencies: []
|
|
9
|
+
conflicts: []
|
|
10
|
+
---
|
|
11
|
+
<!-- INFLUXDB:START -->
|
|
12
|
+
# InfluxDB Time-Series Database Instructions
|
|
13
|
+
|
|
14
|
+
**CRITICAL**: Use InfluxDB for time-series data, metrics, IoT data, and real-time analytics with high write throughput.
|
|
15
|
+
|
|
16
|
+
## Core Features
|
|
17
|
+
|
|
18
|
+
### Connection
|
|
19
|
+
```typescript
|
|
20
|
+
// Using @influxdata/influxdb-client
|
|
21
|
+
import { InfluxDB, Point } from '@influxdata/influxdb-client'
|
|
22
|
+
|
|
23
|
+
const token = process.env.INFLUXDB_TOKEN || ''
|
|
24
|
+
const org = process.env.INFLUXDB_ORG || 'myorg'
|
|
25
|
+
const bucket = process.env.INFLUXDB_BUCKET || 'mybucket'
|
|
26
|
+
|
|
27
|
+
const client = new InfluxDB({
|
|
28
|
+
url: process.env.INFLUXDB_URL || 'http://localhost:8086',
|
|
29
|
+
token,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const writeApi = client.getWriteApi(org, bucket, 'ns')
|
|
33
|
+
const queryApi = client.getQueryApi(org)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Writing Data
|
|
37
|
+
```typescript
|
|
38
|
+
// Create point
|
|
39
|
+
const point = new Point('temperature')
|
|
40
|
+
.tag('location', 'room1')
|
|
41
|
+
.tag('sensor', 'sensor1')
|
|
42
|
+
.floatField('value', 23.5)
|
|
43
|
+
.timestamp(new Date())
|
|
44
|
+
|
|
45
|
+
writeApi.writePoint(point)
|
|
46
|
+
|
|
47
|
+
// Multiple points
|
|
48
|
+
const points = [
|
|
49
|
+
new Point('temperature').tag('location', 'room1').floatField('value', 23.5),
|
|
50
|
+
new Point('humidity').tag('location', 'room1').floatField('value', 65.2),
|
|
51
|
+
new Point('pressure').tag('location', 'room1').floatField('value', 1013.25),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
writeApi.writePoints(points)
|
|
55
|
+
await writeApi.close()
|
|
56
|
+
|
|
57
|
+
// Using line protocol
|
|
58
|
+
writeApi.writeRecord('temperature,location=room1 value=23.5')
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Querying Data
|
|
62
|
+
```typescript
|
|
63
|
+
// Flux query
|
|
64
|
+
const query = `
|
|
65
|
+
from(bucket: "${bucket}")
|
|
66
|
+
|> range(start: -1h)
|
|
67
|
+
|> filter(fn: (r) => r._measurement == "temperature")
|
|
68
|
+
|> filter(fn: (r) => r.location == "room1")
|
|
69
|
+
|> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
|
|
70
|
+
|> yield(name: "mean")
|
|
71
|
+
`
|
|
72
|
+
|
|
73
|
+
queryApi.queryRows(query, {
|
|
74
|
+
next(row, tableMeta) {
|
|
75
|
+
const record = tableMeta.toObject(row)
|
|
76
|
+
console.log(record)
|
|
77
|
+
},
|
|
78
|
+
error(error) {
|
|
79
|
+
console.error(error)
|
|
80
|
+
},
|
|
81
|
+
complete() {
|
|
82
|
+
console.log('Query completed')
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
// InfluxQL query (legacy)
|
|
87
|
+
const query = `
|
|
88
|
+
SELECT mean("value")
|
|
89
|
+
FROM "temperature"
|
|
90
|
+
WHERE "location" = 'room1'
|
|
91
|
+
AND time >= now() - 1h
|
|
92
|
+
GROUP BY time(5m)
|
|
93
|
+
`
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Common Patterns
|
|
97
|
+
|
|
98
|
+
### Metrics Collection
|
|
99
|
+
```typescript
|
|
100
|
+
async function recordMetric(measurement: string, tags: Record<string, string>, fields: Record<string, number>) {
|
|
101
|
+
const point = new Point(measurement)
|
|
102
|
+
|
|
103
|
+
for (const [key, value] of Object.entries(tags)) {
|
|
104
|
+
point.tag(key, value)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
108
|
+
point.floatField(key, value)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
point.timestamp(new Date())
|
|
112
|
+
writeApi.writePoint(point)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Usage
|
|
116
|
+
await recordMetric('api_request', {
|
|
117
|
+
endpoint: '/users',
|
|
118
|
+
method: 'GET',
|
|
119
|
+
status: '200',
|
|
120
|
+
}, {
|
|
121
|
+
duration: 125.5,
|
|
122
|
+
bytes: 2048,
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Aggregations
|
|
127
|
+
```typescript
|
|
128
|
+
async function getAverageTemperature(location: string, duration: string) {
|
|
129
|
+
const query = `
|
|
130
|
+
from(bucket: "${bucket}")
|
|
131
|
+
|> range(start: ${duration})
|
|
132
|
+
|> filter(fn: (r) => r._measurement == "temperature")
|
|
133
|
+
|> filter(fn: (r) => r.location == "${location}")
|
|
134
|
+
|> mean()
|
|
135
|
+
`
|
|
136
|
+
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
const results: number[] = []
|
|
139
|
+
queryApi.queryRows(query, {
|
|
140
|
+
next(row, tableMeta) {
|
|
141
|
+
const record = tableMeta.toObject(row)
|
|
142
|
+
results.push(record._value)
|
|
143
|
+
},
|
|
144
|
+
error: reject,
|
|
145
|
+
complete() {
|
|
146
|
+
resolve(results[0] || 0)
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Batch Writing
|
|
154
|
+
```typescript
|
|
155
|
+
class MetricsBuffer {
|
|
156
|
+
private points: Point[] = []
|
|
157
|
+
private maxSize = 1000
|
|
158
|
+
private flushInterval = 5000 // 5 seconds
|
|
159
|
+
|
|
160
|
+
constructor() {
|
|
161
|
+
setInterval(() => this.flush(), this.flushInterval)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
add(point: Point) {
|
|
165
|
+
this.points.push(point)
|
|
166
|
+
if (this.points.length >= this.maxSize) {
|
|
167
|
+
this.flush()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async flush() {
|
|
172
|
+
if (this.points.length === 0) return
|
|
173
|
+
|
|
174
|
+
const points = [...this.points]
|
|
175
|
+
this.points = []
|
|
176
|
+
|
|
177
|
+
for (const point of points) {
|
|
178
|
+
writeApi.writePoint(point)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await writeApi.flush()
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Best Practices
|
|
187
|
+
|
|
188
|
+
✅ **DO:**
|
|
189
|
+
- Use tags for frequently filtered fields
|
|
190
|
+
- Use fields for numeric values
|
|
191
|
+
- Batch writes for better performance
|
|
192
|
+
- Use appropriate retention policies
|
|
193
|
+
- Monitor disk usage
|
|
194
|
+
- Use downsampling for old data
|
|
195
|
+
- Create continuous queries for aggregations
|
|
196
|
+
- Use appropriate precision (ns, us, ms, s)
|
|
197
|
+
- Tag data with metadata (location, device, etc.)
|
|
198
|
+
- Monitor write performance
|
|
199
|
+
|
|
200
|
+
❌ **DON'T:**
|
|
201
|
+
- Store high-cardinality data in tags
|
|
202
|
+
- Store non-numeric data in fields
|
|
203
|
+
- Write points one at a time
|
|
204
|
+
- Ignore retention policies
|
|
205
|
+
- Store sensitive data without encryption
|
|
206
|
+
- Hardcode connection strings
|
|
207
|
+
- Skip error handling
|
|
208
|
+
- Ignore disk space
|
|
209
|
+
- Use too many tags (affects performance)
|
|
210
|
+
- Store large text in fields
|
|
211
|
+
|
|
212
|
+
## Configuration
|
|
213
|
+
|
|
214
|
+
### Environment Variables
|
|
215
|
+
```bash
|
|
216
|
+
INFLUXDB_URL=http://localhost:8086
|
|
217
|
+
INFLUXDB_TOKEN=your-token
|
|
218
|
+
INFLUXDB_ORG=myorg
|
|
219
|
+
INFLUXDB_BUCKET=mybucket
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Docker Compose
|
|
223
|
+
```yaml
|
|
224
|
+
services:
|
|
225
|
+
influxdb:
|
|
226
|
+
image: influxdb:2.7
|
|
227
|
+
ports:
|
|
228
|
+
- "8086:8086"
|
|
229
|
+
environment:
|
|
230
|
+
DOCKER_INFLUXDB_INIT_MODE: setup
|
|
231
|
+
DOCKER_INFLUXDB_INIT_USERNAME: admin
|
|
232
|
+
DOCKER_INFLUXDB_INIT_PASSWORD: securepassword
|
|
233
|
+
DOCKER_INFLUXDB_INIT_ORG: myorg
|
|
234
|
+
DOCKER_INFLUXDB_INIT_BUCKET: mybucket
|
|
235
|
+
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: your-token
|
|
236
|
+
volumes:
|
|
237
|
+
- influxdb_data:/var/lib/influxdb2
|
|
238
|
+
healthcheck:
|
|
239
|
+
test: ["CMD", "influx", "ping"]
|
|
240
|
+
interval: 10s
|
|
241
|
+
timeout: 5s
|
|
242
|
+
retries: 5
|
|
243
|
+
|
|
244
|
+
volumes:
|
|
245
|
+
influxdb_data:
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Integration with Development
|
|
249
|
+
|
|
250
|
+
### Testing
|
|
251
|
+
```typescript
|
|
252
|
+
// Use test bucket
|
|
253
|
+
const testBucket = 'test_bucket'
|
|
254
|
+
const testWriteApi = client.getWriteApi(org, testBucket, 'ns')
|
|
255
|
+
|
|
256
|
+
// Clean up after tests
|
|
257
|
+
afterEach(async () => {
|
|
258
|
+
// Delete test data or use separate test bucket
|
|
259
|
+
})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Health Checks
|
|
263
|
+
```typescript
|
|
264
|
+
async function checkInfluxDBHealth(): Promise<boolean> {
|
|
265
|
+
try {
|
|
266
|
+
const health = await fetch(`${process.env.INFLUXDB_URL}/health`)
|
|
267
|
+
return health.ok
|
|
268
|
+
} catch {
|
|
269
|
+
return false
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
<!-- INFLUXDB:END -->
|
|
275
|
+
|