@getvision/server 0.4.3-d4c761e-develop → 0.4.4-44d79d9-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/CHANGELOG.md +8 -0
- package/dist/event-bus.d.ts +87 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +265 -0
- package/dist/event-bus.js.map +10 -0
- package/dist/event-registry.d.ts +79 -0
- package/dist/event-registry.d.ts.map +1 -0
- package/dist/event-registry.js +93 -0
- package/dist/event-registry.js.map +10 -0
- package/{src/index.ts → dist/index.d.ts} +14 -28
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +10 -0
- package/dist/router.d.ts +16 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +117 -0
- package/dist/router.js.map +10 -0
- package/dist/service.d.ts +151 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +341 -0
- package/dist/service.js.map +10 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +9 -0
- package/dist/vision-app.d.ts +166 -0
- package/dist/vision-app.d.ts.map +1 -0
- package/dist/vision-app.js +611 -0
- package/dist/vision-app.js.map +10 -0
- package/dist/vision.d.ts +63 -0
- package/dist/vision.d.ts.map +1 -0
- package/dist/vision.js +223 -0
- package/dist/vision.js.map +10 -0
- package/package.json +13 -3
- package/.env.example +0 -3
- package/.eslintrc.cjs +0 -7
- package/.turbo/turbo-build.log +0 -1
- package/src/event-bus.ts +0 -409
- package/src/event-registry.ts +0 -158
- package/src/router.ts +0 -118
- package/src/service.ts +0 -618
- package/src/types.ts +0 -93
- package/src/vision-app.ts +0 -880
- package/src/vision.ts +0 -319
- package/tsconfig.json +0 -9
package/dist/service.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
// src/service.ts
|
|
21
|
+
import { generateTemplate } from "@getvision/core";
|
|
22
|
+
import {
|
|
23
|
+
ValidationError,
|
|
24
|
+
createValidationErrorResponse,
|
|
25
|
+
UniversalValidator
|
|
26
|
+
} from "@getvision/core";
|
|
27
|
+
import { getVisionContext } from "./vision-app";
|
|
28
|
+
import { eventRegistry } from "./event-registry";
|
|
29
|
+
import { rateLimiter } from "hono-rate-limiter";
|
|
30
|
+
function parseWindowMs(window) {
|
|
31
|
+
const trimmed = window.trim();
|
|
32
|
+
if (/^\d+$/.test(trimmed))
|
|
33
|
+
return Number(trimmed);
|
|
34
|
+
const match = trimmed.match(/^(\d+)\s*([smhd])$/i);
|
|
35
|
+
if (!match)
|
|
36
|
+
throw new Error(`Invalid ratelimit window: ${window}`);
|
|
37
|
+
const value = Number(match[1]);
|
|
38
|
+
const unit = match[2].toLowerCase();
|
|
39
|
+
const multipliers = { s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
40
|
+
return value * multipliers[unit];
|
|
41
|
+
}
|
|
42
|
+
function getClientKey(c, method, path) {
|
|
43
|
+
const ip = c.req.header("x-forwarded-for")?.split(",")[0].trim() || c.req.header("x-real-ip") || c.req.header("cf-connecting-ip") || c.req.header("fly-client-ip") || c.req.header("x-client-ip") || "";
|
|
44
|
+
const ua = c.req.header("user-agent") || "unknown";
|
|
45
|
+
return `${ip || ua}:${method}:${path}`;
|
|
46
|
+
}
|
|
47
|
+
function createEventContext() {
|
|
48
|
+
const store = {};
|
|
49
|
+
const mockRequest = new Request("http://localhost/event-trigger");
|
|
50
|
+
const resHeaders = new Headers;
|
|
51
|
+
const fake = {
|
|
52
|
+
get: (key) => store[key],
|
|
53
|
+
set: (key, value) => {
|
|
54
|
+
store[key] = value;
|
|
55
|
+
},
|
|
56
|
+
header: (key, value) => {
|
|
57
|
+
if (value === undefined) {
|
|
58
|
+
resHeaders.delete(key);
|
|
59
|
+
} else {
|
|
60
|
+
resHeaders.set(key, value);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
status: (code) => {},
|
|
64
|
+
req: {
|
|
65
|
+
header: (name) => name ? undefined : {},
|
|
66
|
+
param: () => ({}),
|
|
67
|
+
query: () => ({}),
|
|
68
|
+
json: async () => ({}),
|
|
69
|
+
raw: mockRequest,
|
|
70
|
+
url: "http://localhost/event-trigger",
|
|
71
|
+
method: "POST"
|
|
72
|
+
},
|
|
73
|
+
res: {
|
|
74
|
+
headers: resHeaders
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
return fake;
|
|
78
|
+
}
|
|
79
|
+
async function runMiddlewareChain(middlewares, c) {
|
|
80
|
+
let index = -1;
|
|
81
|
+
const dispatch = async (i) => {
|
|
82
|
+
if (i <= index)
|
|
83
|
+
throw new Error("next() called multiple times");
|
|
84
|
+
index = i;
|
|
85
|
+
const mw = middlewares[i];
|
|
86
|
+
if (!mw)
|
|
87
|
+
return;
|
|
88
|
+
await mw(c, () => dispatch(i + 1));
|
|
89
|
+
};
|
|
90
|
+
await dispatch(0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
class ServiceBuilder {
|
|
94
|
+
name;
|
|
95
|
+
eventBus;
|
|
96
|
+
visionCore;
|
|
97
|
+
endpoints = new Map;
|
|
98
|
+
eventHandlers = new Map;
|
|
99
|
+
cronJobs = new Map;
|
|
100
|
+
globalMiddleware = [];
|
|
101
|
+
eventSchemas = {};
|
|
102
|
+
constructor(name, eventBus, visionCore) {
|
|
103
|
+
this.name = name;
|
|
104
|
+
this.eventBus = eventBus;
|
|
105
|
+
this.visionCore = visionCore;
|
|
106
|
+
}
|
|
107
|
+
use(...middleware) {
|
|
108
|
+
this.globalMiddleware.push(...middleware);
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
getRoutesMetadata() {
|
|
112
|
+
const routes = [];
|
|
113
|
+
this.endpoints.forEach((ep) => {
|
|
114
|
+
let requestBody = undefined;
|
|
115
|
+
let queryParams = undefined;
|
|
116
|
+
if (ep.schema.input) {
|
|
117
|
+
if (["POST", "PUT", "PATCH"].includes(ep.method)) {
|
|
118
|
+
requestBody = generateTemplate(ep.schema.input);
|
|
119
|
+
} else if (ep.method === "GET" || ep.method === "DELETE") {
|
|
120
|
+
const pathParamNames = (ep.path.match(/:([^/]+)/g) || []).map((p) => p.slice(1));
|
|
121
|
+
const fullTemplate = generateTemplate(ep.schema.input);
|
|
122
|
+
if (fullTemplate && pathParamNames.length > 0) {
|
|
123
|
+
const queryFields = fullTemplate.fields.filter((f) => !pathParamNames.includes(f.name));
|
|
124
|
+
if (queryFields.length > 0) {
|
|
125
|
+
queryParams = { ...fullTemplate, fields: queryFields };
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
queryParams = fullTemplate;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
let responseBody = undefined;
|
|
133
|
+
if (ep.schema.output) {
|
|
134
|
+
responseBody = generateTemplate(ep.schema.output);
|
|
135
|
+
}
|
|
136
|
+
routes.push({
|
|
137
|
+
method: ep.method,
|
|
138
|
+
path: ep.path,
|
|
139
|
+
queryParams,
|
|
140
|
+
requestBody,
|
|
141
|
+
responseBody
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
return routes;
|
|
145
|
+
}
|
|
146
|
+
getDisplayName() {
|
|
147
|
+
return this.name.charAt(0).toUpperCase() + this.name.slice(1);
|
|
148
|
+
}
|
|
149
|
+
endpoint(method, path, schema, handler, config) {
|
|
150
|
+
this.endpoints.set(`${method}:${path}`, {
|
|
151
|
+
method,
|
|
152
|
+
path,
|
|
153
|
+
handler,
|
|
154
|
+
schema,
|
|
155
|
+
config: { ...config, method, path },
|
|
156
|
+
middleware: config?.middleware || []
|
|
157
|
+
});
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
on(eventName, config) {
|
|
161
|
+
const { schema, handler, description, icon, tags } = config;
|
|
162
|
+
this.eventSchemas[eventName] = schema;
|
|
163
|
+
const wrappedHandler = async (data) => {
|
|
164
|
+
const ctx = createEventContext();
|
|
165
|
+
if (this.globalMiddleware.length > 0) {
|
|
166
|
+
await runMiddlewareChain(this.globalMiddleware, ctx);
|
|
167
|
+
}
|
|
168
|
+
await handler(data, ctx);
|
|
169
|
+
};
|
|
170
|
+
eventRegistry.registerEvent(eventName, schema, wrappedHandler, { description, icon, tags });
|
|
171
|
+
this.eventBus.registerHandler(eventName, wrappedHandler, {
|
|
172
|
+
concurrency: config.concurrency
|
|
173
|
+
});
|
|
174
|
+
this.eventHandlers.set(eventName, config);
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
cron(schedule, config) {
|
|
178
|
+
const { handler, description, icon, tags } = config;
|
|
179
|
+
const cronName = `${this.name}.cron.${schedule}`;
|
|
180
|
+
eventRegistry.registerCron(cronName, schedule, handler, { description, icon, tags });
|
|
181
|
+
this.cronJobs.set(cronName, { schedule, ...config });
|
|
182
|
+
this.setupCronJob(cronName, schedule, handler);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
async setupCronJob(cronName, schedule, handler) {
|
|
186
|
+
const queue = await this.eventBus.getQueueForCron(cronName);
|
|
187
|
+
await queue.upsertJobScheduler(cronName, {
|
|
188
|
+
pattern: schedule
|
|
189
|
+
}, {
|
|
190
|
+
name: cronName,
|
|
191
|
+
data: {},
|
|
192
|
+
opts: {}
|
|
193
|
+
});
|
|
194
|
+
this.eventBus.registerCronHandler(cronName, handler);
|
|
195
|
+
}
|
|
196
|
+
build(app, servicesAccumulator) {
|
|
197
|
+
const routes = Array.from(this.endpoints.values()).map((ep) => {
|
|
198
|
+
let requestBody = undefined;
|
|
199
|
+
let queryParams = undefined;
|
|
200
|
+
if (ep.schema.input) {
|
|
201
|
+
if (["POST", "PUT", "PATCH"].includes(ep.method)) {
|
|
202
|
+
requestBody = generateTemplate(ep.schema.input);
|
|
203
|
+
} else if (ep.method === "GET" || ep.method === "DELETE") {
|
|
204
|
+
const pathParamNames = (ep.path.match(/:([^/]+)/g) || []).map((p) => p.slice(1));
|
|
205
|
+
const fullTemplate = generateTemplate(ep.schema.input);
|
|
206
|
+
if (fullTemplate && pathParamNames.length > 0) {
|
|
207
|
+
const queryFields = fullTemplate.fields.filter((f) => !pathParamNames.includes(f.name));
|
|
208
|
+
if (queryFields.length > 0) {
|
|
209
|
+
queryParams = { ...fullTemplate, fields: queryFields };
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
queryParams = fullTemplate;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
let responseBody = undefined;
|
|
217
|
+
if (ep.schema.output) {
|
|
218
|
+
responseBody = generateTemplate(ep.schema.output);
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
method: ep.method,
|
|
222
|
+
path: ep.path,
|
|
223
|
+
handler: this.name,
|
|
224
|
+
middleware: [],
|
|
225
|
+
queryParams,
|
|
226
|
+
requestBody,
|
|
227
|
+
responseBody
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
const capitalizedName = this.name.charAt(0).toUpperCase() + this.name.slice(1);
|
|
231
|
+
if (servicesAccumulator) {
|
|
232
|
+
servicesAccumulator.push({
|
|
233
|
+
name: capitalizedName,
|
|
234
|
+
routes
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
this.endpoints.forEach((ep) => {
|
|
238
|
+
let rateLimitMw;
|
|
239
|
+
const rl = ep.config?.ratelimit;
|
|
240
|
+
if (rl) {
|
|
241
|
+
const windowMs = parseWindowMs(rl.window);
|
|
242
|
+
const limit = rl.requests;
|
|
243
|
+
rateLimitMw = rateLimiter({
|
|
244
|
+
windowMs,
|
|
245
|
+
limit,
|
|
246
|
+
standardHeaders: "draft-6",
|
|
247
|
+
keyGenerator: (c) => getClientKey(c, ep.method, ep.path),
|
|
248
|
+
...rl.store ? { store: rl.store } : {}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const allMiddleware = [
|
|
252
|
+
...this.globalMiddleware,
|
|
253
|
+
...rateLimitMw ? [rateLimitMw] : [],
|
|
254
|
+
...ep.middleware
|
|
255
|
+
];
|
|
256
|
+
const finalHandler = async (c) => {
|
|
257
|
+
try {
|
|
258
|
+
const visionCtx = getVisionContext();
|
|
259
|
+
if (visionCtx && this.visionCore) {
|
|
260
|
+
const { vision, traceId, rootSpanId } = visionCtx;
|
|
261
|
+
const tracer = vision.getTracer();
|
|
262
|
+
c.addContext = (context) => {
|
|
263
|
+
const current = getVisionContext();
|
|
264
|
+
const targetTraceId = current?.traceId || traceId;
|
|
265
|
+
const visionTrace = vision.getTraceStore().getTrace(targetTraceId);
|
|
266
|
+
if (visionTrace) {
|
|
267
|
+
visionTrace.metadata = { ...visionTrace.metadata || {}, ...context };
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
c.span = (name, attributes = {}, fn) => {
|
|
271
|
+
const span = tracer.startSpan(name, traceId, rootSpanId);
|
|
272
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
273
|
+
tracer.setAttribute(span.id, key, value);
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
const result2 = fn ? fn() : undefined;
|
|
277
|
+
const completedSpan = tracer.endSpan(span.id);
|
|
278
|
+
if (completedSpan) {
|
|
279
|
+
vision.getTraceStore().addSpan(traceId, completedSpan);
|
|
280
|
+
}
|
|
281
|
+
return result2;
|
|
282
|
+
} catch (error) {
|
|
283
|
+
tracer.setAttribute(span.id, "error", true);
|
|
284
|
+
tracer.setAttribute(span.id, "error.message", error instanceof Error ? error.message : String(error));
|
|
285
|
+
const completedSpan = tracer.endSpan(span.id);
|
|
286
|
+
if (completedSpan) {
|
|
287
|
+
vision.getTraceStore().addSpan(traceId, completedSpan);
|
|
288
|
+
}
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
if (!c.emit) {
|
|
294
|
+
c.emit = async (eventName, data) => {
|
|
295
|
+
return this.eventBus.emit(eventName, data);
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
const params = c.req.param();
|
|
299
|
+
const query = c.req.query();
|
|
300
|
+
let body = {};
|
|
301
|
+
if (["POST", "PUT", "PATCH"].includes(ep.method)) {
|
|
302
|
+
body = await c.req.json().catch(() => ({}));
|
|
303
|
+
}
|
|
304
|
+
const input = { ...params, ...query, ...body };
|
|
305
|
+
const validated = UniversalValidator.parse(ep.schema.input, input);
|
|
306
|
+
const finalInput = { ...params, ...validated || {} };
|
|
307
|
+
const result = await ep.handler(finalInput, c);
|
|
308
|
+
if (ep.schema.output) {
|
|
309
|
+
const validatedOutput = UniversalValidator.parse(ep.schema.output, result);
|
|
310
|
+
return c.json(validatedOutput);
|
|
311
|
+
}
|
|
312
|
+
if (result instanceof Response) {
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
return c.json(result);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (error instanceof ValidationError) {
|
|
318
|
+
const requestId = c.req.header("x-request-id");
|
|
319
|
+
return c.json(createValidationErrorResponse(error.issues, requestId), 400);
|
|
320
|
+
}
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
if (allMiddleware.length > 0) {
|
|
325
|
+
app.on([ep.method], ep.path, ...allMiddleware, finalHandler);
|
|
326
|
+
} else {
|
|
327
|
+
app.on([ep.method], ep.path, finalHandler);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
endpoints: Array.from(this.endpoints.values()),
|
|
332
|
+
eventHandlers: Array.from(this.eventHandlers.values()),
|
|
333
|
+
cronJobs: Array.from(this.cronJobs.values())
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
export {
|
|
338
|
+
ServiceBuilder
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
//# debugId=786008A0EDA35F9864756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/service.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Hono, Context, MiddlewareHandler, Env, Input } from 'hono'\nimport type { z } from 'zod'\nimport { VisionCore, generateTemplate } from '@getvision/core'\nimport {\n ValidationError,\n createValidationErrorResponse,\n UniversalValidator\n} from '@getvision/core'\nimport type { EndpointConfig, Handler } from './types'\nimport { getVisionContext } from './vision-app'\nimport { eventRegistry } from './event-registry'\nimport type { EventBus } from './event-bus'\nimport { rateLimiter } from 'hono-rate-limiter'\n\n// Simple window parser supporting values like '15m', '1h', '30s', '2d' or plain milliseconds as number string\nfunction parseWindowMs(window: string): number {\n const trimmed = window.trim()\n if (/^\\d+$/.test(trimmed)) return Number(trimmed)\n const match = trimmed.match(/^(\\d+)\\s*([smhd])$/i)\n if (!match) throw new Error(`Invalid ratelimit window: ${window}`)\n const value = Number(match[1])\n const unit = match[2].toLowerCase()\n const multipliers: Record<string, number> = { s: 1000, m: 60_000, h: 3_600_000, d: 86_400_000 }\n return value * multipliers[unit]\n}\n\nfunction getClientKey(c: Context, method: string, path: string): string {\n const ip =\n c.req.header('x-forwarded-for')?.split(',')[0].trim() ||\n c.req.header('x-real-ip') ||\n c.req.header('cf-connecting-ip') ||\n c.req.header('fly-client-ip') ||\n c.req.header('x-client-ip') ||\n ''\n // Fallback to UA if no IP available (still scoped per endpoint)\n const ua = c.req.header('user-agent') || 'unknown'\n return `${ip || ua}:${method}:${path}`\n}\n\n/**\n * Create a minimal Hono-like Context for event handlers\n * so service-level middleware can populate c.set(...)\n */\nfunction createEventContext<E extends Env = any, I extends Input = {}>(): Context<E, any, I> {\n const store: Record<string, any> = {}\n const mockRequest = new Request('http://localhost/event-trigger')\n const resHeaders = new Headers()\n \n const fake: Partial<Context<E, any, I>> = {\n get: (key: string) => store[key],\n set: (key: string, value: any) => { store[key] = value },\n header: (key: string, value: string | undefined) => { \n if (value === undefined) {\n resHeaders.delete(key)\n } else {\n resHeaders.set(key, value) \n }\n },\n status: (code: number) => {},\n req: {\n header: ((name?: string) => name ? undefined : {}) as any,\n param: () => ({}),\n query: () => ({}),\n json: async () => ({}),\n raw: mockRequest,\n url: 'http://localhost/event-trigger',\n method: 'POST',\n } as any,\n res: {\n headers: resHeaders,\n } as any,\n }\n return fake as Context<E, any, I>\n}\n\n/**\n * Run Hono middleware chain on a context\n */\nasync function runMiddlewareChain<E extends Env, I extends Input>(\n middlewares: MiddlewareHandler<E, string, any, any>[],\n c: Context<E, any, I>\n): Promise<void> {\n let index = -1\n const dispatch = async (i: number): Promise<void> => {\n if (i <= index) throw new Error('next() called multiple times')\n index = i\n const mw = middlewares[i]\n if (!mw) return\n await mw(c, () => dispatch(i + 1))\n }\n await dispatch(0)\n}\n\n/**\n * Event schema map - accumulates event types as they're registered\n */\ntype EventSchemaMap = Record<string, z.ZodSchema<any>>\n\n/**\n * ServiceBuilder - Builder pattern API for defining services\n * \n * Automatically infers event types from Zod schemas passed to .on()\n * \n * @example\n * ```ts\n * const userService = app.service('users')\n * .use(logger())\n * .endpoint('GET', '/users/:id', { input, output }, handler)\n * .on('user/created', {\n * schema: z.object({ userId: z.string(), email: z.string() }),\n * handler: async (event) => {\n * // event is fully typed: { userId: string, email: string }\n * }\n * })\n * ```\n */\nexport class ServiceBuilder<\n TEvents extends EventSchemaMap = {},\n E extends Env = Env,\n I extends Input = {}\n> {\n private endpoints: Map<string, any> = new Map()\n private eventHandlers: Map<string, any> = new Map()\n private cronJobs: Map<string, any> = new Map()\n private globalMiddleware: MiddlewareHandler<E, string, any, any>[] = []\n private eventSchemas: EventSchemaMap = {}\n \n constructor(\n private name: string,\n private eventBus: EventBus,\n private visionCore?: VisionCore\n ) {}\n \n /**\n * Add global middleware for all endpoints in this service\n */\n use(...middleware: MiddlewareHandler<E, string, any, any>[]) {\n this.globalMiddleware.push(...middleware)\n return this\n }\n\n /**\n * Get service name (capitalized) and route metadata without registering\n */\n public getRoutesMetadata(): Array<{\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'\n path: string\n queryParams?: any\n requestBody?: any\n responseBody?: any\n }> {\n const routes: Array<{\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'\n path: string\n queryParams?: any\n requestBody?: any\n responseBody?: any\n }> = []\n this.endpoints.forEach((ep) => {\n let requestBody = undefined\n let queryParams = undefined\n \n if (ep.schema.input) {\n if (['POST', 'PUT', 'PATCH'].includes(ep.method)) {\n requestBody = generateTemplate(ep.schema.input)\n } else if (ep.method === 'GET' || ep.method === 'DELETE') {\n // Exclude path params from query params\n const pathParamNames = (ep.path.match(/:([^/]+)/g) || []).map((p: string) => p.slice(1))\n const fullTemplate = generateTemplate(ep.schema.input)\n \n if (fullTemplate && pathParamNames.length > 0) {\n const queryFields = fullTemplate.fields.filter(\n (f: { name: string }) => !pathParamNames.includes(f.name)\n )\n if (queryFields.length > 0) {\n queryParams = { ...fullTemplate, fields: queryFields }\n }\n } else {\n queryParams = fullTemplate\n }\n }\n }\n \n let responseBody = undefined\n if (ep.schema.output) {\n responseBody = generateTemplate(ep.schema.output)\n }\n routes.push({\n method: ep.method,\n path: ep.path,\n queryParams,\n requestBody,\n responseBody,\n })\n })\n return routes\n }\n\n public getDisplayName(): string {\n return this.name.charAt(0).toUpperCase() + this.name.slice(1)\n }\n \n /**\n * Define an HTTP endpoint with Zod validation\n * \n * @example\n * ```ts\n * service.endpoint(\n * 'GET',\n * '/users/:id',\n * {\n * input: z.object({ id: z.string() }),\n * output: z.object({ id: z.string(), name: z.string() })\n * },\n * async ({ id }, c) => {\n * return { id, name: 'John' }\n * },\n * { middleware: [authMiddleware] }\n * )\n * ```\n */\n endpoint<\n TInputSchema extends z.ZodType,\n TOutputSchema extends z.ZodType | undefined,\n PPath extends string\n >(\n method: EndpointConfig['method'],\n path: PPath,\n schema: {\n input: TInputSchema\n output?: TOutputSchema\n },\n handler: Handler<\n z.infer<TInputSchema>,\n TOutputSchema extends z.ZodType ? z.infer<TOutputSchema> : any,\n TEvents,\n E,\n PPath,\n I\n >,\n config?: Partial<EndpointConfig>\n ) {\n this.endpoints.set(`${method}:${path}`, {\n method,\n path,\n handler,\n schema,\n config: { ...config, method, path },\n middleware: config?.middleware || []\n })\n return this\n }\n \n /**\n * Subscribe to events with Zod schema validation\n * \n * Automatically infers the event type from the Zod schema.\n * TypeScript will ensure that c.emit() calls match the registered schema.\n * \n * @example\n * ```ts\n * service.on('user/created', {\n * schema: z.object({\n * userId: z.string().uuid(),\n * email: z.string().email()\n * }),\n * description: 'User account created',\n * icon: '👤',\n * tags: ['user', 'auth'],\n * handler: async (event) => {\n * // event is fully typed: { userId: string, email: string }\n * console.log('User created:', event.email)\n * }\n * })\n * ```\n */\n on<\n K extends string,\n T extends Record<string, any>\n >(\n eventName: K,\n config: {\n schema: z.ZodSchema<T>\n description?: string\n icon?: string\n tags?: string[]\n /**\n * Max number of concurrent jobs this handler will process.\n * Falls back to EventBus config.workerConcurrency (or 1).\n */\n concurrency?: number\n handler: (event: T, c: Context<E, any, I>) => Promise<void>\n }\n ): ServiceBuilder<TEvents & { [key in K]: T }, E, I> {\n const { schema, handler, description, icon, tags } = config\n \n // Store schema for type inference\n this.eventSchemas[eventName] = schema\n \n // Wrap handler to provide Hono-like context with middleware support\n const wrappedHandler = async (data: T) => {\n const ctx = createEventContext<E, I>()\n // Run service-level middleware to populate ctx (e.g., c.set('db', db))\n if (this.globalMiddleware.length > 0) {\n await runMiddlewareChain(this.globalMiddleware, ctx)\n }\n // Call original handler with event data and context\n await handler(data, ctx)\n }\n \n // Register wrapped handler in event registry (for metadata/stats)\n eventRegistry.registerEvent(\n eventName,\n schema,\n wrappedHandler,\n { description, icon, tags }\n )\n \n // Register wrapped handler in event bus\n this.eventBus.registerHandler(eventName, wrappedHandler, {\n concurrency: config.concurrency,\n })\n \n // Store for later reference\n this.eventHandlers.set(eventName, config)\n \n // Return typed ServiceBuilder with accumulated events\n return this as ServiceBuilder<TEvents & { [key in K]: T }, E, I>\n }\n \n /**\n * Schedule a cron job using BullMQ Repeatable\n * \n * @example\n * ```ts\n * service.cron('0 0 * * *', {\n * description: 'Daily cleanup',\n * icon: '🧹',\n * tags: ['maintenance'],\n * handler: async (c) => {\n * console.log('Daily cleanup')\n * }\n * })\n * ```\n */\n cron(\n schedule: string,\n config: {\n description?: string\n icon?: string\n tags?: string[]\n handler: (context: any) => Promise<void>\n }\n ) {\n const { handler, description, icon, tags } = config\n const cronName = `${this.name}.cron.${schedule}`\n \n // Register in event registry\n eventRegistry.registerCron(\n cronName,\n schedule,\n handler,\n { description, icon, tags }\n )\n \n // Store for later reference\n this.cronJobs.set(cronName, { schedule, ...config })\n \n // Setup BullMQ repeatable job\n // This will be called when the service is built\n this.setupCronJob(cronName, schedule, handler)\n \n return this\n }\n \n /**\n * Setup BullMQ repeatable job for cron\n */\n private async setupCronJob(\n cronName: string,\n schedule: string,\n handler: (context: any) => Promise<void>\n ) {\n // Get queue from EventBus (we'll add a getQueue method)\n const queue = await this.eventBus.getQueueForCron(cronName)\n \n // Register cron job using BullMQ upsertJobScheduler\n await queue.upsertJobScheduler(\n cronName,\n {\n pattern: schedule, // Cron expression (e.g., '0 0 * * *')\n },\n {\n name: cronName,\n data: {},\n opts: {},\n }\n )\n \n // Register worker to process cron jobs\n this.eventBus.registerCronHandler(cronName, handler)\n }\n \n /**\n * Build and register all endpoints with Hono\n */\n build(app: Hono, servicesAccumulator?: Array<{ name: string; routes: any[] }>) {\n // Prepare routes with Zod schemas\n const routes = Array.from(this.endpoints.values()).map(ep => {\n // Generate requestBody schema (input) for POST/PUT/PATCH\n let requestBody = undefined\n let queryParams = undefined\n \n if (ep.schema.input) {\n if (['POST', 'PUT', 'PATCH'].includes(ep.method)) {\n requestBody = generateTemplate(ep.schema.input)\n } else if (ep.method === 'GET' || ep.method === 'DELETE') {\n // For GET/DELETE, input schema represents query parameters\n // BUT we need to exclude path params from query params\n const pathParamNames = (ep.path.match(/:([^/]+)/g) || []).map((p: string) => p.slice(1))\n const fullTemplate = generateTemplate(ep.schema.input)\n \n if (fullTemplate && pathParamNames.length > 0) {\n // Filter out path params from query params\n const queryFields = fullTemplate.fields.filter(\n (f: { name: string }) => !pathParamNames.includes(f.name)\n )\n if (queryFields.length > 0) {\n queryParams = { ...fullTemplate, fields: queryFields }\n }\n } else {\n queryParams = fullTemplate\n }\n }\n }\n \n // Generate responseBody schema (output)\n let responseBody = undefined\n if (ep.schema.output) {\n responseBody = generateTemplate(ep.schema.output)\n }\n \n return {\n method: ep.method,\n path: ep.path,\n handler: this.name,\n middleware: [],\n queryParams,\n requestBody,\n responseBody,\n }\n })\n \n const capitalizedName = this.name.charAt(0).toUpperCase() + this.name.slice(1)\n \n // Add to accumulator (для батч реєстрації в buildAllServices)\n if (servicesAccumulator) {\n servicesAccumulator.push({\n name: capitalizedName,\n routes\n })\n }\n \n // Register HTTP endpoints\n this.endpoints.forEach((ep) => {\n // Prepare rate limiter when configured per-endpoint\n let rateLimitMw: MiddlewareHandler<E, string, any, any> | undefined\n const rl = ep.config?.ratelimit as EndpointConfig['ratelimit'] | undefined\n if (rl) {\n const windowMs = parseWindowMs(rl.window)\n const limit = rl.requests\n rateLimitMw = rateLimiter({\n windowMs,\n limit,\n standardHeaders: 'draft-6',\n keyGenerator: (c) => getClientKey(c, ep.method, ep.path),\n // If user provides a distributed store (e.g., RedisStore), pass it through\n ...(rl.store ? { store: rl.store } : {}),\n })\n }\n\n // Combine global + rate-limit (if any) + endpoint-specific middleware\n const allMiddleware = [\n ...this.globalMiddleware,\n ...(rateLimitMw ? [rateLimitMw] as MiddlewareHandler<E, string, any, any>[] : []),\n ...ep.middleware,\n ]\n \n // Create handler with middleware chain\n const finalHandler = async (c: Context<E, any, I>) => {\n try {\n // Add span helper and emit to context\n const visionCtx = getVisionContext()\n if (visionCtx && this.visionCore) {\n const { vision, traceId, rootSpanId } = visionCtx\n const tracer = vision.getTracer();\n \n // Add addContext() method to context\n (c as any).addContext = (context: Record<string, unknown>) => {\n const current = getVisionContext()\n // Use current traceId from context if available (handles nested spans/async correctly)\n const targetTraceId = current?.traceId || traceId\n \n const visionTrace = vision.getTraceStore().getTrace(targetTraceId)\n if (visionTrace) {\n visionTrace.metadata = { ...(visionTrace.metadata || {}), ...context }\n }\n }\n\n // Add span() method to context\n (c as any).span = <T>(\n name: string,\n attributes: Record<string, any> = {},\n fn?: () => T\n ): T => {\n const span = tracer.startSpan(name, traceId, rootSpanId)\n \n for (const [key, value] of Object.entries(attributes)) {\n tracer.setAttribute(span.id, key, value)\n }\n \n try {\n const result = fn ? fn() : (undefined as any)\n const completedSpan = tracer.endSpan(span.id)\n \n if (completedSpan) {\n vision.getTraceStore().addSpan(traceId, completedSpan)\n }\n \n return result\n } catch (error) {\n tracer.setAttribute(span.id, 'error', true)\n tracer.setAttribute(\n span.id,\n 'error.message',\n error instanceof Error ? error.message : String(error)\n )\n const completedSpan = tracer.endSpan(span.id)\n \n if (completedSpan) {\n vision.getTraceStore().addSpan(traceId, completedSpan)\n }\n \n throw error\n }\n }\n }\n\n // Always provide emit() so events work in sub-apps without local VisionCore\n if (!(c as any).emit) {\n (c as any).emit = async <K extends keyof TEvents>(\n eventName: K,\n data: TEvents[K]\n ): Promise<void> => {\n return this.eventBus.emit(eventName as string, data)\n }\n }\n \n // Parse and merge params, body, query\n const params = c.req.param()\n const query = c.req.query()\n let body = {}\n \n if (['POST', 'PUT', 'PATCH'].includes(ep.method)) {\n body = await c.req.json().catch(() => ({}))\n }\n \n const input = { ...params, ...query, ...body }\n \n // Validate input with UniversalValidator (supports Zod, Valibot, etc.)\n const validated = UniversalValidator.parse(ep.schema.input, input)\n \n // Merge back path params that are not in the schema\n // This ensures path params like :id are always available to the handler\n const finalInput = { ...params, ...(validated || {}) }\n \n // Execute handler\n const result = await ep.handler(finalInput, c as any)\n\n // If an output schema exists, validate and return JSON\n if (ep.schema.output) {\n const validatedOutput = UniversalValidator.parse(ep.schema.output, result)\n return c.json(validatedOutput)\n }\n\n // No output schema: allow raw Response or JSON\n if (result instanceof Response) {\n return result\n }\n return c.json(result)\n } catch (error) {\n if (error instanceof ValidationError) {\n const requestId = c.req.header('x-request-id')\n return c.json(\n createValidationErrorResponse(error.issues, requestId),\n 400\n )\n }\n throw error\n }\n }\n \n // Register with middleware chain\n if (allMiddleware.length > 0) {\n app.on([ep.method], ep.path, ...allMiddleware, finalHandler)\n } else {\n app.on([ep.method], ep.path, finalHandler)\n }\n })\n \n return {\n endpoints: Array.from(this.endpoints.values()),\n eventHandlers: Array.from(this.eventHandlers.values()),\n cronJobs: Array.from(this.cronJobs.values())\n }\n }\n}\n\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAEA;AACA;AAAA;AAAA;AAAA;AAAA;AAMA;AACA;AAEA;AAGA,SAAS,aAAa,CAAC,QAAwB;AAAA,EAC7C,MAAM,UAAU,OAAO,KAAK;AAAA,EAC5B,IAAI,QAAQ,KAAK,OAAO;AAAA,IAAG,OAAO,OAAO,OAAO;AAAA,EAChD,MAAM,QAAQ,QAAQ,MAAM,qBAAqB;AAAA,EACjD,IAAI,CAAC;AAAA,IAAO,MAAM,IAAI,MAAM,6BAA6B,QAAQ;AAAA,EACjE,MAAM,QAAQ,OAAO,MAAM,EAAE;AAAA,EAC7B,MAAM,OAAO,MAAM,GAAG,YAAY;AAAA,EAClC,MAAM,cAAsC,EAAE,GAAG,MAAM,GAAG,OAAQ,GAAG,SAAW,GAAG,SAAW;AAAA,EAC9F,OAAO,QAAQ,YAAY;AAAA;AAG7B,SAAS,YAAY,CAAC,GAAY,QAAgB,MAAsB;AAAA,EACtE,MAAM,KACJ,EAAE,IAAI,OAAO,iBAAiB,GAAG,MAAM,GAAG,EAAE,GAAG,KAAK,KACpD,EAAE,IAAI,OAAO,WAAW,KACxB,EAAE,IAAI,OAAO,kBAAkB,KAC/B,EAAE,IAAI,OAAO,eAAe,KAC5B,EAAE,IAAI,OAAO,aAAa,KAC1B;AAAA,EAEF,MAAM,KAAK,EAAE,IAAI,OAAO,YAAY,KAAK;AAAA,EACzC,OAAO,GAAG,MAAM,MAAM,UAAU;AAAA;AAOlC,SAAS,kBAA6D,GAAuB;AAAA,EAC3F,MAAM,QAA6B,CAAC;AAAA,EACpC,MAAM,cAAc,IAAI,QAAQ,gCAAgC;AAAA,EAChE,MAAM,aAAa,IAAI;AAAA,EAEvB,MAAM,OAAoC;AAAA,IACxC,KAAK,CAAC,QAAgB,MAAM;AAAA,IAC5B,KAAK,CAAC,KAAa,UAAe;AAAA,MAAE,MAAM,OAAO;AAAA;AAAA,IACjD,QAAQ,CAAC,KAAa,UAA8B;AAAA,MAClD,IAAI,UAAU,WAAW;AAAA,QACvB,WAAW,OAAO,GAAG;AAAA,MACvB,EAAO;AAAA,QACL,WAAW,IAAI,KAAK,KAAK;AAAA;AAAA;AAAA,IAG7B,QAAQ,CAAC,SAAiB;AAAA,IAC1B,KAAK;AAAA,MACH,QAAS,CAAC,SAAkB,OAAO,YAAY,CAAC;AAAA,MAChD,OAAO,OAAO,CAAC;AAAA,MACf,OAAO,OAAO,CAAC;AAAA,MACf,MAAM,aAAa,CAAC;AAAA,MACpB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,IACV;AAAA,IACA,KAAK;AAAA,MACH,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAMT,eAAe,kBAAkD,CAC/D,aACA,GACe;AAAA,EACf,IAAI,QAAQ;AAAA,EACZ,MAAM,WAAW,OAAO,MAA6B;AAAA,IACnD,IAAI,KAAK;AAAA,MAAO,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAC9D,QAAQ;AAAA,IACR,MAAM,KAAK,YAAY;AAAA,IACvB,IAAI,CAAC;AAAA,MAAI;AAAA,IACT,MAAM,GAAG,GAAG,MAAM,SAAS,IAAI,CAAC,CAAC;AAAA;AAAA,EAEnC,MAAM,SAAS,CAAC;AAAA;AAAA;AA0BX,MAAM,eAIX;AAAA,EAQU;AAAA,EACA;AAAA,EACA;AAAA,EATF,YAA8B,IAAI;AAAA,EAClC,gBAAkC,IAAI;AAAA,EACtC,WAA6B,IAAI;AAAA,EACjC,mBAA6D,CAAC;AAAA,EAC9D,eAA+B,CAAC;AAAA,EAExC,WAAW,CACD,MACA,UACA,YACR;AAAA,IAHQ;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAMV,GAAG,IAAI,YAAsD;AAAA,IAC3D,KAAK,iBAAiB,KAAK,GAAG,UAAU;AAAA,IACxC,OAAO;AAAA;AAAA,EAMF,iBAAiB,GAMrB;AAAA,IACD,MAAM,SAMD,CAAC;AAAA,IACN,KAAK,UAAU,QAAQ,CAAC,OAAO;AAAA,MAC7B,IAAI,cAAc;AAAA,MAClB,IAAI,cAAc;AAAA,MAElB,IAAI,GAAG,OAAO,OAAO;AAAA,QACnB,IAAI,CAAC,QAAQ,OAAO,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG;AAAA,UAChD,cAAc,iBAAiB,GAAG,OAAO,KAAK;AAAA,QAChD,EAAO,SAAI,GAAG,WAAW,SAAS,GAAG,WAAW,UAAU;AAAA,UAExD,MAAM,kBAAkB,GAAG,KAAK,MAAM,WAAW,KAAK,CAAC,GAAG,IAAI,CAAC,MAAc,EAAE,MAAM,CAAC,CAAC;AAAA,UACvF,MAAM,eAAe,iBAAiB,GAAG,OAAO,KAAK;AAAA,UAErD,IAAI,gBAAgB,eAAe,SAAS,GAAG;AAAA,YAC7C,MAAM,cAAc,aAAa,OAAO,OACtC,CAAC,MAAwB,CAAC,eAAe,SAAS,EAAE,IAAI,CAC1D;AAAA,YACA,IAAI,YAAY,SAAS,GAAG;AAAA,cAC1B,cAAc,KAAK,cAAc,QAAQ,YAAY;AAAA,YACvD;AAAA,UACF,EAAO;AAAA,YACL,cAAc;AAAA;AAAA,QAElB;AAAA,MACF;AAAA,MAEA,IAAI,eAAe;AAAA,MACnB,IAAI,GAAG,OAAO,QAAQ;AAAA,QACpB,eAAe,iBAAiB,GAAG,OAAO,MAAM;AAAA,MAClD;AAAA,MACA,OAAO,KAAK;AAAA,QACV,QAAQ,GAAG;AAAA,QACX,MAAM,GAAG;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,KACF;AAAA,IACD,OAAO;AAAA;AAAA,EAGF,cAAc,GAAW;AAAA,IAC9B,OAAO,KAAK,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,KAAK,MAAM,CAAC;AAAA;AAAA,EAsB9D,QAIC,CACC,QACA,MACA,QAIA,SAQA,QACA;AAAA,IACA,KAAK,UAAU,IAAI,GAAG,UAAU,QAAQ;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,QAAQ,QAAQ,KAAK;AAAA,MAClC,YAAY,QAAQ,cAAc,CAAC;AAAA,IACrC,CAAC;AAAA,IACD,OAAO;AAAA;AAAA,EA0BT,EAGC,CACC,WACA,QAYmD;AAAA,IACnD,QAAQ,QAAQ,SAAS,aAAa,MAAM,SAAS;AAAA,IAGrD,KAAK,aAAa,aAAa;AAAA,IAG/B,MAAM,iBAAiB,OAAO,SAAY;AAAA,MACxC,MAAM,MAAM,mBAAyB;AAAA,MAErC,IAAI,KAAK,iBAAiB,SAAS,GAAG;AAAA,QACpC,MAAM,mBAAmB,KAAK,kBAAkB,GAAG;AAAA,MACrD;AAAA,MAEA,MAAM,QAAQ,MAAM,GAAG;AAAA;AAAA,IAIzB,cAAc,cACZ,WACA,QACA,gBACA,EAAE,aAAa,MAAM,KAAK,CAC5B;AAAA,IAGA,KAAK,SAAS,gBAAgB,WAAW,gBAAgB;AAAA,MACvD,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,IAGD,KAAK,cAAc,IAAI,WAAW,MAAM;AAAA,IAGxC,OAAO;AAAA;AAAA,EAkBT,IAAI,CACF,UACA,QAMA;AAAA,IACA,QAAQ,SAAS,aAAa,MAAM,SAAS;AAAA,IAC7C,MAAM,WAAW,GAAG,KAAK,aAAa;AAAA,IAGtC,cAAc,aACZ,UACA,UACA,SACA,EAAE,aAAa,MAAM,KAAK,CAC5B;AAAA,IAGA,KAAK,SAAS,IAAI,UAAU,EAAE,aAAa,OAAO,CAAC;AAAA,IAInD,KAAK,aAAa,UAAU,UAAU,OAAO;AAAA,IAE7C,OAAO;AAAA;AAAA,OAMK,aAAY,CACxB,UACA,UACA,SACA;AAAA,IAEA,MAAM,QAAQ,MAAM,KAAK,SAAS,gBAAgB,QAAQ;AAAA,IAG1D,MAAM,MAAM,mBACV,UACA;AAAA,MACE,SAAS;AAAA,IACX,GACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM,CAAC;AAAA,MACP,MAAM,CAAC;AAAA,IACT,CACF;AAAA,IAGA,KAAK,SAAS,oBAAoB,UAAU,OAAO;AAAA;AAAA,EAMrD,KAAK,CAAC,KAAW,qBAA8D;AAAA,IAE7E,MAAM,SAAS,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,QAAM;AAAA,MAE3D,IAAI,cAAc;AAAA,MAClB,IAAI,cAAc;AAAA,MAElB,IAAI,GAAG,OAAO,OAAO;AAAA,QACnB,IAAI,CAAC,QAAQ,OAAO,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG;AAAA,UAChD,cAAc,iBAAiB,GAAG,OAAO,KAAK;AAAA,QAChD,EAAO,SAAI,GAAG,WAAW,SAAS,GAAG,WAAW,UAAU;AAAA,UAGxD,MAAM,kBAAkB,GAAG,KAAK,MAAM,WAAW,KAAK,CAAC,GAAG,IAAI,CAAC,MAAc,EAAE,MAAM,CAAC,CAAC;AAAA,UACvF,MAAM,eAAe,iBAAiB,GAAG,OAAO,KAAK;AAAA,UAErD,IAAI,gBAAgB,eAAe,SAAS,GAAG;AAAA,YAE7C,MAAM,cAAc,aAAa,OAAO,OACtC,CAAC,MAAwB,CAAC,eAAe,SAAS,EAAE,IAAI,CAC1D;AAAA,YACA,IAAI,YAAY,SAAS,GAAG;AAAA,cAC1B,cAAc,KAAK,cAAc,QAAQ,YAAY;AAAA,YACvD;AAAA,UACF,EAAO;AAAA,YACL,cAAc;AAAA;AAAA,QAElB;AAAA,MACF;AAAA,MAGA,IAAI,eAAe;AAAA,MACnB,IAAI,GAAG,OAAO,QAAQ;AAAA,QACpB,eAAe,iBAAiB,GAAG,OAAO,MAAM;AAAA,MAClD;AAAA,MAEA,OAAO;AAAA,QACL,QAAQ,GAAG;AAAA,QACX,MAAM,GAAG;AAAA,QACT,SAAS,KAAK;AAAA,QACd,YAAY,CAAC;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,KACD;AAAA,IAED,MAAM,kBAAkB,KAAK,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,KAAK,MAAM,CAAC;AAAA,IAG7E,IAAI,qBAAqB;AAAA,MACvB,oBAAoB,KAAK;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAGA,KAAK,UAAU,QAAQ,CAAC,OAAO;AAAA,MAE7B,IAAI;AAAA,MACJ,MAAM,KAAK,GAAG,QAAQ;AAAA,MACtB,IAAI,IAAI;AAAA,QACN,MAAM,WAAW,cAAc,GAAG,MAAM;AAAA,QACxC,MAAM,QAAQ,GAAG;AAAA,QACjB,cAAc,YAAY;AAAA,UACxB;AAAA,UACA;AAAA,UACA,iBAAiB;AAAA,UACjB,cAAc,CAAC,MAAM,aAAa,GAAG,GAAG,QAAQ,GAAG,IAAI;AAAA,aAEnD,GAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,MAGA,MAAM,gBAAgB;AAAA,QACpB,GAAG,KAAK;AAAA,QACR,GAAI,cAAc,CAAC,WAAW,IAAgD,CAAC;AAAA,QAC/E,GAAG,GAAG;AAAA,MACR;AAAA,MAGA,MAAM,eAAe,OAAO,MAA0B;AAAA,QACpD,IAAI;AAAA,UAEF,MAAM,YAAY,iBAAiB;AAAA,UACnC,IAAI,aAAa,KAAK,YAAY;AAAA,YAChC,QAAQ,QAAQ,SAAS,eAAe;AAAA,YACxC,MAAM,SAAS,OAAO,UAAU;AAAA,YAG/B,EAAU,aAAa,CAAC,YAAqC;AAAA,cAC5D,MAAM,UAAU,iBAAiB;AAAA,cAEjC,MAAM,gBAAgB,SAAS,WAAW;AAAA,cAE1C,MAAM,cAAc,OAAO,cAAc,EAAE,SAAS,aAAa;AAAA,cACjE,IAAI,aAAa;AAAA,gBACf,YAAY,WAAW,KAAM,YAAY,YAAY,CAAC,MAAO,QAAQ;AAAA,cACvE;AAAA;AAAA,YAID,EAAU,OAAO,CAChB,MACA,aAAkC,CAAC,GACnC,OACM;AAAA,cACN,MAAM,OAAO,OAAO,UAAU,MAAM,SAAS,UAAU;AAAA,cAEvD,YAAY,KAAK,UAAU,OAAO,QAAQ,UAAU,GAAG;AAAA,gBACrD,OAAO,aAAa,KAAK,IAAI,KAAK,KAAK;AAAA,cACzC;AAAA,cAEA,IAAI;AAAA,gBACF,MAAM,UAAS,KAAK,GAAG,IAAK;AAAA,gBAC5B,MAAM,gBAAgB,OAAO,QAAQ,KAAK,EAAE;AAAA,gBAE5C,IAAI,eAAe;AAAA,kBACjB,OAAO,cAAc,EAAE,QAAQ,SAAS,aAAa;AAAA,gBACvD;AAAA,gBAEA,OAAO;AAAA,gBACP,OAAO,OAAO;AAAA,gBACd,OAAO,aAAa,KAAK,IAAI,SAAS,IAAI;AAAA,gBAC1C,OAAO,aACL,KAAK,IACL,iBACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,gBACA,MAAM,gBAAgB,OAAO,QAAQ,KAAK,EAAE;AAAA,gBAE5C,IAAI,eAAe;AAAA,kBACjB,OAAO,cAAc,EAAE,QAAQ,SAAS,aAAa;AAAA,gBACvD;AAAA,gBAEA,MAAM;AAAA;AAAA;AAAA,UAGZ;AAAA,UAGA,IAAI,CAAE,EAAU,MAAM;AAAA,YACnB,EAAU,OAAO,OAChB,WACA,SACkB;AAAA,cAClB,OAAO,KAAK,SAAS,KAAK,WAAqB,IAAI;AAAA;AAAA,UAEvD;AAAA,UAGA,MAAM,SAAS,EAAE,IAAI,MAAM;AAAA,UAC3B,MAAM,QAAQ,EAAE,IAAI,MAAM;AAAA,UAC1B,IAAI,OAAO,CAAC;AAAA,UAEZ,IAAI,CAAC,QAAQ,OAAO,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG;AAAA,YAChD,OAAO,MAAM,EAAE,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,UAC5C;AAAA,UAEA,MAAM,QAAQ,KAAK,WAAW,UAAU,KAAK;AAAA,UAG7C,MAAM,YAAY,mBAAmB,MAAM,GAAG,OAAO,OAAO,KAAK;AAAA,UAIjE,MAAM,aAAa,KAAK,WAAY,aAAa,CAAC,EAAG;AAAA,UAGrD,MAAM,SAAS,MAAM,GAAG,QAAQ,YAAY,CAAQ;AAAA,UAGpD,IAAI,GAAG,OAAO,QAAQ;AAAA,YACpB,MAAM,kBAAkB,mBAAmB,MAAM,GAAG,OAAO,QAAQ,MAAM;AAAA,YACzE,OAAO,EAAE,KAAK,eAAe;AAAA,UAC/B;AAAA,UAGA,IAAI,kBAAkB,UAAU;AAAA,YAC9B,OAAO;AAAA,UACT;AAAA,UACA,OAAO,EAAE,KAAK,MAAM;AAAA,UACpB,OAAO,OAAO;AAAA,UACd,IAAI,iBAAiB,iBAAiB;AAAA,YACpC,MAAM,YAAY,EAAE,IAAI,OAAO,cAAc;AAAA,YAC7C,OAAO,EAAE,KACP,8BAA8B,MAAM,QAAQ,SAAS,GACrD,GACF;AAAA,UACF;AAAA,UACA,MAAM;AAAA;AAAA;AAAA,MAKV,IAAI,cAAc,SAAS,GAAG;AAAA,QAC5B,IAAI,GAAG,CAAC,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,eAAe,YAAY;AAAA,MAC7D,EAAO;AAAA,QACL,IAAI,GAAG,CAAC,GAAG,MAAM,GAAG,GAAG,MAAM,YAAY;AAAA;AAAA,KAE5C;AAAA,IAED,OAAO;AAAA,MACL,WAAW,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,MAC7C,eAAe,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC;AAAA,MACrD,UAAU,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;AAAA,IAC7C;AAAA;AAEJ;",
|
|
8
|
+
"debugId": "786008A0EDA35F9864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Context, Env, Input, MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { VisionCore } from '@getvision/core';
|
|
3
|
+
/**
|
|
4
|
+
* Vision context stored in AsyncLocalStorage
|
|
5
|
+
*/
|
|
6
|
+
export interface VisionContext<E extends Env = any, P extends string = any, I extends Input = {}> extends Context<E, P, I> {
|
|
7
|
+
vision: VisionCore;
|
|
8
|
+
traceId: string;
|
|
9
|
+
rootSpanId: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Endpoint configuration options
|
|
13
|
+
*/
|
|
14
|
+
export interface EndpointConfig {
|
|
15
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
16
|
+
path: string;
|
|
17
|
+
middleware?: MiddlewareHandler[];
|
|
18
|
+
auth?: boolean;
|
|
19
|
+
ratelimit?: {
|
|
20
|
+
requests: number;
|
|
21
|
+
window: string;
|
|
22
|
+
store?: any;
|
|
23
|
+
};
|
|
24
|
+
cache?: {
|
|
25
|
+
ttl: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extended Context with span helper and emit
|
|
30
|
+
*
|
|
31
|
+
* Generic TEvents parameter allows type-safe event emission
|
|
32
|
+
*/
|
|
33
|
+
export interface ExtendedContext<TEvents extends Record<string, any> = {}, E extends Env = any, P extends string = any, I extends Input = {}> extends Context<E, P, I> {
|
|
34
|
+
span<T>(name: string, attributes?: Record<string, any>, fn?: () => T): T;
|
|
35
|
+
/**
|
|
36
|
+
* Add context to the current active trace
|
|
37
|
+
* This is the "Wide Event" API - allowing adding high-cardinality data
|
|
38
|
+
* to the current request context.
|
|
39
|
+
*/
|
|
40
|
+
addContext(context: Record<string, unknown>): void;
|
|
41
|
+
/**
|
|
42
|
+
* Emit an event with type-safe validation
|
|
43
|
+
*
|
|
44
|
+
* The event name and data are validated against registered Zod schemas.
|
|
45
|
+
* TypeScript will ensure:
|
|
46
|
+
* 1. The event name is registered (via .on())
|
|
47
|
+
* 2. The data matches the schema exactly
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // After .on('user/created', { schema: z.object({ userId: z.string(), email: z.string() }) })
|
|
52
|
+
*
|
|
53
|
+
* // ✅ TypeScript allows this:
|
|
54
|
+
* await c.emit('user/created', {
|
|
55
|
+
* userId: '123',
|
|
56
|
+
* email: 'user@example.com'
|
|
57
|
+
* })
|
|
58
|
+
*
|
|
59
|
+
* // ❌ TypeScript errors:
|
|
60
|
+
* await c.emit('unknown/event', {}) // Event not registered
|
|
61
|
+
* await c.emit('user/created', { userId: '123' }) // Missing email
|
|
62
|
+
* await c.emit('user/created', { userId: '123', email: 'x', extra: 'extra' }) // Extra field
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
emit<K extends keyof TEvents>(eventName: K, data: TEvents[K]): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Handler type with Zod-validated input and Vision-enhanced context
|
|
69
|
+
*/
|
|
70
|
+
export type Handler<TInput = any, TOutput = any, TEvents extends Record<string, any> = {}, E extends Env = any, P extends string = any, I extends Input = {}> = (req: TInput, ctx: ExtendedContext<TEvents, E, P, I>) => Promise<TOutput> | TOutput;
|
|
71
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,KAAK,GAAG,EAAE,CAAE,SAAQ,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACxH,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAA;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAEhC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,CAAA;IAC7D,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe,CAC9B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EACxC,CAAC,SAAS,GAAG,GAAG,GAAG,EACnB,CAAC,SAAS,MAAM,GAAG,GAAG,EACtB,CAAC,SAAS,KAAK,GAAG,EAAE,CACpB,SAAQ,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,EACJ,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,EAAE,CAAC,EAAE,MAAM,CAAC,GACX,CAAC,CAAA;IAEJ;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAElD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,OAAO,EAC1B,SAAS,EAAE,CAAC,EACZ,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,OAAO,CACjB,MAAM,GAAG,GAAG,EACZ,OAAO,GAAG,GAAG,EACb,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EACxC,CAAC,SAAS,GAAG,GAAG,GAAG,EACnB,CAAC,SAAS,MAAM,GAAG,GAAG,EACtB,CAAC,SAAS,KAAK,GAAG,EAAE,IAClB,CACF,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,eAAe,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KACnC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { Env, Schema } from 'hono';
|
|
3
|
+
import { VisionCore } from '@getvision/core';
|
|
4
|
+
import type { RouteMetadata } from '@getvision/core';
|
|
5
|
+
import { ServiceBuilder } from './service';
|
|
6
|
+
import { EventBus } from './event-bus';
|
|
7
|
+
import type { serve as honoServe } from '@hono/node-server';
|
|
8
|
+
import type { QueueEventsOptions, QueueOptions, WorkerOptions } from "bullmq";
|
|
9
|
+
export interface VisionALSContext {
|
|
10
|
+
vision: VisionCore;
|
|
11
|
+
traceId: string;
|
|
12
|
+
rootSpanId: string;
|
|
13
|
+
}
|
|
14
|
+
type BunServeOptions = Parameters<typeof Bun['serve']>[0];
|
|
15
|
+
type NodeServeOptions = Parameters<typeof honoServe>[0];
|
|
16
|
+
type VisionStartOptions = Omit<Partial<BunServeOptions>, 'fetch' | 'port'> & Omit<Partial<NodeServeOptions>, 'fetch' | 'port'>;
|
|
17
|
+
/**
|
|
18
|
+
* Vision Server configuration
|
|
19
|
+
*/
|
|
20
|
+
export interface VisionConfig {
|
|
21
|
+
service: {
|
|
22
|
+
name: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
integrations?: Record<string, string>;
|
|
26
|
+
drizzle?: {
|
|
27
|
+
autoStart?: boolean;
|
|
28
|
+
port?: number;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
vision?: {
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
port?: number;
|
|
34
|
+
maxTraces?: number;
|
|
35
|
+
maxLogs?: number;
|
|
36
|
+
logging?: boolean;
|
|
37
|
+
apiUrl?: string;
|
|
38
|
+
};
|
|
39
|
+
routes?: {
|
|
40
|
+
autodiscover?: boolean;
|
|
41
|
+
dirs?: string[];
|
|
42
|
+
};
|
|
43
|
+
pubsub?: {
|
|
44
|
+
redis?: {
|
|
45
|
+
host?: string;
|
|
46
|
+
port?: number;
|
|
47
|
+
password?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Enable keepalive to prevent connection timeouts (default: 30000ms)
|
|
50
|
+
*/
|
|
51
|
+
keepAlive?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Max retry attempts for failed commands (default: 20)
|
|
54
|
+
*/
|
|
55
|
+
maxRetriesPerRequest?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Enable ready check before executing commands (default: true)
|
|
58
|
+
*/
|
|
59
|
+
enableReadyCheck?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Connection timeout in ms (default: 10000)
|
|
62
|
+
*/
|
|
63
|
+
connectTimeout?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Enable offline queue (default: true)
|
|
66
|
+
*/
|
|
67
|
+
enableOfflineQueue?: boolean;
|
|
68
|
+
};
|
|
69
|
+
devMode?: boolean;
|
|
70
|
+
eventBus?: EventBus;
|
|
71
|
+
/**
|
|
72
|
+
* Default BullMQ worker concurrency for all handlers (overridable per handler)
|
|
73
|
+
*/
|
|
74
|
+
workerConcurrency?: number;
|
|
75
|
+
queue?: Omit<QueueOptions, 'connection'>;
|
|
76
|
+
worker?: Omit<WorkerOptions, 'connection'>;
|
|
77
|
+
queueEvents?: Omit<QueueEventsOptions, 'connection'>;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Vision - Meta-framework built on Hono with observability
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const app = new Vision({
|
|
86
|
+
* service: {
|
|
87
|
+
* name: 'My API',
|
|
88
|
+
* version: '1.0.0'
|
|
89
|
+
* }
|
|
90
|
+
* })
|
|
91
|
+
*
|
|
92
|
+
* const userService = app.service('users')
|
|
93
|
+
* .on('user/created', handler)
|
|
94
|
+
* .endpoint('GET', '/users/:id', schema, handler)
|
|
95
|
+
*
|
|
96
|
+
* app.start(3000)
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare class Vision<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'> extends Hono<E, S, BasePath> {
|
|
100
|
+
private visionCore;
|
|
101
|
+
private eventBus;
|
|
102
|
+
private config;
|
|
103
|
+
private serviceBuilders;
|
|
104
|
+
private bunServer?;
|
|
105
|
+
private signalHandler?;
|
|
106
|
+
constructor(config?: VisionConfig);
|
|
107
|
+
/**
|
|
108
|
+
* Register JSON-RPC methods for events and cron jobs
|
|
109
|
+
*/
|
|
110
|
+
private registerEventMethods;
|
|
111
|
+
/**
|
|
112
|
+
* Install Vision tracing middleware
|
|
113
|
+
*/
|
|
114
|
+
private installVisionMiddleware;
|
|
115
|
+
/**
|
|
116
|
+
* Create a new service with builder pattern
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const userService = app.service('users')
|
|
121
|
+
* .endpoint('GET', '/users/:id', schema, handler)
|
|
122
|
+
* .on('user/created', handler)
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
service<E2 extends Env = E, TEvents extends Record<string, any> = {}>(name: string): ServiceBuilder<TEvents, E2, {}>;
|
|
126
|
+
/**
|
|
127
|
+
* Get services and routes metadata without registering to this VisionCore
|
|
128
|
+
*/
|
|
129
|
+
getServiceSummaries(): Array<{
|
|
130
|
+
name: string;
|
|
131
|
+
routes: RouteMetadata[];
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Build all service builders
|
|
135
|
+
*/
|
|
136
|
+
buildAllServices(): {
|
|
137
|
+
name: string;
|
|
138
|
+
routes: RouteMetadata[];
|
|
139
|
+
}[];
|
|
140
|
+
/**
|
|
141
|
+
* Get Vision Core instance
|
|
142
|
+
*/
|
|
143
|
+
getVision(): VisionCore;
|
|
144
|
+
/**
|
|
145
|
+
* Get EventBus instance
|
|
146
|
+
*/
|
|
147
|
+
getEventBus(): EventBus;
|
|
148
|
+
/**
|
|
149
|
+
* Autoload Vision/Hono sub-apps from configured directories
|
|
150
|
+
*/
|
|
151
|
+
private autoloadRoutes;
|
|
152
|
+
/**
|
|
153
|
+
* Start the server (convenience method)
|
|
154
|
+
*/
|
|
155
|
+
start(port?: number, options?: VisionStartOptions): Promise<this | undefined>;
|
|
156
|
+
/**
|
|
157
|
+
* Set the EventBus instance (used internally by router to inject shared EventBus)
|
|
158
|
+
*/
|
|
159
|
+
setEventBus(eventBus: EventBus): void;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get Vision context (internal use)
|
|
163
|
+
*/
|
|
164
|
+
export declare function getVisionContext(): VisionALSContext | undefined;
|
|
165
|
+
export {};
|
|
166
|
+
//# sourceMappingURL=vision-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-app.d.ts","sourceRoot":"","sources":["../src/vision-app.ts"],"names":[],"mappings":"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"}
|