@mastra/deployer-vercel 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.
- package/CHANGELOG.md +9 -0
- package/LICENSE +44 -0
- package/dist/deployer-vercel.cjs.development.js +559 -0
- package/dist/deployer-vercel.cjs.development.js.map +1 -0
- package/dist/deployer-vercel.cjs.production.min.js +2 -0
- package/dist/deployer-vercel.cjs.production.min.js.map +1 -0
- package/dist/deployer-vercel.esm.js +555 -0
- package/dist/deployer-vercel.esm.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/package.json +49 -0
- package/src/index.ts +170 -0
- package/tsconfig.json +10 -0
- package/vitest.config.ts +8 -0
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mastra/deployer-vercel",
|
|
3
|
+
"version": "0.0.1-alpha.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/deployer-vercel.esm.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/deployer-vercel.esm.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [],
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"date-fns": "^4.1.0",
|
|
27
|
+
"dotenv": "^16.3.1",
|
|
28
|
+
"execa": "^9.3.1",
|
|
29
|
+
"vercel": "^39.3.0",
|
|
30
|
+
"zod": "^3.24.1",
|
|
31
|
+
"@mastra/core": "0.1.27-alpha.66",
|
|
32
|
+
"@mastra/deployer": "0.0.1-alpha.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@babel/preset-env": "^7.26.0",
|
|
36
|
+
"@babel/preset-typescript": "^7.26.0",
|
|
37
|
+
"@tsconfig/recommended": "^1.0.7",
|
|
38
|
+
"@types/jsdom": "^21.1.7",
|
|
39
|
+
"@types/node": "^22.9.0",
|
|
40
|
+
"@types/pg": "^8.11.10",
|
|
41
|
+
"dts-cli": "^2.0.5",
|
|
42
|
+
"vitest": "^2.1.8"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "dts build",
|
|
46
|
+
"build:dev": "dts watch",
|
|
47
|
+
"test": "vitest run"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { MastraDeployer } from '@mastra/core';
|
|
2
|
+
import { execa } from 'execa';
|
|
3
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
|
|
6
|
+
interface EnvVar {
|
|
7
|
+
key: string;
|
|
8
|
+
value: string;
|
|
9
|
+
target: ('production' | 'preview' | 'development')[];
|
|
10
|
+
type: 'plain' | 'secret';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface VercelError {
|
|
14
|
+
message: string;
|
|
15
|
+
code: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class VercelDeployer extends MastraDeployer {
|
|
19
|
+
constructor({ scope, env, projectName }: { env?: Record<string, any>; scope: string; projectName: string }) {
|
|
20
|
+
super({ scope, env, projectName });
|
|
21
|
+
}
|
|
22
|
+
writeFiles({ dir }: { dir: string }): void {
|
|
23
|
+
this.writeIndex({ dir });
|
|
24
|
+
|
|
25
|
+
writeFileSync(
|
|
26
|
+
join(dir, 'vercel.json'),
|
|
27
|
+
JSON.stringify(
|
|
28
|
+
{
|
|
29
|
+
version: 2,
|
|
30
|
+
builds: [
|
|
31
|
+
{
|
|
32
|
+
src: 'index.mjs',
|
|
33
|
+
use: '@vercel/node',
|
|
34
|
+
config: { includeFiles: ['**'] },
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
routes: [
|
|
38
|
+
{
|
|
39
|
+
src: '/(.*)',
|
|
40
|
+
dest: 'index.mjs',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
null,
|
|
45
|
+
2,
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private getProjectId({ dir }: { dir: string }): string {
|
|
51
|
+
const projectJsonPath = join(dir, '.vercel', 'project.json');
|
|
52
|
+
try {
|
|
53
|
+
const projectJson = JSON.parse(readFileSync(projectJsonPath, 'utf-8'));
|
|
54
|
+
return projectJson.projectId;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
throw new Error('Could not find project ID. Make sure the project has been deployed first.');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async syncEnv({ scope, dir, token }: { token: string; dir: string; scope: string }) {
|
|
61
|
+
const envFiles = this.getEnvFiles();
|
|
62
|
+
const envVars: string[] = [];
|
|
63
|
+
|
|
64
|
+
for (const file of envFiles) {
|
|
65
|
+
const vars = this.parseEnvFile(file);
|
|
66
|
+
envVars.push(...vars);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log('Syncing environment variables...');
|
|
70
|
+
|
|
71
|
+
// Transform env vars into the format expected by Vercel API
|
|
72
|
+
const vercelEnvVars: EnvVar[] = envVars.map(envVar => {
|
|
73
|
+
const [key, value] = envVar.split('=');
|
|
74
|
+
if (!key || !value) {
|
|
75
|
+
throw new Error(`Invalid environment variable format: ${envVar}`);
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
key,
|
|
79
|
+
value,
|
|
80
|
+
target: ['production', 'preview', 'development'],
|
|
81
|
+
type: 'plain',
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const projectId = this.getProjectId({ dir });
|
|
87
|
+
|
|
88
|
+
const response = await fetch(`https://api.vercel.com/v10/projects/${projectId}/env?teamId=${scope}&upsert=true`, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: {
|
|
91
|
+
Authorization: `Bearer ${token}`,
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify(vercelEnvVars),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const error = (await response.json()) as VercelError;
|
|
99
|
+
throw new Error(`Failed to sync environment variables: ${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log('✓ Successfully synced environment variables');
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (error instanceof Error) {
|
|
105
|
+
console.error('Failed to sync environment variables:', error.message);
|
|
106
|
+
} else {
|
|
107
|
+
console.error('Failed to sync environment variables:', error);
|
|
108
|
+
}
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async deploy({ dir, token }: { dir: string; token: string }): Promise<void> {
|
|
114
|
+
// Get env vars for initial deployment
|
|
115
|
+
const envFiles = this.getEnvFiles();
|
|
116
|
+
const envVars: string[] = [];
|
|
117
|
+
|
|
118
|
+
for (const file of envFiles) {
|
|
119
|
+
const vars = this.parseEnvFile(file);
|
|
120
|
+
envVars.push(...vars);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Create the command array with base arguments
|
|
124
|
+
const commandArgs = [
|
|
125
|
+
'--scope',
|
|
126
|
+
this.scope as string,
|
|
127
|
+
'--cwd',
|
|
128
|
+
dir,
|
|
129
|
+
'deploy',
|
|
130
|
+
'--token',
|
|
131
|
+
token,
|
|
132
|
+
'--yes',
|
|
133
|
+
...(this.projectName ? ['--name', this.projectName] : []),
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
// Add env vars to initial deployment
|
|
137
|
+
for (const envVar of envVars) {
|
|
138
|
+
commandArgs.push('--env', envVar);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Run the Vercel deploy command
|
|
142
|
+
// console.log('Running command:', 'vercel', commandArgs.join(' '));
|
|
143
|
+
const p2 = execa('vercel', commandArgs);
|
|
144
|
+
|
|
145
|
+
p2.stdout.pipe(process.stdout);
|
|
146
|
+
p2.stderr.pipe(process.stderr);
|
|
147
|
+
|
|
148
|
+
console.log('Deployment started on Vercel. You can wait for it to finish or exit this command.');
|
|
149
|
+
await p2;
|
|
150
|
+
|
|
151
|
+
if (envVars.length > 0) {
|
|
152
|
+
// Sync environment variables for future deployments
|
|
153
|
+
await this.syncEnv({ scope: this.scope, dir, token });
|
|
154
|
+
} else {
|
|
155
|
+
console.log('\nAdd your ENV vars to .env or your vercel dashboard.\n');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
writeIndex({ dir }: { dir: string }): void {
|
|
160
|
+
writeFileSync(
|
|
161
|
+
join(dir, 'index.mjs'),
|
|
162
|
+
`
|
|
163
|
+
import { handle } from 'hono/vercel'
|
|
164
|
+
import { app } from './hono.mjs';
|
|
165
|
+
export const GET = handle(app);
|
|
166
|
+
export const POST = handle(app);
|
|
167
|
+
`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
package/tsconfig.json
ADDED