@mastra/express 0.0.0-main-test-2-20251127211532 → 0.0.0-mastra-auto-detect-server-20260108233416

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/dist/index.js CHANGED
@@ -1,27 +1,333 @@
1
- import { InMemoryTaskStore } from '@mastra/server/a2a/store';
2
- import { MastraServerAdapter } from '@mastra/server/server-adapter';
1
+ import { Busboy } from '@fastify/busboy';
2
+ import { formatZodError } from '@mastra/server/handlers/error';
3
+ import { MastraServer as MastraServer$1, redactStreamChunk, normalizeQueryParams } from '@mastra/server/server-adapter';
4
+ import { isDevPlaygroundRequest, isProtectedPath, canAccessPublicly, checkRules, defaultAuthConfig } from '@mastra/server/auth';
3
5
 
4
6
  // src/index.ts
5
- var ExpressServerAdapter = class extends MastraServerAdapter {
6
- taskStore;
7
- customRouteAuthConfig;
8
- playground;
9
- isDev;
10
- constructor({
11
- mastra,
12
- tools,
13
- taskStore,
14
- customRouteAuthConfig,
15
- playground,
16
- isDev,
17
- bodyLimitOptions
18
- }) {
19
- super({ mastra, bodyLimitOptions, tools });
20
- this.taskStore = taskStore || new InMemoryTaskStore();
21
- this.customRouteAuthConfig = customRouteAuthConfig;
22
- this.playground = playground;
23
- this.isDev = isDev;
7
+
8
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
9
+ var util;
10
+ (function(util2) {
11
+ util2.assertEqual = (_) => {
12
+ };
13
+ function assertIs(_arg) {
14
+ }
15
+ util2.assertIs = assertIs;
16
+ function assertNever(_x) {
17
+ throw new Error();
18
+ }
19
+ util2.assertNever = assertNever;
20
+ util2.arrayToEnum = (items) => {
21
+ const obj = {};
22
+ for (const item of items) {
23
+ obj[item] = item;
24
+ }
25
+ return obj;
26
+ };
27
+ util2.getValidEnumValues = (obj) => {
28
+ const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
29
+ const filtered = {};
30
+ for (const k of validKeys) {
31
+ filtered[k] = obj[k];
32
+ }
33
+ return util2.objectValues(filtered);
34
+ };
35
+ util2.objectValues = (obj) => {
36
+ return util2.objectKeys(obj).map(function(e) {
37
+ return obj[e];
38
+ });
39
+ };
40
+ util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
41
+ const keys = [];
42
+ for (const key in object) {
43
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
44
+ keys.push(key);
45
+ }
46
+ }
47
+ return keys;
48
+ };
49
+ util2.find = (arr, checker) => {
50
+ for (const item of arr) {
51
+ if (checker(item))
52
+ return item;
53
+ }
54
+ return void 0;
55
+ };
56
+ util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
57
+ function joinValues(array, separator = " | ") {
58
+ return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
59
+ }
60
+ util2.joinValues = joinValues;
61
+ util2.jsonStringifyReplacer = (_, value) => {
62
+ if (typeof value === "bigint") {
63
+ return value.toString();
64
+ }
65
+ return value;
66
+ };
67
+ })(util || (util = {}));
68
+ var objectUtil;
69
+ (function(objectUtil2) {
70
+ objectUtil2.mergeShapes = (first, second) => {
71
+ return {
72
+ ...first,
73
+ ...second
74
+ // second overwrites first
75
+ };
76
+ };
77
+ })(objectUtil || (objectUtil = {}));
78
+ util.arrayToEnum([
79
+ "string",
80
+ "nan",
81
+ "number",
82
+ "integer",
83
+ "float",
84
+ "boolean",
85
+ "date",
86
+ "bigint",
87
+ "symbol",
88
+ "function",
89
+ "undefined",
90
+ "null",
91
+ "array",
92
+ "object",
93
+ "unknown",
94
+ "promise",
95
+ "void",
96
+ "never",
97
+ "map",
98
+ "set"
99
+ ]);
100
+
101
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
102
+ util.arrayToEnum([
103
+ "invalid_type",
104
+ "invalid_literal",
105
+ "custom",
106
+ "invalid_union",
107
+ "invalid_union_discriminator",
108
+ "invalid_enum_value",
109
+ "unrecognized_keys",
110
+ "invalid_arguments",
111
+ "invalid_return_type",
112
+ "invalid_date",
113
+ "invalid_string",
114
+ "too_small",
115
+ "too_big",
116
+ "invalid_intersection_types",
117
+ "not_multiple_of",
118
+ "not_finite"
119
+ ]);
120
+ var ZodError = class _ZodError extends Error {
121
+ get errors() {
122
+ return this.issues;
123
+ }
124
+ constructor(issues) {
125
+ super();
126
+ this.issues = [];
127
+ this.addIssue = (sub) => {
128
+ this.issues = [...this.issues, sub];
129
+ };
130
+ this.addIssues = (subs = []) => {
131
+ this.issues = [...this.issues, ...subs];
132
+ };
133
+ const actualProto = new.target.prototype;
134
+ if (Object.setPrototypeOf) {
135
+ Object.setPrototypeOf(this, actualProto);
136
+ } else {
137
+ this.__proto__ = actualProto;
138
+ }
139
+ this.name = "ZodError";
140
+ this.issues = issues;
141
+ }
142
+ format(_mapper) {
143
+ const mapper = _mapper || function(issue) {
144
+ return issue.message;
145
+ };
146
+ const fieldErrors = { _errors: [] };
147
+ const processError = (error) => {
148
+ for (const issue of error.issues) {
149
+ if (issue.code === "invalid_union") {
150
+ issue.unionErrors.map(processError);
151
+ } else if (issue.code === "invalid_return_type") {
152
+ processError(issue.returnTypeError);
153
+ } else if (issue.code === "invalid_arguments") {
154
+ processError(issue.argumentsError);
155
+ } else if (issue.path.length === 0) {
156
+ fieldErrors._errors.push(mapper(issue));
157
+ } else {
158
+ let curr = fieldErrors;
159
+ let i = 0;
160
+ while (i < issue.path.length) {
161
+ const el = issue.path[i];
162
+ const terminal = i === issue.path.length - 1;
163
+ if (!terminal) {
164
+ curr[el] = curr[el] || { _errors: [] };
165
+ } else {
166
+ curr[el] = curr[el] || { _errors: [] };
167
+ curr[el]._errors.push(mapper(issue));
168
+ }
169
+ curr = curr[el];
170
+ i++;
171
+ }
172
+ }
173
+ }
174
+ };
175
+ processError(this);
176
+ return fieldErrors;
177
+ }
178
+ static assert(value) {
179
+ if (!(value instanceof _ZodError)) {
180
+ throw new Error(`Not a ZodError: ${value}`);
181
+ }
182
+ }
183
+ toString() {
184
+ return this.message;
185
+ }
186
+ get message() {
187
+ return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
188
+ }
189
+ get isEmpty() {
190
+ return this.issues.length === 0;
191
+ }
192
+ flatten(mapper = (issue) => issue.message) {
193
+ const fieldErrors = {};
194
+ const formErrors = [];
195
+ for (const sub of this.issues) {
196
+ if (sub.path.length > 0) {
197
+ const firstEl = sub.path[0];
198
+ fieldErrors[firstEl] = fieldErrors[firstEl] || [];
199
+ fieldErrors[firstEl].push(mapper(sub));
200
+ } else {
201
+ formErrors.push(mapper(sub));
202
+ }
203
+ }
204
+ return { formErrors, fieldErrors };
205
+ }
206
+ get formErrors() {
207
+ return this.flatten();
208
+ }
209
+ };
210
+ ZodError.create = (issues) => {
211
+ const error = new ZodError(issues);
212
+ return error;
213
+ };
214
+ var authenticationMiddleware = async (req, res, next) => {
215
+ const mastra = res.locals.mastra;
216
+ const authConfig = mastra.getServer()?.auth;
217
+ const customRouteAuthConfig = res.locals.customRouteAuthConfig;
218
+ if (!authConfig) {
219
+ return next();
220
+ }
221
+ const path = req.path;
222
+ const method = req.method;
223
+ const getHeader = (name) => req.headers[name.toLowerCase()];
224
+ if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {
225
+ return next();
226
+ }
227
+ if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {
228
+ return next();
229
+ }
230
+ if (canAccessPublicly(req.path, req.method, authConfig)) {
231
+ return next();
232
+ }
233
+ const authHeader = req.headers.authorization;
234
+ let token = authHeader ? authHeader.replace("Bearer ", "") : null;
235
+ if (!token && req.query.apiKey) {
236
+ token = req.query.apiKey || null;
237
+ }
238
+ if (!token) {
239
+ return res.status(401).json({ error: "Authentication required" });
240
+ }
241
+ try {
242
+ let user;
243
+ if (typeof authConfig.authenticateToken === "function") {
244
+ user = await authConfig.authenticateToken(token, req);
245
+ } else {
246
+ throw new Error("No token verification method configured");
247
+ }
248
+ if (!user) {
249
+ return res.status(401).json({ error: "Invalid or expired token" });
250
+ }
251
+ res.locals.requestContext.set("user", user);
252
+ return next();
253
+ } catch (err) {
254
+ console.error(err);
255
+ return res.status(401).json({ error: "Invalid or expired token" });
256
+ }
257
+ };
258
+ var authorizationMiddleware = async (req, res, next) => {
259
+ const mastra = res.locals.mastra;
260
+ const authConfig = mastra.getServer()?.auth;
261
+ const customRouteAuthConfig = res.locals.customRouteAuthConfig;
262
+ if (!authConfig) {
263
+ return next();
24
264
  }
265
+ const path = req.path;
266
+ const method = req.method;
267
+ const getHeader = (name) => req.headers[name.toLowerCase()];
268
+ if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {
269
+ return next();
270
+ }
271
+ if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {
272
+ return next();
273
+ }
274
+ if (canAccessPublicly(path, method, authConfig)) {
275
+ return next();
276
+ }
277
+ const user = res.locals.requestContext.get("user");
278
+ if ("authorizeUser" in authConfig && typeof authConfig.authorizeUser === "function") {
279
+ try {
280
+ const isAuthorized = await authConfig.authorizeUser(user, req);
281
+ if (isAuthorized) {
282
+ return next();
283
+ }
284
+ return res.status(403).json({ error: "Access denied" });
285
+ } catch (err) {
286
+ console.error(err);
287
+ return res.status(500).json({ error: "Authorization error" });
288
+ }
289
+ }
290
+ if ("authorize" in authConfig && typeof authConfig.authorize === "function") {
291
+ try {
292
+ const context = {
293
+ get: (key) => {
294
+ if (key === "mastra") return res.locals.mastra;
295
+ if (key === "requestContext") return res.locals.requestContext;
296
+ if (key === "tools") return res.locals.tools;
297
+ if (key === "taskStore") return res.locals.taskStore;
298
+ if (key === "customRouteAuthConfig") return res.locals.customRouteAuthConfig;
299
+ return void 0;
300
+ },
301
+ req
302
+ };
303
+ const isAuthorized = await authConfig.authorize(path, method, user, context);
304
+ if (isAuthorized) {
305
+ return next();
306
+ }
307
+ return res.status(403).json({ error: "Access denied" });
308
+ } catch (err) {
309
+ console.error(err);
310
+ return res.status(500).json({ error: "Authorization error" });
311
+ }
312
+ }
313
+ if ("rules" in authConfig && authConfig.rules && authConfig.rules.length > 0) {
314
+ const isAuthorized = await checkRules(authConfig.rules, path, method, user);
315
+ if (isAuthorized) {
316
+ return next();
317
+ }
318
+ return res.status(403).json({ error: "Access denied" });
319
+ }
320
+ if (defaultAuthConfig.rules && defaultAuthConfig.rules.length > 0) {
321
+ const isAuthorized = await checkRules(defaultAuthConfig.rules, path, method, user);
322
+ if (isAuthorized) {
323
+ return next();
324
+ }
325
+ }
326
+ return res.status(403).json({ error: "Access denied" });
327
+ };
328
+
329
+ // src/index.ts
330
+ var MastraServer = class extends MastraServer$1 {
25
331
  createContextMiddleware() {
26
332
  return async (req, res, next) => {
27
333
  let bodyRequestContext;
@@ -55,13 +361,15 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
55
361
  res.locals.requestContext = requestContext;
56
362
  res.locals.mastra = this.mastra;
57
363
  res.locals.tools = this.tools || {};
58
- res.locals.taskStore = this.taskStore;
59
- res.locals.playground = this.playground === true;
60
- res.locals.isDev = this.isDev === true;
364
+ if (this.taskStore) {
365
+ res.locals.taskStore = this.taskStore;
366
+ }
61
367
  res.locals.customRouteAuthConfig = this.customRouteAuthConfig;
62
368
  const controller = new AbortController();
63
- req.on("close", () => {
64
- controller.abort();
369
+ res.on("close", () => {
370
+ if (!res.writableFinished) {
371
+ controller.abort();
372
+ }
65
373
  });
66
374
  res.locals.abortSignal = controller.signal;
67
375
  next();
@@ -78,12 +386,14 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
78
386
  const { done, value } = await reader.read();
79
387
  if (done) break;
80
388
  if (value) {
389
+ const shouldRedact = this.streamOptions?.redact ?? true;
390
+ const outputValue = shouldRedact ? redactStreamChunk(value) : value;
81
391
  if (streamFormat === "sse") {
82
- res.write(`data: ${JSON.stringify(value)}
392
+ res.write(`data: ${JSON.stringify(outputValue)}
83
393
 
84
394
  `);
85
395
  } else {
86
- res.write(JSON.stringify(value) + "");
396
+ res.write(JSON.stringify(outputValue) + "");
87
397
  }
88
398
  }
89
399
  }
@@ -95,11 +405,75 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
95
405
  }
96
406
  async getParams(route, request) {
97
407
  const urlParams = request.params;
98
- const queryParams = request.query;
99
- const body = await request.body;
408
+ const queryParams = normalizeQueryParams(request.query);
409
+ let body;
410
+ if (route.method === "POST" || route.method === "PUT" || route.method === "PATCH") {
411
+ const contentType = request.headers["content-type"] || "";
412
+ if (contentType.includes("multipart/form-data")) {
413
+ try {
414
+ const maxFileSize = route.maxBodySize ?? this.bodyLimitOptions?.maxSize;
415
+ body = await this.parseMultipartFormData(request, maxFileSize);
416
+ } catch (error) {
417
+ console.error("Failed to parse multipart form data:", error);
418
+ if (error instanceof Error && error.message.toLowerCase().includes("size")) {
419
+ throw error;
420
+ }
421
+ }
422
+ } else {
423
+ body = request.body;
424
+ }
425
+ }
100
426
  return { urlParams, queryParams, body };
101
427
  }
102
- async sendResponse(route, response, result) {
428
+ /**
429
+ * Parse multipart/form-data using @fastify/busboy.
430
+ * Converts file uploads to Buffers and parses JSON field values.
431
+ *
432
+ * @param request - The Express request object
433
+ * @param maxFileSize - Optional maximum file size in bytes
434
+ */
435
+ parseMultipartFormData(request, maxFileSize) {
436
+ return new Promise((resolve, reject) => {
437
+ const result = {};
438
+ const busboy = new Busboy({
439
+ headers: {
440
+ "content-type": request.headers["content-type"]
441
+ },
442
+ limits: maxFileSize ? { fileSize: maxFileSize } : void 0
443
+ });
444
+ busboy.on("file", (fieldname, file) => {
445
+ const chunks = [];
446
+ let limitExceeded = false;
447
+ file.on("data", (chunk) => {
448
+ chunks.push(chunk);
449
+ });
450
+ file.on("limit", () => {
451
+ limitExceeded = true;
452
+ reject(new Error(`File size limit exceeded${maxFileSize ? ` (max: ${maxFileSize} bytes)` : ""}`));
453
+ });
454
+ file.on("end", () => {
455
+ if (!limitExceeded) {
456
+ result[fieldname] = Buffer.concat(chunks);
457
+ }
458
+ });
459
+ });
460
+ busboy.on("field", (fieldname, value) => {
461
+ try {
462
+ result[fieldname] = JSON.parse(value);
463
+ } catch {
464
+ result[fieldname] = value;
465
+ }
466
+ });
467
+ busboy.on("finish", () => {
468
+ resolve(result);
469
+ });
470
+ busboy.on("error", (error) => {
471
+ reject(error);
472
+ });
473
+ request.pipe(busboy);
474
+ });
475
+ }
476
+ async sendResponse(route, response, result, request) {
103
477
  if (route.responseType === "json") {
104
478
  response.json(result);
105
479
  } else if (route.responseType === "stream") {
@@ -122,6 +496,47 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
122
496
  } else {
123
497
  response.end();
124
498
  }
499
+ } else if (route.responseType === "mcp-http") {
500
+ if (!request) {
501
+ response.status(500).json({ error: "Request object required for MCP transport" });
502
+ return;
503
+ }
504
+ const { server, httpPath } = result;
505
+ try {
506
+ await server.startHTTP({
507
+ url: new URL(request.url, `http://${request.headers.host}`),
508
+ httpPath,
509
+ req: request,
510
+ res: response
511
+ });
512
+ } catch {
513
+ if (!response.headersSent) {
514
+ response.status(500).json({
515
+ jsonrpc: "2.0",
516
+ error: { code: -32603, message: "Internal server error" },
517
+ id: null
518
+ });
519
+ }
520
+ }
521
+ } else if (route.responseType === "mcp-sse") {
522
+ if (!request) {
523
+ response.status(500).json({ error: "Request object required for MCP transport" });
524
+ return;
525
+ }
526
+ const { server, ssePath, messagePath } = result;
527
+ try {
528
+ await server.startSSE({
529
+ url: new URL(request.url, `http://${request.headers.host}`),
530
+ ssePath,
531
+ messagePath,
532
+ req: request,
533
+ res: response
534
+ });
535
+ } catch {
536
+ if (!response.headersSent) {
537
+ response.status(500).json({ error: "Error handling MCP SSE request" });
538
+ }
539
+ }
125
540
  } else {
126
541
  response.sendStatus(500);
127
542
  }
@@ -155,9 +570,12 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
155
570
  params.queryParams = await this.parseQueryParams(route, params.queryParams);
156
571
  } catch (error) {
157
572
  console.error("Error parsing query params", error);
573
+ if (error instanceof ZodError) {
574
+ return res.status(400).json(formatZodError(error, "query parameters"));
575
+ }
158
576
  return res.status(400).json({
159
577
  error: "Invalid query parameters",
160
- details: error instanceof Error ? error.message : "Unknown error"
578
+ issues: [{ field: "unknown", message: error instanceof Error ? error.message : "Unknown error" }]
161
579
  });
162
580
  }
163
581
  }
@@ -165,10 +583,13 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
165
583
  try {
166
584
  params.body = await this.parseBody(route, params.body);
167
585
  } catch (error) {
168
- console.error("Error parsing body", error);
586
+ console.error("Error parsing body:", error instanceof Error ? error.message : String(error));
587
+ if (error instanceof ZodError) {
588
+ return res.status(400).json(formatZodError(error, "request body"));
589
+ }
169
590
  return res.status(400).json({
170
591
  error: "Invalid request body",
171
- details: error instanceof Error ? error.message : "Unknown error"
592
+ issues: [{ field: "unknown", message: error instanceof Error ? error.message : "Unknown error" }]
172
593
  });
173
594
  }
174
595
  }
@@ -184,7 +605,7 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
184
605
  };
