@getvision/server 0.0.1 → 0.1.0-5d94ff9-develop
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/.turbo/turbo-build.log +1 -2
- package/package.json +4 -4
- package/src/service.ts +36 -17
- package/src/types.ts +18 -6
- package/src/vision-app.ts +18 -13
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
[0m[2m[35m$[0m [2m[1mtsc --noEmit[0m
|
|
1
|
+
$ tsc --noEmit
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getvision/server",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0-5d94ff9-develop",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vision Server - Meta-framework with built-in observability, pub/sub, and type-safe APIs",
|
|
6
6
|
"exports": {
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"@getvision/core": "0.0.1",
|
|
17
17
|
"@hono/node-server": "^1.19.5",
|
|
18
18
|
"bullmq": "^5.62.0",
|
|
19
|
-
"hono": "^4.10.
|
|
19
|
+
"hono": "^4.10.4",
|
|
20
20
|
"ioredis": "^5.8.2",
|
|
21
21
|
"zod": "^4.1.11"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@repo/eslint-config": "0.0.
|
|
26
|
-
"@repo/typescript-config": "0.0.
|
|
25
|
+
"@repo/eslint-config": "0.0.1",
|
|
26
|
+
"@repo/typescript-config": "0.0.1",
|
|
27
27
|
"@types/node": "^20.14.9",
|
|
28
28
|
"typescript": "5.9.3"
|
|
29
29
|
},
|
package/src/service.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Hono, Context, MiddlewareHandler } from 'hono'
|
|
1
|
+
import type { Hono, Context, MiddlewareHandler, Env, Input } from 'hono'
|
|
2
2
|
import type { z } from 'zod'
|
|
3
3
|
import { VisionCore, generateZodTemplate } from '@getvision/core'
|
|
4
|
-
import type { EndpointConfig, Handler
|
|
4
|
+
import type { EndpointConfig, Handler } from './types'
|
|
5
5
|
import { getVisionContext } from './vision-app'
|
|
6
6
|
import { eventRegistry } from './event-registry'
|
|
7
7
|
import type { EventBus } from './event-bus'
|
|
@@ -29,11 +29,15 @@ type EventSchemaMap = Record<string, z.ZodSchema<any>>
|
|
|
29
29
|
* })
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
|
-
export class ServiceBuilder<
|
|
32
|
+
export class ServiceBuilder<
|
|
33
|
+
TEvents extends EventSchemaMap = {},
|
|
34
|
+
E extends Env = Env,
|
|
35
|
+
I extends Input = {}
|
|
36
|
+
> {
|
|
33
37
|
private endpoints: Map<string, any> = new Map()
|
|
34
38
|
private eventHandlers: Map<string, any> = new Map()
|
|
35
39
|
private cronJobs: Map<string, any> = new Map()
|
|
36
|
-
private globalMiddleware: MiddlewareHandler[] = []
|
|
40
|
+
private globalMiddleware: MiddlewareHandler<E, string, any, any>[] = []
|
|
37
41
|
private eventSchemas: EventSchemaMap = {}
|
|
38
42
|
|
|
39
43
|
constructor(
|
|
@@ -45,7 +49,7 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
45
49
|
/**
|
|
46
50
|
* Add global middleware for all endpoints in this service
|
|
47
51
|
*/
|
|
48
|
-
use(...middleware: MiddlewareHandler[]) {
|
|
52
|
+
use(...middleware: MiddlewareHandler<E, string, any, any>[]) {
|
|
49
53
|
this.globalMiddleware.push(...middleware)
|
|
50
54
|
return this
|
|
51
55
|
}
|
|
@@ -109,15 +113,23 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
109
113
|
*/
|
|
110
114
|
endpoint<
|
|
111
115
|
TInputSchema extends z.ZodType,
|
|
112
|
-
TOutputSchema extends z.ZodType
|
|
116
|
+
TOutputSchema extends z.ZodType | undefined,
|
|
117
|
+
PPath extends string
|
|
113
118
|
>(
|
|
114
119
|
method: EndpointConfig['method'],
|
|
115
|
-
path:
|
|
120
|
+
path: PPath,
|
|
116
121
|
schema: {
|
|
117
122
|
input: TInputSchema
|
|
118
|
-
output
|
|
123
|
+
output?: TOutputSchema
|
|
119
124
|
},
|
|
120
|
-
handler: Handler<
|
|
125
|
+
handler: Handler<
|
|
126
|
+
z.infer<TInputSchema>,
|
|
127
|
+
TOutputSchema extends z.ZodType ? z.infer<TOutputSchema> : any,
|
|
128
|
+
TEvents,
|
|
129
|
+
E,
|
|
130
|
+
PPath,
|
|
131
|
+
I
|
|
132
|
+
>,
|
|
121
133
|
config?: Partial<EndpointConfig>
|
|
122
134
|
) {
|
|
123
135
|
this.endpoints.set(`${method}:${path}`, {
|
|
@@ -166,7 +178,7 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
166
178
|
tags?: string[]
|
|
167
179
|
handler: (event: T) => Promise<void>
|
|
168
180
|
}
|
|
169
|
-
): ServiceBuilder<TEvents & { [key in K]: T }> {
|
|
181
|
+
): ServiceBuilder<TEvents & { [key in K]: T }, E, I> {
|
|
170
182
|
const { schema, handler, description, icon, tags } = config
|
|
171
183
|
|
|
172
184
|
// Store schema for type inference
|
|
@@ -187,7 +199,7 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
187
199
|
this.eventHandlers.set(eventName, config)
|
|
188
200
|
|
|
189
201
|
// Return typed ServiceBuilder with accumulated events
|
|
190
|
-
return this as ServiceBuilder<TEvents & { [key in K]: T }>
|
|
202
|
+
return this as ServiceBuilder<TEvents & { [key in K]: T }, E, I>
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
/**
|
|
@@ -307,7 +319,7 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
307
319
|
const allMiddleware = [...this.globalMiddleware, ...ep.middleware]
|
|
308
320
|
|
|
309
321
|
// Create handler with middleware chain
|
|
310
|
-
const finalHandler = async (c: Context) => {
|
|
322
|
+
const finalHandler = async (c: Context<E, any, I>) => {
|
|
311
323
|
try {
|
|
312
324
|
// Add span helper and emit to context
|
|
313
325
|
const visionCtx = getVisionContext()
|
|
@@ -378,11 +390,18 @@ export class ServiceBuilder<TEvents extends EventSchemaMap = {}> {
|
|
|
378
390
|
|
|
379
391
|
// Execute handler
|
|
380
392
|
const result = await ep.handler(validated, c as any)
|
|
381
|
-
|
|
382
|
-
//
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
393
|
+
|
|
394
|
+
// If an output schema exists, validate and return JSON
|
|
395
|
+
if (ep.schema.output) {
|
|
396
|
+
const validatedOutput = ep.schema.output.parse(result)
|
|
397
|
+
return c.json(validatedOutput)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// No output schema: allow raw Response or JSON
|
|
401
|
+
if (result instanceof Response) {
|
|
402
|
+
return result
|
|
403
|
+
}
|
|
404
|
+
return c.json(result)
|
|
386
405
|
} catch (error) {
|
|
387
406
|
if ((error as any).name === 'ZodError') {
|
|
388
407
|
return c.json({
|
package/src/types.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { Context, MiddlewareHandler } from 'hono'
|
|
2
|
-
import type { z } from 'zod'
|
|
1
|
+
import type { Context, Env, Input, MiddlewareHandler } from 'hono'
|
|
3
2
|
import type { VisionCore } from '@getvision/core'
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Vision context stored in AsyncLocalStorage
|
|
7
6
|
*/
|
|
8
|
-
export interface VisionContext {
|
|
7
|
+
export interface VisionContext<E extends Env = any, P extends string = any, I extends Input = {}> extends Context<E, P, I> {
|
|
9
8
|
vision: VisionCore
|
|
10
9
|
traceId: string
|
|
11
10
|
rootSpanId: string
|
|
@@ -18,6 +17,7 @@ export interface EndpointConfig {
|
|
|
18
17
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
|
19
18
|
path: string
|
|
20
19
|
middleware?: MiddlewareHandler[]
|
|
20
|
+
// TODO: Below not implemented yet features
|
|
21
21
|
auth?: boolean
|
|
22
22
|
ratelimit?: { requests: number; window: string }
|
|
23
23
|
cache?: { ttl: number }
|
|
@@ -28,7 +28,12 @@ export interface EndpointConfig {
|
|
|
28
28
|
*
|
|
29
29
|
* Generic TEvents parameter allows type-safe event emission
|
|
30
30
|
*/
|
|
31
|
-
export interface ExtendedContext<
|
|
31
|
+
export interface ExtendedContext<
|
|
32
|
+
TEvents extends Record<string, any> = {},
|
|
33
|
+
E extends Env = any,
|
|
34
|
+
P extends string = any,
|
|
35
|
+
I extends Input = {}
|
|
36
|
+
> extends Context<E, P, I> {
|
|
32
37
|
span<T>(
|
|
33
38
|
name: string,
|
|
34
39
|
attributes?: Record<string, any>,
|
|
@@ -68,7 +73,14 @@ export interface ExtendedContext<TEvents extends Record<string, any> = {}> exten
|
|
|
68
73
|
/**
|
|
69
74
|
* Handler type with Zod-validated input and Vision-enhanced context
|
|
70
75
|
*/
|
|
71
|
-
export type Handler<
|
|
76
|
+
export type Handler<
|
|
77
|
+
TInput = any,
|
|
78
|
+
TOutput = any,
|
|
79
|
+
TEvents extends Record<string, any> = {},
|
|
80
|
+
E extends Env = any,
|
|
81
|
+
P extends string = any,
|
|
82
|
+
I extends Input = {}
|
|
83
|
+
> = (
|
|
72
84
|
req: TInput,
|
|
73
|
-
ctx: ExtendedContext<TEvents>
|
|
85
|
+
ctx: ExtendedContext<TEvents, E, P, I>
|
|
74
86
|
) => Promise<TOutput> | TOutput
|
package/src/vision-app.ts
CHANGED
|
@@ -6,11 +6,16 @@ import { AsyncLocalStorage } from 'async_hooks'
|
|
|
6
6
|
import { existsSync } from 'fs'
|
|
7
7
|
import { spawn, type ChildProcess } from 'child_process'
|
|
8
8
|
import { ServiceBuilder } from './service'
|
|
9
|
-
import type { VisionContext } from './types'
|
|
10
9
|
import { EventBus } from './event-bus'
|
|
11
10
|
import { eventRegistry } from './event-registry'
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
export interface VisionALSContext {
|
|
13
|
+
vision: VisionCore
|
|
14
|
+
traceId: string
|
|
15
|
+
rootSpanId: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const visionContext = new AsyncLocalStorage<VisionALSContext>()
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Vision Server configuration
|
|
@@ -81,7 +86,7 @@ export class Vision<
|
|
|
81
86
|
private visionCore: VisionCore
|
|
82
87
|
private eventBus: EventBus
|
|
83
88
|
private config: VisionConfig
|
|
84
|
-
private serviceBuilders: ServiceBuilder<any>[] = []
|
|
89
|
+
private serviceBuilders: ServiceBuilder<any, E>[] = []
|
|
85
90
|
private fileBasedRoutes: RouteMetadata[] = []
|
|
86
91
|
|
|
87
92
|
constructor(config?: VisionConfig) {
|
|
@@ -253,11 +258,11 @@ export class Vision<
|
|
|
253
258
|
|
|
254
259
|
// Run request in AsyncLocalStorage context
|
|
255
260
|
return visionContext.run(
|
|
256
|
-
{
|
|
257
|
-
vision: this.visionCore,
|
|
258
|
-
traceId: trace.id,
|
|
259
|
-
rootSpanId: ''
|
|
260
|
-
},
|
|
261
|
+
{
|
|
262
|
+
vision: this.visionCore,
|
|
263
|
+
traceId: trace.id,
|
|
264
|
+
rootSpanId: ''
|
|
265
|
+
},
|
|
261
266
|
async () => {
|
|
262
267
|
// Start main span
|
|
263
268
|
const tracer = this.visionCore.getTracer()
|
|
@@ -427,11 +432,11 @@ export class Vision<
|
|
|
427
432
|
* .on('user/created', handler)
|
|
428
433
|
* ```
|
|
429
434
|
*/
|
|
430
|
-
service<TEvents extends Record<string, any> = {}>(name: string) {
|
|
431
|
-
const builder = new ServiceBuilder<TEvents>(name, this.eventBus, this.visionCore)
|
|
435
|
+
service<E2 extends Env = E, TEvents extends Record<string, any> = {}>(name: string) {
|
|
436
|
+
const builder = new ServiceBuilder<TEvents, E2>(name, this.eventBus, this.visionCore)
|
|
432
437
|
|
|
433
|
-
//
|
|
434
|
-
this.serviceBuilders.push(builder)
|
|
438
|
+
// Preserve builder for registration in start()
|
|
439
|
+
this.serviceBuilders.push(builder as unknown as ServiceBuilder<any, E>)
|
|
435
440
|
|
|
436
441
|
return builder
|
|
437
442
|
}
|
|
@@ -610,7 +615,7 @@ export class Vision<
|
|
|
610
615
|
/**
|
|
611
616
|
* Get Vision context (internal use)
|
|
612
617
|
*/
|
|
613
|
-
export function getVisionContext():
|
|
618
|
+
export function getVisionContext(): VisionALSContext | undefined {
|
|
614
619
|
return visionContext.getStore()
|
|
615
620
|
}
|
|
616
621
|
|