@getvision/adapter-express 0.0.0-develop-20251031183955
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/.eslintrc.js +9 -0
- package/.turbo/turbo-build.log +1 -0
- package/README.md +266 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +435 -0
- package/dist/zod-utils.d.ts +7 -0
- package/dist/zod-utils.d.ts.map +1 -0
- package/dist/zod-utils.js +145 -0
- package/dist/zod-validator.d.ts +44 -0
- package/dist/zod-validator.d.ts.map +1 -0
- package/dist/zod-validator.js +98 -0
- package/package.json +30 -0
- package/src/index.ts +529 -0
- package/src/zod-utils.ts +170 -0
- package/src/zod-validator.ts +118 -0
- package/tsconfig.json +13 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ tsc
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# @getvision/adapter-express
|
|
2
|
+
|
|
3
|
+
Express.js adapter for Vision Dashboard.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @getvision/adapter-express
|
|
9
|
+
# or
|
|
10
|
+
npm install @getvision/adapter-express
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import express from 'express'
|
|
17
|
+
import { visionMiddleware, enableAutoDiscovery, zValidator } from '@getvision/adapter-express'
|
|
18
|
+
import { z } from 'zod'
|
|
19
|
+
|
|
20
|
+
const app = express()
|
|
21
|
+
|
|
22
|
+
// Add Vision middleware (development only)
|
|
23
|
+
if (process.env.NODE_ENV === 'development') {
|
|
24
|
+
app.use(visionMiddleware({ port: 9500 }))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// JSON parser
|
|
28
|
+
app.use(express.json())
|
|
29
|
+
|
|
30
|
+
// Your routes
|
|
31
|
+
app.get('/users', (req, res) => {
|
|
32
|
+
res.json({ users: [] })
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// Zod validation (typed + auto-documented in Vision)
|
|
36
|
+
const createUser = z.object({
|
|
37
|
+
name: z.string().min(1).describe('Full name'),
|
|
38
|
+
email: z.string().email().describe('Email'),
|
|
39
|
+
age: z.number().int().positive().optional().describe('Age (optional)'),
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
app.post('/users', zValidator('body', createUser), (req, res) => {
|
|
43
|
+
res.status(201).json(req.body)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// Enable auto-discovery after routes
|
|
47
|
+
if (process.env.NODE_ENV === 'development') {
|
|
48
|
+
// Auto-group routes by first path segment (Users, Root, etc.)
|
|
49
|
+
enableAutoDiscovery(app)
|
|
50
|
+
|
|
51
|
+
// Or provide manual services grouping with glob-like patterns
|
|
52
|
+
// e.g. `/users/*` → "Users" service
|
|
53
|
+
// `/auth/*` → "Auth" service
|
|
54
|
+
// Unmatched → "Uncategorized"
|
|
55
|
+
//
|
|
56
|
+
// enableAutoDiscovery(app, { services: [
|
|
57
|
+
// { name: 'Users', description: 'User management', routes: ['/users/*'] },
|
|
58
|
+
// { name: 'Auth', routes: ['/auth/*'] }
|
|
59
|
+
// ]})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
app.listen(3000)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Visit `http://localhost:9500` to see the dashboard! 🎉
|
|
66
|
+
|
|
67
|
+
## Features
|
|
68
|
+
|
|
69
|
+
### Automatic Request Tracing
|
|
70
|
+
Every request is automatically traced with:
|
|
71
|
+
- HTTP method, path, query params
|
|
72
|
+
- Request/response headers and body (captured before/after send)
|
|
73
|
+
- Status code and duration
|
|
74
|
+
- Response capture
|
|
75
|
+
- Root `http.request` span with child spans (DB, etc.)
|
|
76
|
+
|
|
77
|
+
### Custom Spans
|
|
78
|
+
Track operations within requests:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { useVisionSpan } from '@getvision/adapter-express'
|
|
82
|
+
|
|
83
|
+
app.get('/users', async (req, res) => {
|
|
84
|
+
const withSpan = useVisionSpan()
|
|
85
|
+
|
|
86
|
+
const users = withSpan('db.query', {
|
|
87
|
+
'db.system': 'postgresql',
|
|
88
|
+
'db.table': 'users'
|
|
89
|
+
}, () => {
|
|
90
|
+
return db.select().from(users).all()
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
res.json({ users })
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Auto-Discovery (Services Catalog)
|
|
98
|
+
Automatically discover all routes:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
enableAutoDiscovery(app)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This will register all routes with Vision for the service catalog.
|
|
105
|
+
|
|
106
|
+
## API
|
|
107
|
+
|
|
108
|
+
### `visionMiddleware(options?)`
|
|
109
|
+
|
|
110
|
+
Express middleware for Vision.
|
|
111
|
+
|
|
112
|
+
**Options:**
|
|
113
|
+
```typescript
|
|
114
|
+
interface VisionExpressOptions {
|
|
115
|
+
port?: number // Dashboard port (default: 9500)
|
|
116
|
+
enabled?: boolean // Enable Vision (default: true)
|
|
117
|
+
maxTraces?: number // Max traces to store (default: 1000)
|
|
118
|
+
maxLogs?: number // Max logs to store (default: 10000)
|
|
119
|
+
logging?: boolean // Console logging (default: true)
|
|
120
|
+
cors?: boolean // Auto CORS for dashboard (default: true)
|
|
121
|
+
service?: {
|
|
122
|
+
name?: string // Service name
|
|
123
|
+
version?: string // Service version
|
|
124
|
+
description?: string // Service description
|
|
125
|
+
integrations?: {
|
|
126
|
+
database?: string // Database connection
|
|
127
|
+
redis?: string // Redis connection
|
|
128
|
+
[key: string]: string | undefined
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### `enableAutoDiscovery(app, options?)`
|
|
135
|
+
|
|
136
|
+
Enable automatic route discovery for Express app.
|
|
137
|
+
|
|
138
|
+
**Note:** Call this after all routes are defined.
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
type ServiceDefinition = {
|
|
142
|
+
name: string
|
|
143
|
+
description?: string
|
|
144
|
+
routes: string[] // e.g. ['/users/*']
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
enableAutoDiscovery(app, {
|
|
148
|
+
services: [
|
|
149
|
+
{ name: 'Users', routes: ['/users/*'] },
|
|
150
|
+
]
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `useVisionSpan()`
|
|
155
|
+
|
|
156
|
+
Get span helper for current request. Child spans are automatically parented to the root `http.request` span for the current request.
|
|
157
|
+
|
|
158
|
+
**Returns:** `(name, attributes, fn) => result`
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const withSpan = useVisionSpan()
|
|
162
|
+
|
|
163
|
+
const result = withSpan('operation.name', {
|
|
164
|
+
'attr.key': 'value'
|
|
165
|
+
}, () => {
|
|
166
|
+
// Your operation
|
|
167
|
+
return result
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `getVisionContext()`
|
|
172
|
+
|
|
173
|
+
Get current Vision context.
|
|
174
|
+
|
|
175
|
+
**Returns:** `{ vision: VisionCore, traceId: string, rootSpanId: string }`
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { getVisionContext } from '@getvision/adapter-express'
|
|
179
|
+
|
|
180
|
+
app.get('/debug', (req, res) => {
|
|
181
|
+
const { vision, traceId } = getVisionContext()
|
|
182
|
+
res.json({ traceId })
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `getVisionInstance()`
|
|
187
|
+
|
|
188
|
+
Get the global Vision instance.
|
|
189
|
+
|
|
190
|
+
**Returns:** `VisionCore | null`
|
|
191
|
+
|
|
192
|
+
## Environment Variables
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
VISION_ENABLED=true # Enable/disable Vision
|
|
196
|
+
VISION_PORT=9500 # Dashboard port
|
|
197
|
+
NODE_ENV=development # Environment
|
|
198
|
+
|
|
199
|
+
# CORS notes
|
|
200
|
+
# Dashboard adds/needs headers: X-Vision-Trace-Id, X-Vision-Session
|
|
201
|
+
# The middleware auto-sets:
|
|
202
|
+
# Access-Control-Allow-Origin: *
|
|
203
|
+
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
|
|
204
|
+
# Access-Control-Allow-Headers: Content-Type, Authorization, X-Vision-Trace-Id, X-Vision-Session
|
|
205
|
+
# Access-Control-Expose-Headers: X-Vision-Trace-Id, X-Vision-Session
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Example
|
|
209
|
+
|
|
210
|
+
See [examples/express-basic](../../examples/express) for a complete example.
|
|
211
|
+
|
|
212
|
+
## Integration with ORMs
|
|
213
|
+
|
|
214
|
+
### Prisma
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
app.get('/users', async (req, res) => {
|
|
218
|
+
const withSpan = useVisionSpan()
|
|
219
|
+
|
|
220
|
+
const users = await withSpan('db.query', {
|
|
221
|
+
'db.system': 'postgresql',
|
|
222
|
+
'db.operation': 'findMany'
|
|
223
|
+
}, async () => {
|
|
224
|
+
return await prisma.user.findMany()
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
res.json({ users })
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### TypeORM
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
app.get('/users', async (req, res) => {
|
|
235
|
+
const withSpan = useVisionSpan()
|
|
236
|
+
|
|
237
|
+
const users = await withSpan('db.query', {
|
|
238
|
+
'db.system': 'postgresql',
|
|
239
|
+
'db.table': 'users'
|
|
240
|
+
}, async () => {
|
|
241
|
+
return await userRepository.find()
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
res.json({ users })
|
|
245
|
+
})
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## TypeScript
|
|
249
|
+
|
|
250
|
+
Full TypeScript support included.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import type { VisionExpressOptions } from '@getvision/adapter-express'
|
|
254
|
+
|
|
255
|
+
const options: VisionExpressOptions = {
|
|
256
|
+
port: 9500,
|
|
257
|
+
service: {
|
|
258
|
+
name: 'my-api',
|
|
259
|
+
version: '1.0.0'
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction, Application } from 'express';
|
|
2
|
+
import { VisionCore } from '@getvision/core';
|
|
3
|
+
import type { VisionExpressOptions, ServiceDefinition } from '@getvision/core';
|
|
4
|
+
interface VisionContext {
|
|
5
|
+
vision: VisionCore;
|
|
6
|
+
traceId: string;
|
|
7
|
+
rootSpanId: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get current vision context (vision instance and traceId)
|
|
11
|
+
* Available in route handlers when using visionMiddleware
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* app.get('/users', (req, res) => {
|
|
16
|
+
* const { vision, traceId } = getVisionContext()
|
|
17
|
+
* // ...
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function getVisionContext(): VisionContext;
|
|
22
|
+
/**
|
|
23
|
+
* Create span helper using current trace context
|
|
24
|
+
* Child spans will be nested under the root http.request span
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* app.get('/users', async (req, res) => {
|
|
29
|
+
* const withSpan = useVisionSpan()
|
|
30
|
+
*
|
|
31
|
+
* const users = withSpan('db.select', { 'db.table': 'users' }, () => {
|
|
32
|
+
* return db.select().from(users).all()
|
|
33
|
+
* })
|
|
34
|
+
* })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function useVisionSpan(): <T>(name: string, attributes: Record<string, any> | undefined, fn: () => T) => T;
|
|
38
|
+
/**
|
|
39
|
+
* Express middleware for Vision Dashboard
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import express from 'express'
|
|
44
|
+
* import { visionMiddleware } from '@getvision/adapter-express'
|
|
45
|
+
*
|
|
46
|
+
* const app = express()
|
|
47
|
+
*
|
|
48
|
+
* if (process.env.NODE_ENV === 'development') {
|
|
49
|
+
* app.use(visionMiddleware({ port: 9500 }))
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* app.get('/hello', (req, res) => {
|
|
53
|
+
* res.json({ message: 'Hello!' })
|
|
54
|
+
* })
|
|
55
|
+
*
|
|
56
|
+
* app.listen(3000)
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function visionMiddleware(options?: VisionExpressOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Enable automatic route discovery for Express app
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const app = express()
|
|
66
|
+
* app.use(visionMiddleware())
|
|
67
|
+
*
|
|
68
|
+
* // Define routes...
|
|
69
|
+
* app.get('/users', handler)
|
|
70
|
+
* app.post('/users', handler)
|
|
71
|
+
*
|
|
72
|
+
* // Enable auto-discovery after all routes defined
|
|
73
|
+
* enableAutoDiscovery(app)
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function enableAutoDiscovery(app: Application, options?: {
|
|
77
|
+
services?: ServiceDefinition[];
|
|
78
|
+
}): void;
|
|
79
|
+
/**
|
|
80
|
+
* Get the current Vision instance
|
|
81
|
+
*/
|
|
82
|
+
export declare function getVisionInstance(): VisionCore | null;
|
|
83
|
+
export { zValidator, getRouteSchema, getAllRouteSchemas } from './zod-validator';
|
|
84
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC3E,OAAO,EACL,UAAU,EAGX,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAiB,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAK7F,UAAU,aAAa;IACrB,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAMhD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,KAInB,CAAC,EACP,MAAM,MAAM,EACZ,YAAY,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,YAAK,EACpC,IAAI,MAAM,CAAC,KACV,CAAC,CAqCL;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,SAIlD,OAAO,OAAO,QAAQ,QAAQ,YAAY,UA8L1D;AAuFD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAAE,GAAG,IAAI,CA+FxG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,GAAG,IAAI,CAErD;AAGD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
|