185
606
  try {
186
607
  const result = await route.handler(handlerParams);
187
- await this.sendResponse(route, res, result);
608
+ await this.sendResponse(route, res, result, req);
188
609
  } catch (error) {
189
610
  console.error("Error calling handler", error);
190
611
  let status = 500;
@@ -200,14 +621,19 @@ var ExpressServerAdapter = class extends MastraServerAdapter {
200
621
  }
201
622
  );
202
623
  }
203
- registerContextMiddleware(app) {
204
- app.use(this.createContextMiddleware());
624
+ registerContextMiddleware() {
625
+ this.app.use(this.createContextMiddleware());
205
626
  }
206
- async registerRoutes(app, { prefix, openapiPath }) {
207
- await super.registerRoutes(app, { prefix, openapiPath });
627
+ registerAuthMiddleware() {
628
+ const authConfig = this.mastra.getServer()?.auth;
629
+ if (!authConfig) {
630
+ return;
631
+ }
632
+ this.app.use(authenticationMiddleware);
633
+ this.app.use(authorizationMiddleware);
208
634
  }
209
635
  };
210
636
 
211
- export { ExpressServerAdapter };
637
+ export { MastraServer };
212
638
  //# sourceMappingURL=index.js.map
213
639
  //# sourceMappingURL=index.js.map