@runtime-digital-twin/sdk 1.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 +214 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +13 -0
- package/dist/db-wrapper.d.ts +258 -0
- package/dist/db-wrapper.d.ts.map +1 -0
- package/dist/db-wrapper.js +636 -0
- package/dist/event-envelope.d.ts +35 -0
- package/dist/event-envelope.d.ts.map +1 -0
- package/dist/event-envelope.js +101 -0
- package/dist/fastify-plugin.d.ts +29 -0
- package/dist/fastify-plugin.d.ts.map +1 -0
- package/dist/fastify-plugin.js +243 -0
- package/dist/http-sentinels.d.ts +39 -0
- package/dist/http-sentinels.d.ts.map +1 -0
- package/dist/http-sentinels.js +169 -0
- package/dist/http-wrapper.d.ts +25 -0
- package/dist/http-wrapper.d.ts.map +1 -0
- package/dist/http-wrapper.js +477 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/invariants.d.ts +58 -0
- package/dist/invariants.d.ts.map +1 -0
- package/dist/invariants.js +192 -0
- package/dist/multi-service-edge-builder.d.ts +80 -0
- package/dist/multi-service-edge-builder.d.ts.map +1 -0
- package/dist/multi-service-edge-builder.js +107 -0
- package/dist/outbound-matcher.d.ts +192 -0
- package/dist/outbound-matcher.d.ts.map +1 -0
- package/dist/outbound-matcher.js +457 -0
- package/dist/peer-service-resolver.d.ts +22 -0
- package/dist/peer-service-resolver.d.ts.map +1 -0
- package/dist/peer-service-resolver.js +85 -0
- package/dist/redaction.d.ts +111 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +487 -0
- package/dist/replay-logger.d.ts +438 -0
- package/dist/replay-logger.d.ts.map +1 -0
- package/dist/replay-logger.js +434 -0
- package/dist/root-cause-analyzer.d.ts +45 -0
- package/dist/root-cause-analyzer.d.ts.map +1 -0
- package/dist/root-cause-analyzer.js +606 -0
- package/dist/shape-digest-utils.d.ts +45 -0
- package/dist/shape-digest-utils.d.ts.map +1 -0
- package/dist/shape-digest-utils.js +154 -0
- package/dist/trace-bundle-writer.d.ts +52 -0
- package/dist/trace-bundle-writer.d.ts.map +1 -0
- package/dist/trace-bundle-writer.js +267 -0
- package/dist/trace-loader.d.ts +69 -0
- package/dist/trace-loader.d.ts.map +1 -0
- package/dist/trace-loader.js +146 -0
- package/dist/trace-uploader.d.ts +25 -0
- package/dist/trace-uploader.d.ts.map +1 -0
- package/dist/trace-uploader.js +132 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# @runtime-digital-twin/sdk
|
|
2
|
+
|
|
3
|
+
In-process instrumentation library for capturing runtime behavior and enabling automatic incident response.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @runtime-digital-twin/sdk
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @runtime-digital-twin/sdk
|
|
11
|
+
# or
|
|
12
|
+
yarn add @runtime-digital-twin/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Install the SDK
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @runtime-digital-twin/sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 2. Add to Your Fastify App
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import Fastify from 'fastify';
|
|
27
|
+
import { fastifyTracing } from '@runtime-digital-twin/sdk';
|
|
28
|
+
|
|
29
|
+
const fastify = Fastify();
|
|
30
|
+
|
|
31
|
+
// Register the tracing plugin
|
|
32
|
+
await fastify.register(fastifyTracing, {
|
|
33
|
+
mode: 'record', // or 'replay'
|
|
34
|
+
outputDir: './traces',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Your routes work as normal
|
|
38
|
+
fastify.get('/api/users', async (request, reply) => {
|
|
39
|
+
return { users: [] };
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await fastify.listen({ port: 3000 });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. Wrap Your Database Client
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createWrappedDbClient } from '@runtime-digital-twin/sdk';
|
|
49
|
+
import { Pool } from 'pg';
|
|
50
|
+
|
|
51
|
+
const db = await createWrappedDbClient({
|
|
52
|
+
realClient: new Pool({ connectionString: process.env.DATABASE_URL }),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Use it like a normal DB client
|
|
56
|
+
const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 4. Wrap Your HTTP Client (Optional)
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { wrapFetch } from '@runtime-digital-twin/sdk';
|
|
63
|
+
|
|
64
|
+
// Wrap global fetch
|
|
65
|
+
const wrappedFetch = wrapFetch(fetch);
|
|
66
|
+
|
|
67
|
+
// Use wrapped fetch for outbound calls
|
|
68
|
+
const response = await wrappedFetch('https://api.example.com/data');
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- ✅ **HTTP Request/Response Capture** - Automatic Fastify plugin
|
|
74
|
+
- ✅ **Database Query Capture** - Postgres wrapper with query/result recording
|
|
75
|
+
- ✅ **HTTP Client Wrapping** - Capture outbound HTTP calls
|
|
76
|
+
- ✅ **Error Capture** - Automatic error and stack trace recording
|
|
77
|
+
- ✅ **Trace Bundle Writing** - Self-contained trace format
|
|
78
|
+
- ✅ **Correlation ID Generation** - Cross-service tracing
|
|
79
|
+
- ✅ **Span Tracking** - Request/response span relationships
|
|
80
|
+
|
|
81
|
+
## Configuration
|
|
82
|
+
|
|
83
|
+
### Fastify Plugin Options
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
await fastify.register(fastifyTracing, {
|
|
87
|
+
serviceName: 'my-service', // Required: Service identifier
|
|
88
|
+
serviceVersion: '1.0.0', // Optional: Service version
|
|
89
|
+
environment: 'production', // Optional: Environment name
|
|
90
|
+
traceDir: './traces', // Optional: Where to store traces (default: './traces')
|
|
91
|
+
headerAllowlist: [], // Optional: Headers to capture
|
|
92
|
+
maxBodySize: 10 * 1024 * 1024, // Optional: Max body size to capture (default: 10MB)
|
|
93
|
+
enabled: true, // Optional: Enable/disable tracing (default: true)
|
|
94
|
+
// Upload options (optional)
|
|
95
|
+
uploadUrl: process.env.WRAITH_API_URL + '/api/traces/ingest',
|
|
96
|
+
apiKey: process.env.WRAITH_API_KEY,
|
|
97
|
+
uploadOnComplete: true, // Optional: Auto-upload after completion (default: true)
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Database Client Options
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const db = await createWrappedDbClient({
|
|
105
|
+
realClient: new Pool({ connectionString: process.env.DATABASE_URL }),
|
|
106
|
+
traceDir: './traces', // Optional: custom trace directory
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Trace Ingestion (Automatic Upload)
|
|
111
|
+
|
|
112
|
+
To automatically upload traces to your Wraith control plane:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { fastifyTracing } from '@runtime-digital-twin/sdk';
|
|
116
|
+
|
|
117
|
+
await fastify.register(fastifyTracing, {
|
|
118
|
+
serviceName: 'my-service',
|
|
119
|
+
serviceVersion: '1.0.0',
|
|
120
|
+
environment: process.env.ENVIRONMENT || 'production',
|
|
121
|
+
traceDir: './traces',
|
|
122
|
+
// Auto-upload traces after request completes
|
|
123
|
+
uploadUrl: process.env.WRAITH_API_URL
|
|
124
|
+
? `${process.env.WRAITH_API_URL}/api/traces/ingest`
|
|
125
|
+
: undefined,
|
|
126
|
+
apiKey: process.env.WRAITH_API_KEY,
|
|
127
|
+
uploadOnComplete: true, // Default: true
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Environment Variables:**
|
|
132
|
+
```bash
|
|
133
|
+
WRAITH_API_URL=https://your-wraith-app.vercel.app
|
|
134
|
+
WRAITH_API_KEY=your-api-key-here
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Traces are uploaded asynchronously after each request completes, so they don't slow down your application.
|
|
138
|
+
|
|
139
|
+
## Modes
|
|
140
|
+
|
|
141
|
+
### Record Mode
|
|
142
|
+
|
|
143
|
+
Active instrumentation that captures all runtime behavior:
|
|
144
|
+
- HTTP requests/responses
|
|
145
|
+
- Database queries and results
|
|
146
|
+
- Outbound HTTP calls
|
|
147
|
+
- Errors and stack traces
|
|
148
|
+
|
|
149
|
+
### Replay Mode
|
|
150
|
+
|
|
151
|
+
Disabled instrumentation (used during trace replay):
|
|
152
|
+
- No events written
|
|
153
|
+
- Service runs with mocked dependencies
|
|
154
|
+
- Used by replay engine for deterministic debugging
|
|
155
|
+
|
|
156
|
+
## Environment Variables
|
|
157
|
+
|
|
158
|
+
- `RDT_MODE` - Set to `record` or `replay` (default: `record`)
|
|
159
|
+
- `RDT_TRACE_DIR` - Directory for trace storage (default: `./traces`)
|
|
160
|
+
- `WRAITH_API_URL` - Control plane URL for trace ingestion
|
|
161
|
+
- `WRAITH_API_KEY` - API key for authentication
|
|
162
|
+
|
|
163
|
+
## API Reference
|
|
164
|
+
|
|
165
|
+
### Fastify Plugin
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { fastifyTracing, FastifyTracingOptions } from '@runtime-digital-twin/sdk';
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Database Wrapper
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import {
|
|
175
|
+
createWrappedDbClient,
|
|
176
|
+
wrapDbClient,
|
|
177
|
+
CreateWrappedDbClientOptions
|
|
178
|
+
} from '@runtime-digital-twin/sdk';
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### HTTP Wrapper
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { wrapFetch, setTraceContext, getTraceContext } from '@runtime-digital-twin/sdk';
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Trace Management
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import {
|
|
191
|
+
createTrace,
|
|
192
|
+
loadTraceMeta,
|
|
193
|
+
validateTraceStructure,
|
|
194
|
+
TraceBundle
|
|
195
|
+
} from '@runtime-digital-twin/sdk';
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Trace Upload
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import {
|
|
202
|
+
uploadTrace,
|
|
203
|
+
type TraceUploadOptions,
|
|
204
|
+
type TraceUploadResult
|
|
205
|
+
} from '@runtime-digital-twin/sdk';
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Examples
|
|
209
|
+
|
|
210
|
+
See the [Quickstart Guide](../../QUICKSTART.md) for complete examples.
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for the Runtime Digital Twin SDK
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Current trace format version. Increment when making breaking changes.
|
|
6
|
+
*
|
|
7
|
+
* Version history:
|
|
8
|
+
* - 1: Initial version (P0)
|
|
9
|
+
*/
|
|
10
|
+
export declare const CURRENT_TRACE_FORMAT_VERSION = 1;
|
|
11
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Constants for the Runtime Digital Twin SDK
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CURRENT_TRACE_FORMAT_VERSION = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Current trace format version. Increment when making breaking changes.
|
|
9
|
+
*
|
|
10
|
+
* Version history:
|
|
11
|
+
* - 1: Initial version (P0)
|
|
12
|
+
*/
|
|
13
|
+
exports.CURRENT_TRACE_FORMAT_VERSION = 1;
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { ReplayLogger } from "./replay-logger";
|
|
2
|
+
/**
|
|
3
|
+
* Replay modes for DB query matching
|
|
4
|
+
*/
|
|
5
|
+
export type DbReplayMode = "strict" | "explain";
|
|
6
|
+
/**
|
|
7
|
+
* Structured failure for DB query mismatch
|
|
8
|
+
*/
|
|
9
|
+
export interface DbQueryMismatch {
|
|
10
|
+
type: "db_query_mismatch";
|
|
11
|
+
location: string;
|
|
12
|
+
expected: string;
|
|
13
|
+
actual: string;
|
|
14
|
+
hint: string;
|
|
15
|
+
queryIndex: number;
|
|
16
|
+
service: string;
|
|
17
|
+
diff: {
|
|
18
|
+
field: string;
|
|
19
|
+
expected: string | null;
|
|
20
|
+
actual: string | null;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Structured failure for unexpected DB query (query occurred but no recorded match)
|
|
25
|
+
*/
|
|
26
|
+
export interface UnexpectedDbQuery {
|
|
27
|
+
type: "unexpected_db_query";
|
|
28
|
+
location: string;
|
|
29
|
+
expected: string;
|
|
30
|
+
actual: string;
|
|
31
|
+
hint: string;
|
|
32
|
+
queryIndex: number;
|
|
33
|
+
service: string;
|
|
34
|
+
query: DbQuerySignature;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Structured failure for missing DB query (recorded query never happened)
|
|
38
|
+
*/
|
|
39
|
+
export interface MissingDbQuery {
|
|
40
|
+
type: "missing_db_query";
|
|
41
|
+
location: string;
|
|
42
|
+
expected: string;
|
|
43
|
+
actual: string;
|
|
44
|
+
hint: string;
|
|
45
|
+
queryIndex: number;
|
|
46
|
+
service: string;
|
|
47
|
+
spanId: string;
|
|
48
|
+
recordedQuery: RecordedDbQuery;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Structured failure for blocked live DB access
|
|
52
|
+
*/
|
|
53
|
+
export interface BlockedDbAccess {
|
|
54
|
+
type: "blocked_db_access";
|
|
55
|
+
location: string;
|
|
56
|
+
expected: string;
|
|
57
|
+
actual: string;
|
|
58
|
+
hint: string;
|
|
59
|
+
query: DbQuerySignature;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Union type for all DB query failures
|
|
63
|
+
*/
|
|
64
|
+
export type DbQueryFailure = DbQueryMismatch | UnexpectedDbQuery | MissingDbQuery | BlockedDbAccess;
|
|
65
|
+
/**
|
|
66
|
+
* Divergence event for DB queries
|
|
67
|
+
*/
|
|
68
|
+
export interface DbQueryDivergence {
|
|
69
|
+
type: "divergence";
|
|
70
|
+
severity: "warning" | "error";
|
|
71
|
+
queryIndex: number;
|
|
72
|
+
message: string;
|
|
73
|
+
expected: RecordedDbQuery | null;
|
|
74
|
+
actual: DbQuerySignature;
|
|
75
|
+
recoverable: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Recorded DB query from trace
|
|
79
|
+
*/
|
|
80
|
+
export interface RecordedDbQuery {
|
|
81
|
+
spanId: string;
|
|
82
|
+
operation: string;
|
|
83
|
+
sql: string;
|
|
84
|
+
normalizedSql: string;
|
|
85
|
+
params: unknown[];
|
|
86
|
+
paramsHash: string;
|
|
87
|
+
result: {
|
|
88
|
+
rows: unknown[];
|
|
89
|
+
rowCount: number;
|
|
90
|
+
resultHash: string | null;
|
|
91
|
+
resultBlob: string | null;
|
|
92
|
+
};
|
|
93
|
+
durationMs: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Signature used to match a DB query
|
|
97
|
+
*/
|
|
98
|
+
export interface DbQuerySignature {
|
|
99
|
+
sql: string;
|
|
100
|
+
params: unknown[];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Normalize SQL for matching: lowercase, trim whitespace, normalize spaces
|
|
104
|
+
*/
|
|
105
|
+
export declare function normalizeSql(sql: string): string;
|
|
106
|
+
/**
|
|
107
|
+
* Compute hash of query parameters
|
|
108
|
+
*/
|
|
109
|
+
export declare function computeParamsHash(params: unknown[]): string;
|
|
110
|
+
/**
|
|
111
|
+
* Extract operation type from SQL
|
|
112
|
+
*/
|
|
113
|
+
export declare function extractOperation(sql: string): string;
|
|
114
|
+
/**
|
|
115
|
+
* Compare two queries and return differences
|
|
116
|
+
*/
|
|
117
|
+
export declare function compareDbQueries(expected: RecordedDbQuery, actual: DbQuerySignature): {
|
|
118
|
+
matches: boolean;
|
|
119
|
+
diffs: {
|
|
120
|
+
field: string;
|
|
121
|
+
expected: string | null;
|
|
122
|
+
actual: string | null;
|
|
123
|
+
}[];
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Ordered DB query matcher for replay
|
|
127
|
+
*/
|
|
128
|
+
export declare class DbQueryMatcher {
|
|
129
|
+
private recordedQueries;
|
|
130
|
+
private currentIndex;
|
|
131
|
+
private mode;
|
|
132
|
+
private traceDir;
|
|
133
|
+
private divergences;
|
|
134
|
+
private logger;
|
|
135
|
+
constructor(recordedQueries: RecordedDbQuery[], mode: DbReplayMode, traceDir: string, logger?: ReplayLogger);
|
|
136
|
+
/**
|
|
137
|
+
* Set the logger for structured replay logging
|
|
138
|
+
*/
|
|
139
|
+
setLogger(logger: ReplayLogger): void;
|
|
140
|
+
/**
|
|
141
|
+
* Get all recorded divergences
|
|
142
|
+
*/
|
|
143
|
+
getDivergences(): DbQueryDivergence[];
|
|
144
|
+
/**
|
|
145
|
+
* Get current query index
|
|
146
|
+
*/
|
|
147
|
+
getCurrentIndex(): number;
|
|
148
|
+
/**
|
|
149
|
+
* Get total recorded queries
|
|
150
|
+
*/
|
|
151
|
+
getTotalQueries(): number;
|
|
152
|
+
/**
|
|
153
|
+
* Check if only SELECT queries are in the recorded set
|
|
154
|
+
*/
|
|
155
|
+
isReadOnly(): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Match the next DB query against the recorded sequence
|
|
158
|
+
*
|
|
159
|
+
* In strict mode: throws DbQueryMismatch on any mismatch
|
|
160
|
+
* In explain mode: emits divergence and returns best-effort match
|
|
161
|
+
*/
|
|
162
|
+
matchNext(actual: DbQuerySignature): RecordedDbQuery;
|
|
163
|
+
/**
|
|
164
|
+
* Check if all recorded queries have been matched
|
|
165
|
+
*/
|
|
166
|
+
isComplete(): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Get summary of unmatched queries
|
|
169
|
+
*/
|
|
170
|
+
getUnmatchedQueries(): RecordedDbQuery[];
|
|
171
|
+
/**
|
|
172
|
+
* Finalize replay and check for missing DB queries
|
|
173
|
+
*/
|
|
174
|
+
finalize(): MissingDbQuery[];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Parse recorded DB queries from trace events
|
|
178
|
+
*/
|
|
179
|
+
export declare function parseRecordedDbQueries(events: unknown[]): RecordedDbQuery[];
|
|
180
|
+
/**
|
|
181
|
+
* Generic DB client interface for wrapping
|
|
182
|
+
*/
|
|
183
|
+
export interface DbClient {
|
|
184
|
+
query(sql: string, params?: unknown[]): Promise<{
|
|
185
|
+
rows: unknown[];
|
|
186
|
+
rowCount: number;
|
|
187
|
+
}>;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Wrapped DB client for recording/replay
|
|
191
|
+
*/
|
|
192
|
+
export interface WrappedDbClient extends DbClient {
|
|
193
|
+
getQueryCount(): number;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Options for wrapping a DB client
|
|
197
|
+
*/
|
|
198
|
+
export interface WrapDbClientOptions {
|
|
199
|
+
mode: "record" | "replay";
|
|
200
|
+
matcher?: DbQueryMatcher;
|
|
201
|
+
readBlob?: (blobRef: string) => Promise<unknown[] | null>;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Wrap a DB client for recording or replay
|
|
205
|
+
*
|
|
206
|
+
* During recording: captures queries and results
|
|
207
|
+
* During replay: returns recorded results, blocks live DB access
|
|
208
|
+
*/
|
|
209
|
+
export declare function wrapDbClient(client: DbClient | null, options: WrapDbClientOptions): WrappedDbClient;
|
|
210
|
+
/**
|
|
211
|
+
* Format DbQueryMismatch for CLI output
|
|
212
|
+
*/
|
|
213
|
+
export declare function formatDbQueryMismatch(failure: DbQueryMismatch): string;
|
|
214
|
+
/**
|
|
215
|
+
* Format UnexpectedDbQuery for CLI output
|
|
216
|
+
*/
|
|
217
|
+
export declare function formatUnexpectedDbQuery(failure: UnexpectedDbQuery): string;
|
|
218
|
+
/**
|
|
219
|
+
* Format MissingDbQuery for CLI output
|
|
220
|
+
*/
|
|
221
|
+
export declare function formatMissingDbQuery(failure: MissingDbQuery): string;
|
|
222
|
+
/**
|
|
223
|
+
* Format BlockedDbAccess for CLI output
|
|
224
|
+
*/
|
|
225
|
+
export declare function formatBlockedDbAccess(failure: BlockedDbAccess): string;
|
|
226
|
+
/**
|
|
227
|
+
* Format any DB query failure for CLI output
|
|
228
|
+
*/
|
|
229
|
+
export declare function formatDbQueryFailure(failure: DbQueryFailure): string;
|
|
230
|
+
/**
|
|
231
|
+
* Auto-detect replay mode and create a wrapped DB client
|
|
232
|
+
*
|
|
233
|
+
* This helper function automatically:
|
|
234
|
+
* 1. Detects if we're in replay mode (via RDT_MODE or RDT_REPLAY env vars)
|
|
235
|
+
* 2. In replay mode: loads trace events and creates a matcher
|
|
236
|
+
* 3. In record mode: wraps the provided real DB client
|
|
237
|
+
*
|
|
238
|
+
* Usage:
|
|
239
|
+
* ```typescript
|
|
240
|
+
* const db = await createWrappedDbClient({
|
|
241
|
+
* realClient: new Pool({ connectionString: process.env.DATABASE_URL }),
|
|
242
|
+
* // Optional: provide custom trace dir (defaults to RDT_TRACE_DIR)
|
|
243
|
+
* traceDir: process.env.RDT_TRACE_DIR,
|
|
244
|
+
* });
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
export interface CreateWrappedDbClientOptions {
|
|
248
|
+
/** Real DB client to use in record mode (required for record mode) */
|
|
249
|
+
realClient?: DbClient | null;
|
|
250
|
+
/** Trace directory (defaults to RDT_TRACE_DIR env var) */
|
|
251
|
+
traceDir?: string;
|
|
252
|
+
/** Replay mode: "strict" or "explain" (defaults to RDT_REPLAY_MODE env var or "strict") */
|
|
253
|
+
replayMode?: DbReplayMode;
|
|
254
|
+
/** Custom blob reader (defaults to reading from traceDir/blobs/) */
|
|
255
|
+
readBlob?: (blobRef: string) => Promise<unknown[] | null>;
|
|
256
|
+
}
|
|
257
|
+
export declare function createWrappedDbClient(options?: CreateWrappedDbClientOptions): Promise<WrappedDbClient | null>;
|
|
258
|
+
//# sourceMappingURL=db-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-wrapper.d.ts","sourceRoot":"","sources":["../src/db-wrapper.ts"],"names":[],"mappings":"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"}
|