@mastra/deployer 0.0.1-alpha.0

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.
Files changed (79) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +44 -0
  3. package/dist/build/bundle.d.ts +8 -0
  4. package/dist/build/bundle.d.ts.map +1 -0
  5. package/dist/build/deps.d.ts +21 -0
  6. package/dist/build/deps.d.ts.map +1 -0
  7. package/dist/build/env.d.ts +14 -0
  8. package/dist/build/env.d.ts.map +1 -0
  9. package/dist/build/fs.d.ts +22 -0
  10. package/dist/build/fs.d.ts.map +1 -0
  11. package/dist/build/index.d.ts +6 -0
  12. package/dist/build/index.d.ts.map +1 -0
  13. package/dist/build/utils.d.ts +2 -0
  14. package/dist/build/utils.d.ts.map +1 -0
  15. package/dist/deploy/base.d.ts +36 -0
  16. package/dist/deploy/base.d.ts.map +1 -0
  17. package/dist/deploy/index.d.ts +2 -0
  18. package/dist/deploy/index.d.ts.map +1 -0
  19. package/dist/deployer.cjs.development.js +2872 -0
  20. package/dist/deployer.cjs.development.js.map +1 -0
  21. package/dist/deployer.cjs.production.min.js +2 -0
  22. package/dist/deployer.cjs.production.min.js.map +1 -0
  23. package/dist/deployer.esm.js +2840 -0
  24. package/dist/deployer.esm.js.map +1 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +8 -0
  28. package/dist/server/handlers/agents.d.ts +6 -0
  29. package/dist/server/handlers/agents.d.ts.map +1 -0
  30. package/dist/server/handlers/client.d.ts +7 -0
  31. package/dist/server/handlers/client.d.ts.map +1 -0
  32. package/dist/server/handlers/error.d.ts +7 -0
  33. package/dist/server/handlers/error.d.ts.map +1 -0
  34. package/dist/server/handlers/logs.d.ts +4 -0
  35. package/dist/server/handlers/logs.d.ts.map +1 -0
  36. package/dist/server/handlers/memory.d.ts +17 -0
  37. package/dist/server/handlers/memory.d.ts.map +1 -0
  38. package/dist/server/handlers/root.d.ts +3 -0
  39. package/dist/server/handlers/root.d.ts.map +1 -0
  40. package/dist/server/handlers/syncs.d.ts +3 -0
  41. package/dist/server/handlers/syncs.d.ts.map +1 -0
  42. package/dist/server/handlers/tools.d.ts +8 -0
  43. package/dist/server/handlers/tools.d.ts.map +1 -0
  44. package/dist/server/handlers/utils.d.ts +2 -0
  45. package/dist/server/handlers/utils.d.ts.map +1 -0
  46. package/dist/server/handlers/workflows.d.ts +11 -0
  47. package/dist/server/handlers/workflows.d.ts.map +1 -0
  48. package/dist/server/index.d.ts +21 -0
  49. package/dist/server/index.d.ts.map +1 -0
  50. package/dist/server/index.js +8964 -0
  51. package/dist/server/types.d.ts +5 -0
  52. package/dist/server/types.d.ts.map +1 -0
  53. package/dist/server/welcome.d.ts +2 -0
  54. package/dist/server/welcome.d.ts.map +1 -0
  55. package/package.json +61 -0
  56. package/src/build/bundle.ts +224 -0
  57. package/src/build/deps.ts +128 -0
  58. package/src/build/env.ts +76 -0
  59. package/src/build/fs.ts +66 -0
  60. package/src/build/index.ts +5 -0
  61. package/src/build/utils.ts +12 -0
  62. package/src/deploy/base.ts +171 -0
  63. package/src/deploy/index.ts +1 -0
  64. package/src/index.ts +3 -0
  65. package/src/server/handlers/agents.ts +121 -0
  66. package/src/server/handlers/client.ts +36 -0
  67. package/src/server/handlers/error.ts +29 -0
  68. package/src/server/handlers/logs.ts +24 -0
  69. package/src/server/handlers/memory.ts +208 -0
  70. package/src/server/handlers/root.ts +6 -0
  71. package/src/server/handlers/syncs.ts +19 -0
  72. package/src/server/handlers/tools.ts +156 -0
  73. package/src/server/handlers/utils.ts +15 -0
  74. package/src/server/handlers/workflows.ts +60 -0
  75. package/src/server/index.ts +185 -0
  76. package/src/server/types.ts +4 -0
  77. package/src/server/welcome.ts +105 -0
  78. package/tsconfig.json +10 -0
  79. package/vitest.config.ts +8 -0
