@mastra/hono 0.0.0-trace-timeline-update-20251121114225 → 0.0.0-unified-workspace-snapshot-20260128233410
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 +409 -2637
- package/README.md +37 -433
- package/dist/auth-middleware.d.ts +11 -0
- package/dist/auth-middleware.d.ts.map +1 -0
- package/dist/index.cjs +484 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +36 -34
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +482 -51
- package/dist/index.js.map +1 -1
- package/package.json +16 -15
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var error = require('@mastra/server/handlers/error');
|
|
4
4
|
var serverAdapter = require('@mastra/server/server-adapter');
|
|
5
|
+
var fetchToNode = require('fetch-to-node');
|
|
6
|
+
var auth = require('@mastra/server/auth');
|
|
5
7
|
|
|
6
8
|
// src/index.ts
|
|
7
9
|
|
|
8
|
-
// ../../node_modules/.pnpm/hono@4.
|
|
10
|
+
// ../../node_modules/.pnpm/hono@4.11.3/node_modules/hono/dist/http-exception.js
|
|
9
11
|
var HTTPException = class extends Error {
|
|
10
12
|
res;
|
|
11
13
|
status;
|
|
14
|
+
/**
|
|
15
|
+
* Creates an instance of `HTTPException`.
|
|
16
|
+
* @param status - HTTP status code for the exception. Defaults to 500.
|
|
17
|
+
* @param options - Additional options for the exception.
|
|
18
|
+
*/
|
|
12
19
|
constructor(status = 500, options) {
|
|
13
20
|
super(options?.message, { cause: options?.cause });
|
|
14
21
|
this.res = options?.res;
|
|
15
22
|
this.status = status;
|
|
16
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the response object associated with the exception.
|
|
26
|
+
* If a response object is not provided, a new response is created with the error message and status code.
|
|
27
|
+
* @returns The response object.
|
|
28
|
+
*/
|
|
17
29
|
getResponse() {
|
|
18
30
|
if (this.res) {
|
|
19
31
|
const newResponse = new Response(this.res.body, {
|
|
@@ -28,7 +40,7 @@ var HTTPException = class extends Error {
|
|
|
28
40
|
}
|
|
29
41
|
};
|
|
30
42
|
|
|
31
|
-
// ../../node_modules/.pnpm/hono@4.
|
|
43
|
+
// ../../node_modules/.pnpm/hono@4.11.3/node_modules/hono/dist/middleware/body-limit/index.js
|
|
32
44
|
var ERROR_MESSAGE = "Payload Too Large";
|
|
33
45
|
var BodyLimitError = class extends Error {
|
|
34
46
|
constructor(message) {
|
|
@@ -85,14 +97,20 @@ var bodyLimit = (options) => {
|
|
|
85
97
|
};
|
|
86
98
|
};
|
|
87
99
|
|
|
88
|
-
// ../../node_modules/.pnpm/hono@4.
|
|
100
|
+
// ../../node_modules/.pnpm/hono@4.11.3/node_modules/hono/dist/utils/stream.js
|
|
89
101
|
var StreamingApi = class {
|
|
90
102
|
writer;
|
|
91
103
|
encoder;
|
|
92
104
|
writable;
|
|
93
105
|
abortSubscribers = [];
|
|
94
106
|
responseReadable;
|
|
107
|
+
/**
|
|
108
|
+
* Whether the stream has been aborted.
|
|
109
|
+
*/
|
|
95
110
|
aborted = false;
|
|
111
|
+
/**
|
|
112
|
+
* Whether the stream has been closed normally.
|
|
113
|
+
*/
|
|
96
114
|
closed = false;
|
|
97
115
|
constructor(writable, _readable) {
|
|
98
116
|
this.writable = writable;
|
|
@@ -144,6 +162,10 @@ var StreamingApi = class {
|
|
|
144
162
|
onAbort(listener) {
|
|
145
163
|
this.abortSubscribers.push(listener);
|
|
146
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Abort the stream.
|
|
167
|
+
* You can call this method when stream is aborted by external event.
|
|
168
|
+
*/
|
|
147
169
|
abort() {
|
|
148
170
|
if (!this.aborted) {
|
|
149
171
|
this.aborted = true;
|
|
@@ -152,7 +174,7 @@ var StreamingApi = class {
|
|
|
152
174
|
}
|
|
153
175
|
};
|
|
154
176
|
|
|
155
|
-
// ../../node_modules/.pnpm/hono@4.
|
|
177
|
+
// ../../node_modules/.pnpm/hono@4.11.3/node_modules/hono/dist/helper/streaming/utils.js
|
|
156
178
|
var isOldBunVersion = () => {
|
|
157
179
|
const version = typeof Bun !== "undefined" ? Bun.version : void 0;
|
|
158
180
|
if (version === void 0) {
|
|
@@ -163,7 +185,7 @@ var isOldBunVersion = () => {
|
|
|
163
185
|
return result;
|
|
164
186
|
};
|
|
165
187
|
|
|
166
|
-
// ../../node_modules/.pnpm/hono@4.
|
|
188
|
+
// ../../node_modules/.pnpm/hono@4.11.3/node_modules/hono/dist/helper/streaming/stream.js
|
|
167
189
|
var contextStash = /* @__PURE__ */ new WeakMap();
|
|
168
190
|
var stream = (c, cb, onError) => {
|
|
169
191
|
const { readable, writable } = new TransformStream();
|
|
@@ -192,27 +214,318 @@ var stream = (c, cb, onError) => {
|
|
|
192
214
|
return c.newResponse(stream2.responseReadable);
|
|
193
215
|
};
|
|
194
216
|
|
|
195
|
-
//
|
|
196
|
-
var
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
217
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
218
|
+
var util;
|
|
219
|
+
(function(util2) {
|
|
220
|
+
util2.assertEqual = (_) => {
|
|
221
|
+
};
|
|
222
|
+
function assertIs(_arg) {
|
|
223
|
+
}
|
|
224
|
+
util2.assertIs = assertIs;
|
|
225
|
+
function assertNever(_x) {
|
|
226
|
+
throw new Error();
|
|
227
|
+
}
|
|
228
|
+
util2.assertNever = assertNever;
|
|
229
|
+
util2.arrayToEnum = (items) => {
|
|
230
|
+
const obj = {};
|
|
231
|
+
for (const item of items) {
|
|
232
|
+
obj[item] = item;
|
|
233
|
+
}
|
|
234
|
+
return obj;
|
|
235
|
+
};
|
|
236
|
+
util2.getValidEnumValues = (obj) => {
|
|
237
|
+
const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
|
|
238
|
+
const filtered = {};
|
|
239
|
+
for (const k of validKeys) {
|
|
240
|
+
filtered[k] = obj[k];
|
|
241
|
+
}
|
|
242
|
+
return util2.objectValues(filtered);
|
|
243
|
+
};
|
|
244
|
+
util2.objectValues = (obj) => {
|
|
245
|
+
return util2.objectKeys(obj).map(function(e) {
|
|
246
|
+
return obj[e];
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
|
|
250
|
+
const keys = [];
|
|
251
|
+
for (const key in object) {
|
|
252
|
+
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
253
|
+
keys.push(key);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return keys;
|
|
257
|
+
};
|
|
258
|
+
util2.find = (arr, checker) => {
|
|
259
|
+
for (const item of arr) {
|
|
260
|
+
if (checker(item))
|
|
261
|
+
return item;
|
|
262
|
+
}
|
|
263
|
+
return void 0;
|
|
264
|
+
};
|
|
265
|
+
util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
|
|
266
|
+
function joinValues(array, separator = " | ") {
|
|
267
|
+
return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
|
|
268
|
+
}
|
|
269
|
+
util2.joinValues = joinValues;
|
|
270
|
+
util2.jsonStringifyReplacer = (_, value) => {
|
|
271
|
+
if (typeof value === "bigint") {
|
|
272
|
+
return value.toString();
|
|
273
|
+
}
|
|
274
|
+
return value;
|
|
275
|
+
};
|
|
276
|
+
})(util || (util = {}));
|
|
277
|
+
var objectUtil;
|
|
278
|
+
(function(objectUtil2) {
|
|
279
|
+
objectUtil2.mergeShapes = (first, second) => {
|
|
280
|
+
return {
|
|
281
|
+
...first,
|
|
282
|
+
...second
|
|
283
|
+
// second overwrites first
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
})(objectUtil || (objectUtil = {}));
|
|
287
|
+
util.arrayToEnum([
|
|
288
|
+
"string",
|
|
289
|
+
"nan",
|
|
290
|
+
"number",
|
|
291
|
+
"integer",
|
|
292
|
+
"float",
|
|
293
|
+
"boolean",
|
|
294
|
+
"date",
|
|
295
|
+
"bigint",
|
|
296
|
+
"symbol",
|
|
297
|
+
"function",
|
|
298
|
+
"undefined",
|
|
299
|
+
"null",
|
|
300
|
+
"array",
|
|
301
|
+
"object",
|
|
302
|
+
"unknown",
|
|
303
|
+
"promise",
|
|
304
|
+
"void",
|
|
305
|
+
"never",
|
|
306
|
+
"map",
|
|
307
|
+
"set"
|
|
308
|
+
]);
|
|
309
|
+
|
|
310
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
|
|
311
|
+
util.arrayToEnum([
|
|
312
|
+
"invalid_type",
|
|
313
|
+
"invalid_literal",
|
|
314
|
+
"custom",
|
|
315
|
+
"invalid_union",
|
|
316
|
+
"invalid_union_discriminator",
|
|
317
|
+
"invalid_enum_value",
|
|
318
|
+
"unrecognized_keys",
|
|
319
|
+
"invalid_arguments",
|
|
320
|
+
"invalid_return_type",
|
|
321
|
+
"invalid_date",
|
|
322
|
+
"invalid_string",
|
|
323
|
+
"too_small",
|
|
324
|
+
"too_big",
|
|
325
|
+
"invalid_intersection_types",
|
|
326
|
+
"not_multiple_of",
|
|
327
|
+
"not_finite"
|
|
328
|
+
]);
|
|
329
|
+
var ZodError = class _ZodError extends Error {
|
|
330
|
+
get errors() {
|
|
331
|
+
return this.issues;
|
|
332
|
+
}
|
|
333
|
+
constructor(issues) {
|
|
334
|
+
super();
|
|
335
|
+
this.issues = [];
|
|
336
|
+
this.addIssue = (sub) => {
|
|
337
|
+
this.issues = [...this.issues, sub];
|
|
338
|
+
};
|
|
339
|
+
this.addIssues = (subs = []) => {
|
|
340
|
+
this.issues = [...this.issues, ...subs];
|
|
341
|
+
};
|
|
342
|
+
const actualProto = new.target.prototype;
|
|
343
|
+
if (Object.setPrototypeOf) {
|
|
344
|
+
Object.setPrototypeOf(this, actualProto);
|
|
345
|
+
} else {
|
|
346
|
+
this.__proto__ = actualProto;
|
|
347
|
+
}
|
|
348
|
+
this.name = "ZodError";
|
|
349
|
+
this.issues = issues;
|
|
350
|
+
}
|
|
351
|
+
format(_mapper) {
|
|
352
|
+
const mapper = _mapper || function(issue) {
|
|
353
|
+
return issue.message;
|
|
354
|
+
};
|
|
355
|
+
const fieldErrors = { _errors: [] };
|
|
356
|
+
const processError = (error) => {
|
|
357
|
+
for (const issue of error.issues) {
|
|
358
|
+
if (issue.code === "invalid_union") {
|
|
359
|
+
issue.unionErrors.map(processError);
|
|
360
|
+
} else if (issue.code === "invalid_return_type") {
|
|
361
|
+
processError(issue.returnTypeError);
|
|
362
|
+
} else if (issue.code === "invalid_arguments") {
|
|
363
|
+
processError(issue.argumentsError);
|
|
364
|
+
} else if (issue.path.length === 0) {
|
|
365
|
+
fieldErrors._errors.push(mapper(issue));
|
|
366
|
+
} else {
|
|
367
|
+
let curr = fieldErrors;
|
|
368
|
+
let i = 0;
|
|
369
|
+
while (i < issue.path.length) {
|
|
370
|
+
const el = issue.path[i];
|
|
371
|
+
const terminal = i === issue.path.length - 1;
|
|
372
|
+
if (!terminal) {
|
|
373
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
374
|
+
} else {
|
|
375
|
+
curr[el] = curr[el] || { _errors: [] };
|
|
376
|
+
curr[el]._errors.push(mapper(issue));
|
|
377
|
+
}
|
|
378
|
+
curr = curr[el];
|
|
379
|
+
i++;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
processError(this);
|
|
385
|
+
return fieldErrors;
|
|
386
|
+
}
|
|
387
|
+
static assert(value) {
|
|
388
|
+
if (!(value instanceof _ZodError)) {
|
|
389
|
+
throw new Error(`Not a ZodError: ${value}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
toString() {
|
|
393
|
+
return this.message;
|
|
394
|
+
}
|
|
395
|
+
get message() {
|
|
396
|
+
return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
|
|
397
|
+
}
|
|
398
|
+
get isEmpty() {
|
|
399
|
+
return this.issues.length === 0;
|
|
400
|
+
}
|
|
401
|
+
flatten(mapper = (issue) => issue.message) {
|
|
402
|
+
const fieldErrors = {};
|
|
403
|
+
const formErrors = [];
|
|
404
|
+
for (const sub of this.issues) {
|
|
405
|
+
if (sub.path.length > 0) {
|
|
406
|
+
const firstEl = sub.path[0];
|
|
407
|
+
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
|
|
408
|
+
fieldErrors[firstEl].push(mapper(sub));
|
|
409
|
+
} else {
|
|
410
|
+
formErrors.push(mapper(sub));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return { formErrors, fieldErrors };
|
|
414
|
+
}
|
|
415
|
+
get formErrors() {
|
|
416
|
+
return this.flatten();
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
ZodError.create = (issues) => {
|
|
420
|
+
const error = new ZodError(issues);
|
|
421
|
+
return error;
|
|
422
|
+
};
|
|
423
|
+
var authenticationMiddleware = async (c, next) => {
|
|
424
|
+
const mastra = c.get("mastra");
|
|
425
|
+
const authConfig = mastra.getServer()?.auth;
|
|
426
|
+
const customRouteAuthConfig = c.get("customRouteAuthConfig");
|
|
427
|
+
if (!authConfig) {
|
|
428
|
+
return next();
|
|
429
|
+
}
|
|
430
|
+
const path = c.req.path;
|
|
431
|
+
const method = c.req.method;
|
|
432
|
+
const getHeader = (name) => c.req.header(name);
|
|
433
|
+
if (auth.isDevPlaygroundRequest(path, method, getHeader, authConfig, customRouteAuthConfig)) {
|
|
434
|
+
return next();
|
|
435
|
+
}
|
|
436
|
+
if (!auth.isProtectedPath(c.req.path, c.req.method, authConfig, customRouteAuthConfig)) {
|
|
437
|
+
return next();
|
|
438
|
+
}
|
|
439
|
+
if (auth.canAccessPublicly(c.req.path, c.req.method, authConfig)) {
|
|
440
|
+
return next();
|
|
441
|
+
}
|
|
442
|
+
const authHeader = c.req.header("Authorization");
|
|
443
|
+
let token = authHeader ? authHeader.replace("Bearer ", "") : null;
|
|
444
|
+
if (!token && c.req.query("apiKey")) {
|
|
445
|
+
token = c.req.query("apiKey") || null;
|
|
446
|
+
}
|
|
447
|
+
if (!token) {
|
|
448
|
+
return c.json({ error: "Authentication required" }, 401);
|
|
449
|
+
}
|
|
450
|
+
try {
|
|
451
|
+
let user;
|
|
452
|
+
if (typeof authConfig.authenticateToken === "function") {
|
|
453
|
+
user = await authConfig.authenticateToken(token, c.req);
|
|
454
|
+
} else {
|
|
455
|
+
throw new Error("No token verification method configured");
|
|
456
|
+
}
|
|
457
|
+
if (!user) {
|
|
458
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
459
|
+
}
|
|
460
|
+
c.get("requestContext").set("user", user);
|
|
461
|
+
return next();
|
|
462
|
+
} catch (err) {
|
|
463
|
+
console.error(err);
|
|
464
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
var authorizationMiddleware = async (c, next) => {
|
|
468
|
+
const mastra = c.get("mastra");
|
|
469
|
+
const authConfig = mastra.getServer()?.auth;
|
|
470
|
+
const customRouteAuthConfig = c.get("customRouteAuthConfig");
|
|
471
|
+
if (!authConfig) {
|
|
472
|
+
return next();
|
|
215
473
|
}
|
|
474
|
+
const path = c.req.path;
|
|
475
|
+
const method = c.req.method;
|
|
476
|
+
const getHeader = (name) => c.req.header(name);
|
|
477
|
+
if (auth.isDevPlaygroundRequest(path, method, getHeader, authConfig, customRouteAuthConfig)) {
|
|
478
|
+
return next();
|
|
479
|
+
}
|
|
480
|
+
if (!auth.isProtectedPath(c.req.path, c.req.method, authConfig, customRouteAuthConfig)) {
|
|
481
|
+
return next();
|
|
482
|
+
}
|
|
483
|
+
if (auth.canAccessPublicly(path, method, authConfig)) {
|
|
484
|
+
return next();
|
|
485
|
+
}
|
|
486
|
+
const user = c.get("requestContext").get("user");
|
|
487
|
+
if ("authorizeUser" in authConfig && typeof authConfig.authorizeUser === "function") {
|
|
488
|
+
try {
|
|
489
|
+
const isAuthorized = await authConfig.authorizeUser(user, c.req);
|
|
490
|
+
if (isAuthorized) {
|
|
491
|
+
return next();
|
|
492
|
+
}
|
|
493
|
+
return c.json({ error: "Access denied" }, 403);
|
|
494
|
+
} catch (err) {
|
|
495
|
+
console.error(err);
|
|
496
|
+
return c.json({ error: "Authorization error" }, 500);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if ("authorize" in authConfig && typeof authConfig.authorize === "function") {
|
|
500
|
+
try {
|
|
501
|
+
const isAuthorized = await authConfig.authorize(path, method, user, c);
|
|
502
|
+
if (isAuthorized) {
|
|
503
|
+
return next();
|
|
504
|
+
}
|
|
505
|
+
return c.json({ error: "Access denied" }, 403);
|
|
506
|
+
} catch (err) {
|
|
507
|
+
console.error(err);
|
|
508
|
+
return c.json({ error: "Authorization error" }, 500);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if ("rules" in authConfig && authConfig.rules && authConfig.rules.length > 0) {
|
|
512
|
+
const isAuthorized = await auth.checkRules(authConfig.rules, path, method, user);
|
|
513
|
+
if (isAuthorized) {
|
|
514
|
+
return next();
|
|
515
|
+
}
|
|
516
|
+
return c.json({ error: "Access denied" }, 403);
|
|
517
|
+
}
|
|
518
|
+
if (auth.defaultAuthConfig.rules && auth.defaultAuthConfig.rules.length > 0) {
|
|
519
|
+
const isAuthorized = await auth.checkRules(auth.defaultAuthConfig.rules, path, method, user);
|
|
520
|
+
if (isAuthorized) {
|
|
521
|
+
return next();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return c.json({ error: "Access denied" }, 403);
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/index.ts
|
|
528
|
+
var MastraServer = class extends serverAdapter.MastraServer {
|
|
216
529
|
createContextMiddleware() {
|
|
217
530
|
return async (c, next) => {
|
|
218
531
|
let bodyRequestContext;
|
|
@@ -250,12 +563,10 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
250
563
|
const requestContext = this.mergeRequestContext({ paramsRequestContext, bodyRequestContext });
|
|
251
564
|
c.set("requestContext", requestContext);
|
|
252
565
|
c.set("mastra", this.mastra);
|
|
253
|
-
c.set("
|
|
566
|
+
c.set("registeredTools", this.tools || {});
|
|
254
567
|
c.set("taskStore", this.taskStore);
|
|
255
|
-
c.set("playground", this.playground === true);
|
|
256
|
-
c.set("isDev", this.isDev === true);
|
|
257
|
-
c.set("customRouteAuthConfig", this.customRouteAuthConfig);
|
|
258
568
|
c.set("abortSignal", c.req.raw.signal);
|
|
569
|
+
c.set("customRouteAuthConfig", this.customRouteAuthConfig);
|
|
259
570
|
return next();
|
|
260
571
|
};
|
|
261
572
|
}
|
|
@@ -276,12 +587,14 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
276
587
|
const { done, value } = await reader.read();
|
|
277
588
|
if (done) break;
|
|
278
589
|
if (value) {
|
|
590
|
+
const shouldRedact = this.streamOptions?.redact ?? true;
|
|
591
|
+
const outputValue = shouldRedact ? serverAdapter.redactStreamChunk(value) : value;
|
|
279
592
|
if (streamFormat === "sse") {
|
|
280
|
-
await stream2.write(`data: ${JSON.stringify(
|
|
593
|
+
await stream2.write(`data: ${JSON.stringify(outputValue)}
|
|
281
594
|
|
|
282
595
|
`);
|
|
283
596
|
} else {
|
|
284
|
-
await stream2.write(JSON.stringify(
|
|
597
|
+
await stream2.write(JSON.stringify(outputValue) + "");
|
|
285
598
|
}
|
|
286
599
|
}
|
|
287
600
|
}
|
|
@@ -299,17 +612,64 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
299
612
|
}
|
|
300
613
|
async getParams(route, request) {
|
|
301
614
|
const urlParams = request.param();
|
|
302
|
-
const queryParams = request.
|
|
615
|
+
const queryParams = serverAdapter.normalizeQueryParams(request.queries());
|
|
303
616
|
let body;
|
|
617
|
+
let bodyParseError;
|
|
304
618
|
if (route.method === "POST" || route.method === "PUT" || route.method === "PATCH") {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
619
|
+
const contentType = request.header("content-type") || "";
|
|
620
|
+
if (contentType.includes("multipart/form-data")) {
|
|
621
|
+
try {
|
|
622
|
+
const formData = await request.formData();
|
|
623
|
+
body = await this.parseFormData(formData);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
console.error("Failed to parse multipart form data:", error);
|
|
626
|
+
if (error instanceof Error && error.message.toLowerCase().includes("size")) {
|
|
627
|
+
throw error;
|
|
628
|
+
}
|
|
629
|
+
bodyParseError = {
|
|
630
|
+
message: error instanceof Error ? error.message : "Failed to parse multipart form data"
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
} else if (contentType.includes("application/json")) {
|
|
634
|
+
const clonedReq = request.raw.clone();
|
|
635
|
+
const bodyText = await clonedReq.text();
|
|
636
|
+
if (bodyText && bodyText.trim().length > 0) {
|
|
637
|
+
try {
|
|
638
|
+
body = JSON.parse(bodyText);
|
|
639
|
+
} catch (error) {
|
|
640
|
+
console.error("Failed to parse JSON body:", error);
|
|
641
|
+
bodyParseError = {
|
|
642
|
+
message: error instanceof Error ? error.message : "Invalid JSON in request body"
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return { urlParams, queryParams, body, bodyParseError };
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Parse FormData into a plain object, converting File objects to Buffers.
|
|
652
|
+
*/
|
|
653
|
+
async parseFormData(formData) {
|
|
654
|
+
const result = {};
|
|
655
|
+
for (const [key, value] of formData.entries()) {
|
|
656
|
+
if (value instanceof File) {
|
|
657
|
+
const arrayBuffer = await value.arrayBuffer();
|
|
658
|
+
result[key] = Buffer.from(arrayBuffer);
|
|
659
|
+
} else if (typeof value === "string") {
|
|
660
|
+
try {
|
|
661
|
+
result[key] = JSON.parse(value);
|
|
662
|
+
} catch {
|
|
663
|
+
result[key] = value;
|
|
664
|
+
}
|
|
665
|
+
} else {
|
|
666
|
+
result[key] = value;
|
|
308
667
|
}
|
|
309
668
|
}
|
|
310
|
-
return
|
|
669
|
+
return result;
|
|
311
670
|
}
|
|
312
|
-
async sendResponse(route, response, result) {
|
|
671
|
+
async sendResponse(route, response, result, prefix) {
|
|
672
|
+
const resolvedPrefix = prefix ?? this.prefix ?? "";
|
|
313
673
|
if (route.responseType === "json") {
|
|
314
674
|
return response.json(result, 200);
|
|
315
675
|
} else if (route.responseType === "stream") {
|
|
@@ -317,11 +677,51 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
317
677
|
} else if (route.responseType === "datastream-response") {
|
|
318
678
|
const fetchResponse = result;
|
|
319
679
|
return fetchResponse;
|
|
680
|
+
} else if (route.responseType === "mcp-http") {
|
|
681
|
+
const { server, httpPath, mcpOptions: routeMcpOptions } = result;
|
|
682
|
+
const { req, res } = fetchToNode.toReqRes(response.req.raw);
|
|
683
|
+
try {
|
|
684
|
+
const options = { ...this.mcpOptions, ...routeMcpOptions };
|
|
685
|
+
await server.startHTTP({
|
|
686
|
+
url: new URL(response.req.url),
|
|
687
|
+
httpPath: `${resolvedPrefix}${httpPath}`,
|
|
688
|
+
req,
|
|
689
|
+
res,
|
|
690
|
+
options: Object.keys(options).length > 0 ? options : void 0
|
|
691
|
+
});
|
|
692
|
+
return await fetchToNode.toFetchResponse(res);
|
|
693
|
+
} catch {
|
|
694
|
+
if (!res.headersSent) {
|
|
695
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
696
|
+
res.end(
|
|
697
|
+
JSON.stringify({
|
|
698
|
+
jsonrpc: "2.0",
|
|
699
|
+
error: { code: -32603, message: "Internal server error" },
|
|
700
|
+
id: null
|
|
701
|
+
})
|
|
702
|
+
);
|
|
703
|
+
return await fetchToNode.toFetchResponse(res);
|
|
704
|
+
}
|
|
705
|
+
return await fetchToNode.toFetchResponse(res);
|
|
706
|
+
}
|
|
707
|
+
} else if (route.responseType === "mcp-sse") {
|
|
708
|
+
const { server, ssePath, messagePath } = result;
|
|
709
|
+
try {
|
|
710
|
+
return await server.startHonoSSE({
|
|
711
|
+
url: new URL(response.req.url),
|
|
712
|
+
ssePath: `${resolvedPrefix}${ssePath}`,
|
|
713
|
+
messagePath: `${resolvedPrefix}${messagePath}`,
|
|
714
|
+
context: response
|
|
715
|
+
});
|
|
716
|
+
} catch {
|
|
717
|
+
return response.json({ error: "Error handling MCP SSE request" }, 500);
|
|
718
|
+
}
|
|
320
719
|
} else {
|
|
321
720
|
return response.status(500);
|
|
322
721
|
}
|
|
323
722
|
}
|
|
324
|
-
async registerRoute(app, route, { prefix }) {
|
|
723
|
+
async registerRoute(app, route, { prefix: prefixParam } = {}) {
|
|
724
|
+
const prefix = prefixParam ?? this.prefix ?? "";
|
|
325
725
|
const shouldApplyBodyLimit = this.bodyLimitOptions && ["POST", "PUT", "PATCH"].includes(route.method.toUpperCase());
|
|
326
726
|
const maxSize = route.maxBodySize ?? this.bodyLimitOptions?.maxSize;
|
|
327
727
|
const middlewares = [];
|
|
@@ -337,16 +737,38 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
337
737
|
`${prefix}${route.path}`,
|
|
338
738
|
...middlewares,
|
|
339
739
|
async (c) => {
|
|
740
|
+
const authError = await this.checkRouteAuth(route, {
|
|
741
|
+
path: c.req.path,
|
|
742
|
+
method: c.req.method,
|
|
743
|
+
getHeader: (name) => c.req.header(name),
|
|
744
|
+
getQuery: (name) => c.req.query(name),
|
|
745
|
+
requestContext: c.get("requestContext")
|
|
746
|
+
});
|
|
747
|
+
if (authError) {
|
|
748
|
+
return c.json({ error: authError.error }, authError.status);
|
|
749
|
+
}
|
|
340
750
|
const params = await this.getParams(route, c.req);
|
|
751
|
+
if (params.bodyParseError) {
|
|
752
|
+
return c.json(
|
|
753
|
+
{
|
|
754
|
+
error: "Invalid request body",
|
|
755
|
+
issues: [{ field: "body", message: params.bodyParseError.message }]
|
|
756
|
+
},
|
|
757
|
+
400
|
|
758
|
+
);
|
|
759
|
+
}
|
|
341
760
|
if (params.queryParams) {
|
|
342
761
|
try {
|
|
343
762
|
params.queryParams = await this.parseQueryParams(route, params.queryParams);
|
|
344
|
-
} catch (error) {
|
|
345
|
-
console.error("Error parsing query params", error);
|
|
763
|
+
} catch (error$1) {
|
|
764
|
+
console.error("Error parsing query params", error$1);
|
|
765
|
+
if (error$1 instanceof ZodError) {
|
|
766
|
+
return c.json(error.formatZodError(error$1, "query parameters"), 400);
|
|
767
|
+
}
|
|
346
768
|
return c.json(
|
|
347
769
|
{
|
|
348
770
|
error: "Invalid query parameters",
|
|
349
|
-
|
|
771
|
+
issues: [{ field: "unknown", message: error$1 instanceof Error ? error$1.message : "Unknown error" }]
|
|
350
772
|
},
|
|
351
773
|
400
|
|
352
774
|
);
|
|
@@ -355,12 +777,15 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
355
777
|
if (params.body) {
|
|
356
778
|
try {
|
|
357
779
|
params.body = await this.parseBody(route, params.body);
|
|
358
|
-
} catch (error) {
|
|
359
|
-
console.error("Error parsing body", error);
|
|
780
|
+
} catch (error$1) {
|
|
781
|
+
console.error("Error parsing body:", error$1 instanceof Error ? error$1.message : String(error$1));
|
|
782
|
+
if (error$1 instanceof ZodError) {
|
|
783
|
+
return c.json(error.formatZodError(error$1, "request body"), 400);
|
|
784
|
+
}
|
|
360
785
|
return c.json(
|
|
361
786
|
{
|
|
362
787
|
error: "Invalid request body",
|
|
363
|
-
|
|
788
|
+
issues: [{ field: "unknown", message: error$1 instanceof Error ? error$1.message : "Unknown error" }]
|
|
364
789
|
},
|
|
365
790
|
400
|
|
366
791
|
);
|
|
@@ -372,13 +797,14 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
372
797
|
...typeof params.body === "object" ? params.body : {},
|
|
373
798
|
requestContext: c.get("requestContext"),
|
|
374
799
|
mastra: this.mastra,
|
|
375
|
-
|
|
800
|
+
registeredTools: c.get("registeredTools"),
|
|
376
801
|
taskStore: c.get("taskStore"),
|
|
377
|
-
abortSignal: c.get("abortSignal")
|
|
802
|
+
abortSignal: c.get("abortSignal"),
|
|
803
|
+
routePrefix: prefix
|
|
378
804
|
};
|
|
379
805
|
try {
|
|
380
806
|
const result = await route.handler(handlerParams);
|
|
381
|
-
return this.sendResponse(route, c, result);
|
|
807
|
+
return this.sendResponse(route, c, result, prefix);
|
|
382
808
|
} catch (error) {
|
|
383
809
|
console.error("Error calling handler", error);
|
|
384
810
|
if (error && typeof error === "object") {
|
|
@@ -396,14 +822,19 @@ var HonoServerAdapter = class extends serverAdapter.MastraServerAdapter {
|
|
|
396
822
|
}
|
|
397
823
|
);
|
|
398
824
|
}
|
|
399
|
-
registerContextMiddleware(
|
|
400
|
-
app.use("*", this.createContextMiddleware());
|
|
825
|
+
registerContextMiddleware() {
|
|
826
|
+
this.app.use("*", this.createContextMiddleware());
|
|
401
827
|
}
|
|
402
|
-
|
|
403
|
-
|
|
828
|
+
registerAuthMiddleware() {
|
|
829
|
+
const authConfig = this.mastra.getServer()?.auth;
|
|
830
|
+
if (!authConfig) {
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
this.app.use("*", authenticationMiddleware);
|
|
834
|
+
this.app.use("*", authorizationMiddleware);
|
|
404
835
|
}
|
|
405
836
|
};
|
|
406
837
|
|
|
407
|
-
exports.
|
|
838
|
+
exports.MastraServer = MastraServer;
|
|
408
839
|
//# sourceMappingURL=index.cjs.map
|
|
409
840
|
//# sourceMappingURL=index.cjs.map
|