@stacknext/drizzle 0.8.0 → 0.10.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.
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: Configuration
3
+ description: Configure the Drizzle adapter, transport and database settings.
4
+ ---
5
+
6
+ # Configuration
7
+
8
+ ## Adapter options
9
+
10
+ ```ts
11
+ import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
12
+
13
+ const logger = createStackNextDrizzleLogger({
14
+ databaseSystem: 'postgresql',
15
+ })
16
+ ```
17
+
18
+ | Option | Required | Default | Notes |
19
+ | --- | --- | --- | --- |
20
+ | `databaseSystem` | No | `'sql'` | Use the engine name, for example `sqlite`, `postgresql` or `mysql`. |
21
+ | `transport` | No | Process-wide transport | Must expose `enqueueDatabaseQuery`. |
22
+ | `onError` | No | none | Receives telemetry failures; they never reach Drizzle. |
23
+
24
+ ## Connect the logger
25
+
26
+ ```ts
27
+ import { drizzle } from 'drizzle-orm/better-sqlite3'
28
+ import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
29
+
30
+ export const db = drizzle(client, {
31
+ logger: createStackNextDrizzleLogger({ databaseSystem: 'sqlite' }),
32
+ })
33
+ ```
34
+
35
+ The logger is registered when the Drizzle client is created. There is no
36
+ automatic global registration and no monkey-patching.
37
+
38
+ ## `stacknext.config.json`
39
+
40
+ ```json
41
+ {
42
+ "database": { "drizzle": true, "prisma": false }
43
+ }
44
+ ```
45
+
46
+ `database.drizzle` is setup intent used by `stacknext init` and
47
+ `stacknext doctor`. Setting it does **not** attach the logger. The adapter must
48
+ be passed to `drizzle(...)` explicitly.
49
+
50
+ ## Environment
51
+
52
+ The adapter uses the active transport. `stacknext dev` exports
53
+ `STACKNEXT_COLLECTOR_URL` and `STACKNEXT_TOKEN`; outside that environment the
54
+ global transport is absent and the logger is inert.
55
+
56
+ Optional adapter overrides for tests are passed through `options.transport`, not
57
+ environment variables.
58
+
59
+ ## Captured fields
60
+
61
+ See [the package overview](index.md#what-is-recorded). There is no option to
62
+ enable bind-parameter capture, SQL parameter logging or query bodies.
63
+
64
+ ## Verify
65
+
66
+ 1. Start `stacknext dev` and make a request that queries the database.
67
+ 2. Run `stacknext coverage`; the database category should show observed
68
+ evidence.
69
+ 3. Open the dashboard Database page or call `list_database_queries` through MCP.
70
+ 4. Confirm durations are `null` and marked unmeasured. That is expected.
package/docs/index.md ADDED
@@ -0,0 +1,94 @@
1
+ ---
2
+ title: "@stacknext/drizzle"
3
+ description: Drizzle ORM query logging adapter for StackNext, without bind-parameter capture.
4
+ ---
5
+
6
+ # @stacknext/drizzle
7
+
8
+ `@stacknext/drizzle` is a Drizzle `Logger` adapter. It sends redacted SQL events
9
+ to the active StackNext transport so queries appear in request timelines and
10
+ diagnostics.
11
+
12
+ ## Who should read this
13
+
14
+ Applications using Drizzle. This is a **public, optional integration package**.
15
+ It is not required unless the project uses Drizzle.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pnpm add @stacknext/drizzle
21
+ ```
22
+
23
+ `drizzle-orm >=0.30.0` is an optional peer dependency. The adapter does not
24
+ import Drizzle at runtime; it accepts any object matching
25
+ `{ logQuery(query, params) }`.
26
+
27
+ ## Usage
28
+
29
+ ```ts
30
+ import { drizzle } from 'drizzle-orm/better-sqlite3'
31
+ import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
32
+
33
+ export const db = drizzle(client, {
34
+ logger: createStackNextDrizzleLogger({ databaseSystem: 'sqlite' }),
35
+ })
36
+ ```
37
+
38
+ ## API
39
+
40
+ ### `createStackNextDrizzleLogger(options?)`
41
+
42
+ Returns a `DrizzleLoggerLike` with `logQuery(query, params)`.
43
+
44
+ `StackNextDrizzleLoggerOptions`:
45
+
46
+ | Option | Type | Default | Meaning |
47
+ | --- | --- | --- | --- |
48
+ | `databaseSystem` | string | `'sql'` | Value reported as `db.system.name`. |
49
+ | `transport` | `Pick<StackNextTransport, 'enqueueDatabaseQuery'>` | global transport | Override for tests or custom setups. |
50
+ | `onError` | `(error: unknown) => void` | none | Called when the telemetry sink throws. |
51
+
52
+ <!-- coderabbit-ai-generated:v1 -->
53
+
54
+ <!-- coderabbit-ai-generated-section:v1:92e6ad51fd00b5bd40b76d93991b902366deea6ad1bb299cee86b066438eac33 -->
55
+
56
+ Telemetry failures are caught, but a throwing `onError` callback can propagate
57
+ its error to Drizzle. Callers must ensure `onError` does not throw. If no transport is active, the
58
+ logger is a no-op.
59
+
60
+ <!-- /coderabbit-ai-generated:v1 -->
61
+
62
+ ## What is recorded
63
+
64
+ - redacted SQL text (capped at 20,000 characters);
65
+ - inferred operation (`select`, `insert`, `update`, `delete`, `with`, and so
66
+ on);
67
+ - active trace/span ids when a valid OTel context exists;
68
+ - `databaseSystem`, `success: true`, `source: 'drizzle'`;
69
+ - `db.query.parameter_count` (the count only);
70
+ - `db.duration.measured: false`.
71
+
72
+ ## Duration is null
73
+
74
+ Drizzle's `Logger` interface does not expose query duration. StackNext stores
75
+ `durationMs: null` and marks it unmeasured. It is never converted to zero.
76
+
77
+ Do not compare Drizzle durations with Prisma durations or rank them as if they
78
+ were fast.
79
+
80
+ ## Privacy
81
+
82
+ `params` is used only for `Array.isArray(params) ? params.length : 0`. The
83
+ values are never read, logged or transmitted. SQL text passes through
84
+ `redactSql`.
85
+
86
+ ## Documentation map
87
+
88
+ - [Configuration](configuration.md)
89
+ - [Troubleshooting](troubleshooting.md)
90
+
91
+ ## Related packages
92
+
93
+ - `@stacknext/core` owns the transport and redaction.
94
+ - `@stacknext/cli` runs the collector.
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: Troubleshooting
3
+ description: Diagnose missing Drizzle queries, null durations and adapter registration problems.
4
+ ---
5
+
6
+ # Troubleshooting
7
+
8
+ ## No Drizzle queries appear
9
+
10
+ 1. Confirm `createStackNextDrizzleLogger()` is passed to the same Drizzle client
11
+ that serves requests.
12
+ 2. Confirm the app is running under `stacknext dev`, which supplies the
13
+ transport environment.
14
+ 3. Make a request that actually executes a query.
15
+ 4. Run `stacknext coverage`; `database` evidence should become observed.
16
+ 5. Check `stacknext doctor` for adapter/config warnings.
17
+
18
+ ## Queries appear without a trace
19
+
20
+ The adapter records trace/span ids only when a valid OpenTelemetry context is
21
+ active. Queries from scripts, workers or background jobs may have no request
22
+ root. They are still stored, but they are not attributed to a request.
23
+
24
+ ## Duration is null
25
+
26
+ Expected. Drizzle's logger does not expose duration. StackNext stores `null` and
27
+ sets `db.duration.measured: false`.
28
+
29
+ Do not treat `null` as zero, and do not compare Drizzle and Prisma durations.
30
+
31
+ ## SQL is redacted or truncated
32
+
33
+ SQL passes through `redactSql` and is capped at 20,000 characters. Bind
34
+ parameters are not included, so a value passed as `?` or `$1` cannot leak.
35
+
36
+ ## The adapter throws?
37
+
38
+ It should not. `logQuery` catches sink errors and forwards them to `onError` if
39
+ provided. If an error escapes, check the Drizzle logger contract and the
40
+ `enqueueDatabaseQuery` implementation supplied through `options.transport`.
41
+
42
+ ## Verify
43
+
44
+ ```bash
45
+ stacknext status --json
46
+ stacknext coverage --json
47
+ stacknext diagnose --category database
48
+ ```
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@stacknext/drizzle",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Drizzle ORM query logging adapter for StackNext",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "files": [
8
- "dist"
8
+ "dist",
9
+ "docs"
9
10
  ],
10
11
  "main": "./dist/index.js",
11
12
  "types": "./dist/index.d.ts",
@@ -18,7 +19,7 @@
18
19
  "./package.json": "./package.json"
19
20
  },
20
21
  "dependencies": {
21
- "@stacknext/core": "0.8.0",
22
+ "@stacknext/core": "0.10.0",
22
23
  "@opentelemetry/api": "1.9.0"
23
24
  },
24
25
  "devDependencies": {