@@ -0,0 +1,156 @@
1
+ import { Context } from 'hono';
2
+ import { stringify } from 'superjson';
3
+ import zodToJsonSchema from 'zod-to-json-schema';
4
+
5
+ import { HTTPException } from 'hono/http-exception';
6
+
7
+ import { handleError } from './error';
8
+ import { validateBody } from './utils';
9
+
10
+ // Tool handlers
11
+ export async function getToolsHandler(c: Context) {
12
+ try {
13
+ const tools = c.get('tools');
14
+
15
+ if (!tools) {
16
+ return c.json({});
17
+ }
18
+
19
+ const serializedTools = Object.entries(tools).reduce(
20
+ (acc, [id, _tool]) => {
21
+ const tool = _tool as any;
22
+ acc[id] = {
23
+ ...tool,
24
+ inputSchema: tool.inputSchema ? stringify(zodToJsonSchema(tool.inputSchema)) : undefined,
25
+ outputSchema: tool.outputSchema ? stringify(zodToJsonSchema(tool.outputSchema)) : undefined,
26
+ };
27
+ return acc;
28
+ },
29
+ {} as Record<string, any>,
30
+ );
31
+
32
+ return c.json(serializedTools);
33
+ } catch (error) {
34
+ return handleError(error, 'Error getting tools');
35
+ }
36
+ }
37
+
38
+ export async function getToolByIdHandler(c: Context) {
39
+ try {
40
+ const tools = c.get('tools');
41
+ const toolId = c.req.param('toolId');
42
+ const tool = Object.values(tools || {}).find((tool: any) => tool.id === toolId) as any;
43
+
44
+ if (!tool) {
45
+ throw new HTTPException(404, { message: 'Tool not found' });
46
+ }
47
+
48
+ const serializedTool = {
49
+ ...tool,
50
+ inputSchema: tool.inputSchema ? stringify(zodToJsonSchema(tool.inputSchema)) : undefined,
51
+ outputSchema: tool.outputSchema ? stringify(zodToJsonSchema(tool.outputSchema)) : undefined,
52
+ };
53
+
54
+ return c.json(serializedTool);
55
+ } catch (error) {
56
+ return handleError(error, 'Error getting tool');
57
+ }
58
+ }
59
+
60
+ export async function getToolResultHandler(c: Context) {
61
+ try {
62
+ const mastra = c.get('mastra');
63
+ const memory = mastra.memory;
64
+ const threadId = c.req.param('threadId');
65
+ const { toolName, toolArgs } = await c.req.json();
66
+
67
+ if (!memory) {
68
+ throw new HTTPException(400, { message: 'Memory is not initialized' });
69
+ }
70
+
71
+ validateBody({ toolName, toolArgs });
72
+
73
+ const thread = await memory.getThreadById({ threadId });
74
+ if (!thread) {
75
+ throw new HTTPException(404, { message: 'Thread not found' });
76
+ }
77
+
78
+ const result = await memory.getToolResult({ threadId, toolName, toolArgs });
79
+ return c.json(result);
80
+ } catch (error) {
81
+ return handleError(error, 'Error getting tool result');
82
+ }
83
+ }
84
+
85
+ export async function validateToolCallArgsHandler(c: Context) {
86
+ try {
87
+ const mastra = c.get('mastra');
88
+ const memory = mastra.memory;
89
+ const { hashedArgs } = await c.req.json();
90
+
91
+ if (!memory) {
92
+ throw new HTTPException(400, { message: 'Memory is not initialized' });
93
+ }
94
+
95
+ validateBody({ hashedArgs });
96
+
97
+ const result = await memory.validateToolCallArgs({ hashedArgs });
98
+ return c.json(result);
99
+ } catch (error) {
100
+ return handleError(error, 'Error validating tool call args');
101
+ }
102
+ }
103
+
104
+ export function executeToolHandler(tools: Record<string, any>) {
105
+ return async (c: Context) => {
106
+ try {
107
+ const toolId = decodeURIComponent(c.req.param('toolId'));
108
+ const tool = Object.values(tools || {}).find((tool: any) => tool.id === toolId) as any;
109
+
110
+ if (!tool) {
111
+ return c.json({ error: 'Tool not found' }, 404);
112
+ }
113
+
114
+ const { input } = await c.req.json();
115
+ const mastra = c.get('mastra');
116
+ const result = await tool.execute({
117
+ context: {
118
+ ...input,
119
+ },
120
+ mastra,
121
+ runId: mastra.runId,
122
+ });
123
+
124
+ return c.json(result);
125
+ } catch (error) {
126
+ return handleError(error, 'Error executing tool');
127
+ }
128
+ };
129
+ }
130
+
131
+ export async function executeAgentToolHandler(c: Context) {
132
+ try {
133
+ const mastra = c.get('mastra');
134
+ const agentId = c.req.param('agentId');
135
+ const toolId = c.req.param('toolId');
136
+ const agent = mastra.getAgent(agentId);
137
+ const tool = Object.values(agent?.tools || {}).find((tool: any) => tool.id === toolId) as any;
138
+
139
+ if (!tool) {
140
+ throw new HTTPException(404, { message: 'Tool not found' });
141
+ }
142
+
143
+ const body = await c.req.json();
144
+ const result = await tool.execute({
145
+ context: {
146
+ ...body,
147
+ },
148
+ mastra,
149
+ runId: agentId,
150
+ });
151
+
152
+ return c.json(result);
153
+ } catch (error) {
154
+ return handleError(error, 'Error executing tool');
155
+ }
156
+ }
@@ -0,0 +1,15 @@
1
+ import { HTTPException } from 'hono/http-exception';
2
+
3
+ // Validation helper
4
+ export function validateBody(body: Record<string, unknown>) {
5
+ const errorResponse = Object.entries(body).reduce<Record<string, string>>((acc, [key, value]) => {
6
+ if (!value) {
7
+ acc[key] = `${key} is required`;
8
+ }
9
+ return acc;
10
+ }, {});
11
+
12
+ if (Object.keys(errorResponse).length > 0) {
13
+ throw new HTTPException(400, { message: JSON.stringify(errorResponse) });
14
+ }
15
+ }
@@ -0,0 +1,60 @@
1
+ import { Context } from 'hono';
2
+ import { stringify } from 'superjson';
3
+ import zodToJsonSchema from 'zod-to-json-schema';
4
+
5
+ import { handleError } from './error';
6
+
7
+ export async function getWorkflowsHandler(c: Context) {
8
+ try {
9
+ const mastra = c.get('mastra');
10
+ const workflows = mastra.getWorkflows({ serialized: true });
11
+ return c.json(workflows);
12
+ } catch (error) {
13
+ return handleError(error, 'Error getting workflows');
14
+ }
15
+ }
16
+
17
+ export async function getWorkflowByIdHandler(c: Context) {
18
+ try {
19
+ const mastra = c.get('mastra');
20
+ const workflowId = c.req.param('workflowId');
21
+ const workflow = mastra.getWorkflow(workflowId);
22
+
23
+ const triggerSchema = workflow.triggerSchema;
24
+ const stepGraph = workflow.stepGraph;
25
+ const stepSubscriberGraph = workflow.stepSubscriberGraph;
26
+ const serializedSteps = Object.entries(workflow.steps).reduce<any>((acc, [key, step]) => {
27
+ const _step = step as any;
28
+ acc[key] = {
29
+ ..._step,
30
+ inputSchema: _step.inputSchema ? stringify(zodToJsonSchema(_step.inputSchema)) : undefined,
31
+ outputSchema: _step.outputSchema ? stringify(zodToJsonSchema(_step.outputSchema)) : undefined,
32
+ };
33
+ return acc;
34
+ }, {});
35
+
36
+ return c.json({
37
+ name: workflow.name,
38
+ triggerSchema: triggerSchema ? stringify(zodToJsonSchema(triggerSchema)) : undefined,
39
+ steps: serializedSteps,
40
+ stepGraph,
41
+ stepSubscriberGraph,
42
+ });
43
+ } catch (error) {
44
+ return handleError(error, 'Error getting workflow');
45
+ }
46
+ }
47
+
48
+ export async function executeWorkflowHandler(c: Context) {
49
+ try {
50
+ const mastra = c.get('mastra');
51
+ const workflowId = c.req.param('workflowId');
52
+ const workflow = mastra.getWorkflow(workflowId);
53
+ const body = await c.req.json();
54
+
55
+ const result = await workflow.execute(body);
56
+ return c.json(result);
57
+ } catch (error) {
58
+ return handleError(error, 'Error executing workflow');
59
+ }
60
+ }
@@ -0,0 +1,185 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { serveStatic } from '@hono/node-server/serve-static';
3
+ import { type Mastra } from '@mastra/core';
4
+ import { Hono } from 'hono';
5
+ import { join } from 'path';
6
+ import { pathToFileURL } from 'url';
7
+
8
+ import { readFile } from 'fs/promises';
9
+ import { cors } from 'hono/cors';
10
+
11
+ import { generateHandler, getAgentByIdHandler, getAgentsHandler, streamGenerateHandler } from './handlers/agents.js';
12
+ import { handleClientsRefresh } from './handlers/client.js';
13
+ import { handleTriggerClientsRefresh } from './handlers/client.js';
14
+ import { getLogsByRunIdHandler, getLogsHandler } from './handlers/logs';
15
+ import {
16
+ createThreadHandler,
17
+ deleteThreadHandler,
18
+ getContextWindowHandler,
19
+ getMemoryStatusHandler,
20
+ getMessagesHandler,
21
+ getThreadByIdHandler,
22
+ getThreadsHandler,
23
+ saveMessagesHandler,
24
+ updateThreadHandler,
25
+ } from './handlers/memory';
26
+ import { rootHandler } from './handlers/root.js';
27
+ import { executeSyncHandler } from './handlers/syncs.js';
28
+ import {
29
+ executeAgentToolHandler,
30
+ executeToolHandler,
31
+ getToolByIdHandler,
32
+ getToolResultHandler,
33
+ getToolsHandler,
34
+ validateToolCallArgsHandler,
35
+ } from './handlers/tools';
36
+ import { executeWorkflowHandler, getWorkflowByIdHandler, getWorkflowsHandler } from './handlers/workflows';
37
+ import { html } from './welcome.js';
38
+
39
+ type Bindings = {};
40
+
41
+ type Variables = {
42
+ mastra: Mastra;
43
+ clients: Set<{ controller: ReadableStreamDefaultController }>;
44
+ tools: Record<string, any>;
45
+ };
46
+
47
+ export async function createHonoServer(mastra: Mastra, options: { playground?: boolean } = {}) {
48
+ // Create typed Hono app
49
+ const app = new Hono<{ Bindings: Bindings; Variables: Variables }>();
50
+
51
+ // Initialize tools
52
+ const mastraToolsPaths = process.env.MASTRA_TOOLS_PATH;
53
+ const toolImports = mastraToolsPaths
54
+ ? await Promise.all(
55
+ mastraToolsPaths.split(',').map(async toolPath => {
56
+ return import(pathToFileURL(toolPath).href);
57
+ }),
58
+ )
59
+ : [];
60
+
61
+ const tools = toolImports.reduce((acc, toolModule) => {
62
+ Object.entries(toolModule).forEach(([key, tool]) => {
63
+ acc[key] = tool;
64
+ });
65
+ return acc;
66
+ }, {});
67
+
68
+ // Middleware
69
+ app.use('*', cors());
70
+
71
+ // Add Mastra to context
72
+ app.use('*', async (c, next) => {
73
+ c.set('mastra', mastra);
74
+ c.set('tools', tools);
75
+ await next();
76
+ });
77
+
78
+ // API routes
79
+ app.get('/api', rootHandler);
80
+
81
+ // Agent routes
82
+ app.get('/api/agents', getAgentsHandler);
83
+ app.get('/api/agents/:agentId', getAgentByIdHandler);
84
+ app.post('/api/agents/:agentId/generate', generateHandler);
85
+ app.post('/api/agents/:agentId/stream', streamGenerateHandler);
86
+ app.post('/api/agents/:agentId/tools/:toolId/execute', executeAgentToolHandler);
87
+
88
+ // Memory routes
89
+ app.get('/api/memory/status', getMemoryStatusHandler);
90
+ app.get('/api/memory/threads', getThreadsHandler);
91
+ app.get('/api/memory/threads/:threadId', getThreadByIdHandler);
92
+ app.get('/api/memory/threads/:threadId/messages', getMessagesHandler);
93
+ app.get('/api/memory/threads/:threadId/context-window', getContextWindowHandler);
94
+ app.post('/api/memory/threads', createThreadHandler);
95
+ app.patch('/api/memory/threads/:threadId', updateThreadHandler);
96
+ app.delete('/api/memory/threads/:threadId', deleteThreadHandler);
97
+ app.post('/api/memory/save-messages', saveMessagesHandler);
98
+ app.post('/api/memory/threads/:threadId/tool-result', getToolResultHandler);
99
+ app.post('/api/memory/validate-tool-call-args', validateToolCallArgsHandler);
100
+
101
+ // Workflow routes
102
+ app.get('/api/workflows', getWorkflowsHandler);
103
+ app.get('/api/workflows/:workflowId', getWorkflowByIdHandler);
104
+ app.post('/api/workflows/:workflowId/execute', executeWorkflowHandler);
105
+
106
+ // Sync routes
107
+ app.post('/api/syncs/:syncId/execute', executeSyncHandler);
108
+
109
+ // Log routes
110
+ app.get('/api/logs', getLogsHandler);
111
+ app.get('/api/logs/:runId', getLogsByRunIdHandler);
112
+
113
+ // Tool routes
114
+ app.get('/api/tools', getToolsHandler);
115
+ app.get('/api/tools/:toolId', getToolByIdHandler);
116
+ app.post('/api/tools/:toolId/execute', executeToolHandler(tools));
117
+
118
+ // SSE endpoint for refresh notifications
119
+ app.get('/refresh-events', handleClientsRefresh);
120
+
121
+ // Trigger refresh for all clients
122
+ app.post('/__refresh', handleTriggerClientsRefresh);
123
+
124
+ if (options?.playground) {
125
+ // Playground routes - these should come after API routes
126
+ // Serve assets with specific MIME types
127
+ app.use('/assets/*', async (c, next) => {
128
+ const path = c.req.path;
129
+ if (path.endsWith('.js')) {
130
+ c.header('Content-Type', 'application/javascript');
131
+ } else if (path.endsWith('.css')) {
132
+ c.header('Content-Type', 'text/css');
133
+ }
134
+ await next();
135
+ });
136
+
137
+ // Serve assets from playground directory
138
+ app.use(
139
+ '/assets/*',
140
+ serveStatic({
141
+ root: './playground/assets',
142
+ }),
143
+ );
144
+
145
+ // Serve static files from playground directory
146
+ app.use(
147
+ '*',
148
+ serveStatic({
149
+ root: './playground',
150
+ }),
151
+ );
152
+ }
153
+
154
+ // Catch-all route to serve index.html for any non-API routes
155
+ app.get('*', async (c, next) => {
156
+ // Skip if it's an API route
157
+ if (c.req.path.startsWith('/api/')) {
158
+ return await next();
159
+ }
160
+ if (options?.playground) {
161
+ // For all other routes, serve index.html
162
+ const indexHtml = await readFile(join(process.cwd(), './playground/index.html'), 'utf-8');
163
+ return c.newResponse(indexHtml, 200, { 'Content-Type': 'text/html' });
164
+ }
165
+
166
+ return c.newResponse(html, 200, { 'Content-Type': 'text/html' });
167
+ });
168
+
169
+ return app;
170
+ }
171
+
172
+ export async function createNodeServer(mastra: Mastra, options: { playground?: boolean } = {}) {
173
+ const app = await createHonoServer(mastra, options);
174
+ return serve(
175
+ {
176
+ fetch: app.fetch,
177
+ port: Number(process.env.PORT) || 4111,
178
+ },
179
+ () => {
180
+ console.log(`🦄 Server running on port ${process.env.PORT || 4111}/api`);
181
+ console.log(`📚 Open API documentation available at http://localhost:${process.env.PORT || 4111}/openapi.json`);
182
+ console.log(`👨‍💻 Playground available at http://localhost:${process.env.PORT || 4111}/`);
183
+ },
184
+ );
185
+ }
@@ -0,0 +1,4 @@
1
+ export interface ApiError extends Error {
2
+ message: string;
3
+ status?: number;
4
+ }
@@ -0,0 +1,105 @@
1
+ export const html = `
2
+ <!doctype html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Welcome to Mastra</title>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/inter-ui/3.19.3/inter.min.css" />
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ background-color: #0d0d0d;
14
+ color: #ffffff;
15
+ font-family:
16
+ 'Inter',
17
+ -apple-system,
18
+ BlinkMacSystemFont,
19
+ system-ui,
20
+ sans-serif;
21
+ min-height: 100vh;
22
+ display: flex;
23
+ flex-direction: column;
24
+ }
25
+
26
+ main {
27
+ flex: 1;
28
+ display: flex;
29
+ flex-direction: column;
30
+ align-items: center;
31
+ justify-content: center;
32
+ padding: 2rem;
33
+ text-align: center;
34
+ }
35
+
36
+ h1 {
37
+ font-size: 4rem;
38
+ font-weight: 600;
39
+ margin: 0 0 1rem 0;
40
+ background: linear-gradient(to right, #fff, #ccc);
41
+ -webkit-background-clip: text;
42
+ -webkit-text-fill-color: transparent;
43
+ line-height: 1.2;
44
+ }
45
+
46
+ .subtitle {
47
+ color: #9ca3af;
48
+ font-size: 1.25rem;
49
+ max-width: 600px;
50
+ margin: 0 auto 3rem auto;
51
+ line-height: 1.6;
52
+ }
53
+
54
+ .docs-link {
55
+ background-color: #1a1a1a;
56
+ padding: 1rem 2rem;
57
+ border-radius: 0.5rem;
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 1rem;
61
+ font-family: monospace;
62
+ font-size: 1rem;
63
+ color: #ffffff;
64
+ text-decoration: none;
65
+ transition: background-color 0.2s;
66
+ }
67
+
68
+ .docs-link:hover {
69
+ background-color: #252525;
70
+ }
71
+
72
+ .arrow-icon {
73
+ transition: transform 0.2s;
74
+ }
75
+
76
+ .docs-link:hover .arrow-icon {
77
+ transform: translateX(4px);
78
+ }
79
+ </style>
80
+ </head>
81
+ <body>
82
+ <main>
83
+ <h1>Welcome to Mastra</h1>
84
+ <p class="subtitle">
85
+ From the team that brought you Gatsby: prototype and productionize AI features with a modern JS/TS stack.
86
+ </p>
87
+
88
+ <a href="https://mastra.ai/docs" class="docs-link">
89
+ Browse the docs
90
+ <svg
91
+ class="arrow-icon"
92
+ width="20"
93
+ height="20"
94
+ viewBox="0 0 24 24"
95
+ fill="none"
96
+ stroke="currentColor"
97
+ stroke-width="2"
98
+ >
99
+ <path d="M5 12h14M12 5l7 7-7 7" />
100
+ </svg>
101
+ </a>
102
+ </main>
103
+ </body>
104
+ </html>
105
+ `;
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "moduleResolution": "bundler",
5
+ "outDir": "./dist",
6
+ "rootDir": "./src"
7
+ },
8
+ "include": ["src/**/*"],
9
+ "exclude": ["node_modules", "**/*.test.ts"]
10
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ include: ['src/**/*.test.ts'],
7
+ },
8
+ });