@ruan-cat/vercel-deploy-tool 0.12.2 → 1.1.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/README.md +375 -75
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +578 -0
- package/dist/index.d.ts +247 -0
- package/dist/index.js +566 -0
- package/package.json +14 -6
- package/src/cli.ts +61 -0
- package/src/commands/deploy.ts +50 -0
- package/src/commands/init.ts +92 -0
- package/src/config/define-config.ts +20 -0
- package/src/config/loader.ts +95 -0
- package/src/config/schema.ts +108 -0
- package/src/core/executor.ts +50 -0
- package/src/core/tasks/after-build.ts +46 -0
- package/src/core/tasks/alias.ts +37 -0
- package/src/core/tasks/build.ts +50 -0
- package/src/core/tasks/copy-dist.ts +59 -0
- package/src/core/tasks/deploy.ts +54 -0
- package/src/core/tasks/index.ts +144 -0
- package/src/core/tasks/link.ts +49 -0
- package/src/core/tasks/user-commands.ts +31 -0
- package/src/core/vercel.ts +55 -0
- package/src/index.ts +68 -550
- package/src/templates/vercel-deploy-tool.config.ts +129 -0
- package/src/types/index.ts +14 -0
- package/src/utils/type-guards.ts +33 -0
- package/src/utils/vercel-null-config.ts +46 -0
- package/tsconfig.json +3 -1
package/dist/cli.js
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
5
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { Command as Command3 } from "commander";
|
|
8
|
+
|
|
9
|
+
// src/commands/deploy.ts
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { consola as consola10 } from "consola";
|
|
12
|
+
import { config as dotenvxConfig2 } from "@dotenvx/dotenvx";
|
|
13
|
+
|
|
14
|
+
// src/config/loader.ts
|
|
15
|
+
import { loadConfig as c12LoadConfig } from "c12";
|
|
16
|
+
import { consola } from "consola";
|
|
17
|
+
import { isUndefined } from "lodash-es";
|
|
18
|
+
import { config as dotenvxConfig } from "@dotenvx/dotenvx";
|
|
19
|
+
import { printFormat } from "@ruan-cat/utils";
|
|
20
|
+
var CONFIG_NAME = "vercel-deploy-tool";
|
|
21
|
+
var DEFAULT_CONFIG = {
|
|
22
|
+
vercelProjectName: "",
|
|
23
|
+
vercelToken: "",
|
|
24
|
+
vercelOrgId: "",
|
|
25
|
+
vercelProjectId: "",
|
|
26
|
+
deployTargets: []
|
|
27
|
+
};
|
|
28
|
+
async function loadConfig() {
|
|
29
|
+
consola.start("\u5F00\u59CB\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6 vercel-deploy-tool.config.* ...");
|
|
30
|
+
const envPath = process.env.VERCEL_DEPLOY_TOOL_ENV_PATH;
|
|
31
|
+
if (envPath) {
|
|
32
|
+
dotenvxConfig({ path: envPath });
|
|
33
|
+
consola.info(`\u5DF2\u4ECE VERCEL_DEPLOY_TOOL_ENV_PATH \u52A0\u8F7D dotenv: ${envPath}`);
|
|
34
|
+
}
|
|
35
|
+
let config;
|
|
36
|
+
const loaded = await c12LoadConfig({
|
|
37
|
+
cwd: process.cwd(),
|
|
38
|
+
name: CONFIG_NAME,
|
|
39
|
+
dotenv: true,
|
|
40
|
+
defaults: DEFAULT_CONFIG
|
|
41
|
+
});
|
|
42
|
+
config = loaded.config;
|
|
43
|
+
const vercelOrgId = process.env.VERCEL_ORG_ID;
|
|
44
|
+
const vercelProjectId = process.env.VERCEL_PROJECT_ID;
|
|
45
|
+
const vercelToken = process.env.VERCEL_TOKEN;
|
|
46
|
+
if (!isUndefined(vercelOrgId)) {
|
|
47
|
+
config.vercelOrgId = vercelOrgId;
|
|
48
|
+
}
|
|
49
|
+
if (!isUndefined(vercelProjectId)) {
|
|
50
|
+
config.vercelProjectId = vercelProjectId;
|
|
51
|
+
}
|
|
52
|
+
if (!isUndefined(vercelToken)) {
|
|
53
|
+
config.vercelToken = vercelToken;
|
|
54
|
+
}
|
|
55
|
+
consola.success("\u914D\u7F6E\u52A0\u8F7D\u5B8C\u6210");
|
|
56
|
+
consola.box(printFormat(config));
|
|
57
|
+
return config;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/core/tasks/index.ts
|
|
61
|
+
import fs4 from "fs";
|
|
62
|
+
import { resolve as resolve5 } from "path";
|
|
63
|
+
import { consola as consola9 } from "consola";
|
|
64
|
+
|
|
65
|
+
// src/core/executor.ts
|
|
66
|
+
import task from "tasuku";
|
|
67
|
+
async function executeSequential(title, tasks) {
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const t of tasks) {
|
|
70
|
+
const result = await task(t.name, t.fn);
|
|
71
|
+
results.push(result.result);
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/utils/type-guards.ts
|
|
77
|
+
function isDeployTargetWithUserCommands(target) {
|
|
78
|
+
return target.type === "userCommands";
|
|
79
|
+
}
|
|
80
|
+
function getIsCopyDist(target) {
|
|
81
|
+
return target.isCopyDist ?? true;
|
|
82
|
+
}
|
|
83
|
+
function isNeedVercelBuild(target) {
|
|
84
|
+
return target.isNeedVercelBuild ?? true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/utils/vercel-null-config.ts
|
|
88
|
+
var VERCEL_NULL_CONFIG = {
|
|
89
|
+
framework: null,
|
|
90
|
+
buildCommand: null,
|
|
91
|
+
installCommand: null,
|
|
92
|
+
outputDirectory: null,
|
|
93
|
+
devCommand: null,
|
|
94
|
+
public: false,
|
|
95
|
+
/**
|
|
96
|
+
* 部署后提供干净的链接
|
|
97
|
+
* @see https://vercel.com/docs/projects/project-configuration#cleanurls
|
|
98
|
+
*
|
|
99
|
+
* @description
|
|
100
|
+
* 暂无效果
|
|
101
|
+
*
|
|
102
|
+
* 目前在 build-output-api 中,实现cleanUrls需要手动地写入配置文件
|
|
103
|
+
*
|
|
104
|
+
* 成本较大,目前不做投入。
|
|
105
|
+
*/
|
|
106
|
+
cleanUrls: true,
|
|
107
|
+
git: {
|
|
108
|
+
deploymentEnabled: {
|
|
109
|
+
main: false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
var VERCEL_NULL_CONFIG_PATH = "./vercel.null.def.json";
|
|
114
|
+
var VERCEL_OUTPUT_STATIC = ".vercel/output/static";
|
|
115
|
+
|
|
116
|
+
// src/core/tasks/link.ts
|
|
117
|
+
import fs from "fs";
|
|
118
|
+
import { resolve } from "path";
|
|
119
|
+
import { spawnSync } from "child_process";
|
|
120
|
+
import { concat } from "lodash-es";
|
|
121
|
+
import { consola as consola2 } from "consola";
|
|
122
|
+
|
|
123
|
+
// src/core/vercel.ts
|
|
124
|
+
function getVercelProjectNameArg(config) {
|
|
125
|
+
return ["--project", config.vercelProjectName];
|
|
126
|
+
}
|
|
127
|
+
function getVercelScopeArg(config) {
|
|
128
|
+
return ["--scope", config.vercelOrgId];
|
|
129
|
+
}
|
|
130
|
+
function getVercelTokenArg(config) {
|
|
131
|
+
return ["--token", config.vercelToken];
|
|
132
|
+
}
|
|
133
|
+
function getVercelLocalConfigArg() {
|
|
134
|
+
return ["--local-config", VERCEL_NULL_CONFIG_PATH];
|
|
135
|
+
}
|
|
136
|
+
function getTargetCWDArg(target) {
|
|
137
|
+
return ["--cwd", target.targetCWD];
|
|
138
|
+
}
|
|
139
|
+
function createVercelSpawnOptions(stdoutMode = "inherit") {
|
|
140
|
+
const base = {
|
|
141
|
+
encoding: "utf8",
|
|
142
|
+
shell: process.platform === "win32"
|
|
143
|
+
};
|
|
144
|
+
if (stdoutMode === "pipe") {
|
|
145
|
+
return { ...base, stdio: ["inherit", "pipe", "inherit"] };
|
|
146
|
+
}
|
|
147
|
+
return { ...base, stdio: "inherit" };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/core/tasks/link.ts
|
|
151
|
+
function createLinkTask(config, target) {
|
|
152
|
+
return {
|
|
153
|
+
name: `Link: ${target.targetCWD}`,
|
|
154
|
+
fn: async () => {
|
|
155
|
+
const targetPath = resolve(target.targetCWD);
|
|
156
|
+
if (!fs.existsSync(targetPath)) {
|
|
157
|
+
const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
|
|
158
|
+
consola2.error(err.message);
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
const args = concat(
|
|
162
|
+
["link"],
|
|
163
|
+
["--yes"],
|
|
164
|
+
getTargetCWDArg(target),
|
|
165
|
+
getVercelProjectNameArg(config),
|
|
166
|
+
getVercelTokenArg(config)
|
|
167
|
+
);
|
|
168
|
+
consola2.start(`\u5F00\u59CB link \u4EFB\u52A1: ${target.targetCWD}`);
|
|
169
|
+
const result = spawnSync("vercel", args, createVercelSpawnOptions());
|
|
170
|
+
if (result.error) {
|
|
171
|
+
consola2.error(`link \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
|
|
172
|
+
throw result.error;
|
|
173
|
+
}
|
|
174
|
+
consola2.success(`\u5B8C\u6210 link \u4EFB\u52A1: ${target.targetCWD}`);
|
|
175
|
+
return result.stdout;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/core/tasks/build.ts
|
|
181
|
+
import fs2 from "fs";
|
|
182
|
+
import { resolve as resolve2 } from "path";
|
|
183
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
184
|
+
import { concat as concat2 } from "lodash-es";
|
|
185
|
+
import { consola as consola3 } from "consola";
|
|
186
|
+
function createBuildTask(config, target) {
|
|
187
|
+
return {
|
|
188
|
+
name: `Build: ${target.targetCWD}`,
|
|
189
|
+
fn: async () => {
|
|
190
|
+
const targetPath = resolve2(target.targetCWD);
|
|
191
|
+
if (!fs2.existsSync(targetPath)) {
|
|
192
|
+
const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
|
|
193
|
+
consola3.error(err.message);
|
|
194
|
+
throw err;
|
|
195
|
+
}
|
|
196
|
+
const args = concat2(
|
|
197
|
+
["build"],
|
|
198
|
+
["--yes"],
|
|
199
|
+
["--prod"],
|
|
200
|
+
getTargetCWDArg(target),
|
|
201
|
+
getVercelLocalConfigArg(),
|
|
202
|
+
getVercelTokenArg(config)
|
|
203
|
+
);
|
|
204
|
+
consola3.start(`\u5F00\u59CB build \u4EFB\u52A1: ${target.targetCWD}`);
|
|
205
|
+
const result = spawnSync2("vercel", args, createVercelSpawnOptions());
|
|
206
|
+
if (result.error) {
|
|
207
|
+
consola3.error(`build \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
|
|
208
|
+
throw result.error;
|
|
209
|
+
}
|
|
210
|
+
consola3.success(`\u5B8C\u6210 build \u4EFB\u52A1: ${target.targetCWD}`);
|
|
211
|
+
return result.stdout;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/core/tasks/after-build.ts
|
|
217
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
218
|
+
import { consola as consola4 } from "consola";
|
|
219
|
+
import { isUndefined as isUndefined2, isEmpty } from "lodash-es";
|
|
220
|
+
function createAfterBuildTasks(config) {
|
|
221
|
+
const afterBuildTasks = config.afterBuildTasks;
|
|
222
|
+
if (isUndefined2(afterBuildTasks) || isEmpty(afterBuildTasks)) {
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
name: "AfterBuild: \u65E0\u4EFB\u52A1",
|
|
226
|
+
fn: async () => {
|
|
227
|
+
consola4.warn("\u5F53\u524D\u6CA1\u6709\u6709\u610F\u4E49\u7684 afterBuildTasks \u4EFB\u52A1\u914D\u7F6E");
|
|
228
|
+
return void 0;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
];
|
|
232
|
+
}
|
|
233
|
+
return afterBuildTasks.map((command) => ({
|
|
234
|
+
name: `AfterBuild: ${command}`,
|
|
235
|
+
fn: async () => {
|
|
236
|
+
consola4.start(`\u5F00\u59CB afterBuild \u4EFB\u52A1: ${command}`);
|
|
237
|
+
const result = spawnSync3(command, [], {
|
|
238
|
+
encoding: "utf-8",
|
|
239
|
+
stdio: "inherit",
|
|
240
|
+
shell: true
|
|
241
|
+
});
|
|
242
|
+
if (result.error) {
|
|
243
|
+
consola4.error(`afterBuild \u4EFB\u52A1\u5931\u8D25: ${command}`);
|
|
244
|
+
throw result.error;
|
|
245
|
+
}
|
|
246
|
+
consola4.success(`\u5B8C\u6210 afterBuild \u4EFB\u52A1: ${command}`);
|
|
247
|
+
return result.stdout;
|
|
248
|
+
}
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/core/tasks/user-commands.ts
|
|
253
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
254
|
+
import { consola as consola5 } from "consola";
|
|
255
|
+
function createUserCommandTasks(target) {
|
|
256
|
+
return target.userCommands.map((command) => ({
|
|
257
|
+
name: `UserCommand: ${command}`,
|
|
258
|
+
fn: async () => {
|
|
259
|
+
consola5.start(`\u5F00\u59CB\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
|
|
260
|
+
const result = spawnSync4(command, [], {
|
|
261
|
+
encoding: "utf-8",
|
|
262
|
+
stdio: "inherit",
|
|
263
|
+
shell: true
|
|
264
|
+
});
|
|
265
|
+
if (result.error) {
|
|
266
|
+
consola5.error(`\u7528\u6237\u547D\u4EE4\u4EFB\u52A1\u5931\u8D25: ${command}`);
|
|
267
|
+
throw result.error;
|
|
268
|
+
}
|
|
269
|
+
consola5.success(`\u5B8C\u6210\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
|
|
270
|
+
return result.stdout;
|
|
271
|
+
}
|
|
272
|
+
}));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// src/core/tasks/copy-dist.ts
|
|
276
|
+
import { resolve as resolve3 } from "path";
|
|
277
|
+
import { rmSync, mkdirSync, cpSync } from "fs";
|
|
278
|
+
import { consola as consola6 } from "consola";
|
|
279
|
+
function createCopyDistTasks(target) {
|
|
280
|
+
const targetCWD = target.targetCWD;
|
|
281
|
+
const outputDirectory = target.outputDirectory;
|
|
282
|
+
function joinPath(dir) {
|
|
283
|
+
return resolve3(process.cwd(), targetCWD, dir);
|
|
284
|
+
}
|
|
285
|
+
const pathVercelOutputStatic = joinPath(VERCEL_OUTPUT_STATIC);
|
|
286
|
+
const pathOutputDirectory = joinPath(outputDirectory);
|
|
287
|
+
return [
|
|
288
|
+
{
|
|
289
|
+
name: `\u5220\u9664\u76EE\u5F55: ${pathVercelOutputStatic}`,
|
|
290
|
+
fn: async () => {
|
|
291
|
+
consola6.start(`\u5F00\u59CB\u5220\u9664\u6587\u4EF6\u4EFB\u52A1: ${pathVercelOutputStatic}`);
|
|
292
|
+
rmSync(pathVercelOutputStatic, { recursive: true, force: true });
|
|
293
|
+
consola6.success(`\u5220\u9664\u8BE5\u8DEF\u5F84\u7684\u6587\u4EF6: ${pathVercelOutputStatic}`);
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
name: `\u521B\u5EFA\u76EE\u5F55: ${pathVercelOutputStatic}`,
|
|
298
|
+
fn: async () => {
|
|
299
|
+
consola6.start(`\u5F00\u59CB\u521B\u5EFA\u6587\u4EF6\u5939\u4EFB\u52A1: ${pathVercelOutputStatic}`);
|
|
300
|
+
mkdirSync(pathVercelOutputStatic, { recursive: true });
|
|
301
|
+
consola6.success(`\u521B\u5EFA\u7684\u65B0\u76EE\u5F55\u4E3A: ${pathVercelOutputStatic}`);
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: `\u590D\u5236\u6587\u4EF6: ${pathOutputDirectory} -> ${pathVercelOutputStatic}`,
|
|
306
|
+
fn: async () => {
|
|
307
|
+
consola6.start(`\u5F00\u59CB\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
|
|
308
|
+
consola6.info(`\u4ECE ${pathOutputDirectory} \u5F00\u59CB`);
|
|
309
|
+
consola6.info(`\u590D\u5236\u5230 ${pathVercelOutputStatic} \u5185`);
|
|
310
|
+
cpSync(pathOutputDirectory, pathVercelOutputStatic, { recursive: true });
|
|
311
|
+
consola6.success(`\u5B8C\u6210\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/core/tasks/deploy.ts
|
|
318
|
+
import fs3 from "fs";
|
|
319
|
+
import { resolve as resolve4 } from "path";
|
|
320
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
321
|
+
import { concat as concat3 } from "lodash-es";
|
|
322
|
+
import { consola as consola7 } from "consola";
|
|
323
|
+
function createDeployTask(config, target) {
|
|
324
|
+
return {
|
|
325
|
+
name: `Deploy: ${target.targetCWD}`,
|
|
326
|
+
fn: async () => {
|
|
327
|
+
const targetPath = resolve4(target.targetCWD);
|
|
328
|
+
if (!fs3.existsSync(targetPath)) {
|
|
329
|
+
const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
|
|
330
|
+
consola7.error(err.message);
|
|
331
|
+
throw err;
|
|
332
|
+
}
|
|
333
|
+
const args = concat3(
|
|
334
|
+
["deploy"],
|
|
335
|
+
["--yes"],
|
|
336
|
+
["--prebuilt"],
|
|
337
|
+
["--prod"],
|
|
338
|
+
getTargetCWDArg(target),
|
|
339
|
+
getVercelTokenArg(config)
|
|
340
|
+
);
|
|
341
|
+
consola7.start(`\u5F00\u59CB\u90E8\u7F72\u4EFB\u52A1: ${target.targetCWD}`);
|
|
342
|
+
const result = spawnSync5("vercel", args, createVercelSpawnOptions("pipe"));
|
|
343
|
+
if (result.error) {
|
|
344
|
+
consola7.error(`\u90E8\u7F72\u5931\u8D25\u4E86: ${target.targetCWD}`);
|
|
345
|
+
consola7.error(result.error);
|
|
346
|
+
throw result.error;
|
|
347
|
+
}
|
|
348
|
+
const vercelUrl = result.stdout.toString().trim();
|
|
349
|
+
consola7.success(`\u5B8C\u6210\u90E8\u7F72\u4EFB\u52A1\uFF0C\u751F\u6210\u7684url\u4E3A:`);
|
|
350
|
+
consola7.box(vercelUrl);
|
|
351
|
+
return vercelUrl;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/core/tasks/alias.ts
|
|
357
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
358
|
+
import { concat as concat4 } from "lodash-es";
|
|
359
|
+
import { consola as consola8 } from "consola";
|
|
360
|
+
function createAliasTask(config, vercelUrl, userUrl) {
|
|
361
|
+
return {
|
|
362
|
+
name: `Alias: ${userUrl}`,
|
|
363
|
+
fn: async () => {
|
|
364
|
+
const args = concat4(["alias", "set", vercelUrl, userUrl], getVercelTokenArg(config), getVercelScopeArg(config));
|
|
365
|
+
consola8.start(`\u5F00\u59CB\u522B\u540D\u4EFB\u52A1: ${userUrl}`);
|
|
366
|
+
const result = spawnSync6("vercel", args, createVercelSpawnOptions());
|
|
367
|
+
if (result.error) {
|
|
368
|
+
consola8.error(`\u522B\u540D\u4EFB\u52A1\u5931\u8D25: ${userUrl}`);
|
|
369
|
+
throw result.error;
|
|
370
|
+
}
|
|
371
|
+
consola8.success(`\u5B8C\u6210\u522B\u540D\u4EFB\u52A1\uFF0C\u53EF\u7528\u7684\u522B\u540D\u5730\u5740\u4E3A:`);
|
|
372
|
+
consola8.box(`https://${userUrl}`);
|
|
373
|
+
return result.stdout;
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/core/tasks/index.ts
|
|
379
|
+
async function generateVercelNullConfig() {
|
|
380
|
+
fs4.writeFileSync(VERCEL_NULL_CONFIG_PATH, JSON.stringify(VERCEL_NULL_CONFIG, null, 2));
|
|
381
|
+
consola9.success(`\u751F\u6210 Vercel \u7A7A\u914D\u7F6E\u6587\u4EF6: ${VERCEL_NULL_CONFIG_PATH}`);
|
|
382
|
+
}
|
|
383
|
+
async function executeDeploymentWorkflow(config) {
|
|
384
|
+
await generateVercelNullConfig();
|
|
385
|
+
const { deployTargets } = config;
|
|
386
|
+
const availableTargets = deployTargets.filter((target) => {
|
|
387
|
+
const targetPath = resolve5(target.targetCWD);
|
|
388
|
+
if (!fs4.existsSync(targetPath)) {
|
|
389
|
+
consola9.warn(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u5DF2\u8DF3\u8FC7: ${target.targetCWD}`);
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
return true;
|
|
393
|
+
});
|
|
394
|
+
if (availableTargets.length === 0) {
|
|
395
|
+
consola9.error("\u6CA1\u6709\u53EF\u7528\u7684\u90E8\u7F72\u76EE\u6807\uFF0C\u8BF7\u5148\u6784\u5EFA\u4EA7\u7269");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
await task("Vercel \u90E8\u7F72\u5DE5\u4F5C\u6D41", async ({ task: task2 }) => {
|
|
399
|
+
await task2("1. Link \u9879\u76EE", async () => {
|
|
400
|
+
const linkTasks = availableTargets.map((target) => createLinkTask(config, target));
|
|
401
|
+
await task2.group((task3) => linkTasks.map((t) => task3(t.name, t.fn)));
|
|
402
|
+
});
|
|
403
|
+
await task2("2. \u6784\u5EFA\u9879\u76EE", async () => {
|
|
404
|
+
const buildTasks = availableTargets.filter(isNeedVercelBuild).map((target) => createBuildTask(config, target));
|
|
405
|
+
if (buildTasks.length === 0) {
|
|
406
|
+
consola9.warn("\u6CA1\u6709\u9700\u8981\u6267\u884C build \u7684\u76EE\u6807");
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
await task2.group((task3) => buildTasks.map((t) => task3(t.name, t.fn)));
|
|
410
|
+
});
|
|
411
|
+
await task2("3. \u6267\u884C AfterBuild \u4EFB\u52A1", async () => {
|
|
412
|
+
const afterBuildTasks = createAfterBuildTasks(config);
|
|
413
|
+
await executeSequential("AfterBuild", afterBuildTasks);
|
|
414
|
+
});
|
|
415
|
+
await task2("4. \u6267\u884C\u7528\u6237\u547D\u4EE4\u4E0E\u6587\u4EF6\u590D\u5236", async () => {
|
|
416
|
+
const targetTasks = availableTargets.map((target) => ({
|
|
417
|
+
name: `\u5904\u7406\u76EE\u6807: ${target.targetCWD}`,
|
|
418
|
+
fn: async () => {
|
|
419
|
+
if (!isDeployTargetWithUserCommands(target)) {
|
|
420
|
+
consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u5C5E\u4E8E userCommands \u7C7B\u578B`);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
const userCommandTasks = createUserCommandTasks(target);
|
|
424
|
+
await executeSequential(`UserCommands: ${target.targetCWD}`, userCommandTasks);
|
|
425
|
+
if (getIsCopyDist(target)) {
|
|
426
|
+
const copyDistTasks = createCopyDistTasks(target);
|
|
427
|
+
await executeSequential(`CopyDist: ${target.targetCWD}`, copyDistTasks);
|
|
428
|
+
} else {
|
|
429
|
+
consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u9700\u8981\u590D\u5236\u6587\u4EF6`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}));
|
|
433
|
+
await task2.group((task3) => targetTasks.map((t) => task3(t.name, t.fn)));
|
|
434
|
+
});
|
|
435
|
+
await task2("5. \u90E8\u7F72\u4E0E\u8BBE\u7F6E\u522B\u540D", async () => {
|
|
436
|
+
const deployAliasTasks = availableTargets.map((target) => ({
|
|
437
|
+
name: `\u90E8\u7F72\u4E0E\u522B\u540D: ${target.targetCWD}`,
|
|
438
|
+
fn: async () => {
|
|
439
|
+
const deployTask = createDeployTask(config, target);
|
|
440
|
+
const deployResult = await task2(deployTask.name, deployTask.fn);
|
|
441
|
+
const vercelUrl = deployResult.result;
|
|
442
|
+
if (target.url && target.url.length > 0) {
|
|
443
|
+
const aliasTasks = target.url.map((userUrl) => createAliasTask(config, vercelUrl, userUrl));
|
|
444
|
+
await task2.group((task3) => aliasTasks.map((t) => task3(t.name, t.fn)));
|
|
445
|
+
} else {
|
|
446
|
+
consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u6CA1\u6709\u914D\u7F6E\u522B\u540D`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}));
|
|
450
|
+
await task2.group((task3) => deployAliasTasks.map((t) => task3(t.name, t.fn)));
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
consola9.success("\u{1F389} Vercel \u90E8\u7F72\u5DE5\u4F5C\u6D41\u5B8C\u6210\uFF01");
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/commands/deploy.ts
|
|
457
|
+
function createDeployCommand() {
|
|
458
|
+
const command = new Command("deploy");
|
|
459
|
+
command.description("\u90E8\u7F72\u9879\u76EE\u5230 Vercel").option("--env-path <path>", "\u6307\u5B9A dotenv \u6587\u4EF6\u8DEF\u5F84\uFF0C\u7528\u4E8E\u8986\u76D6\u9ED8\u8BA4\u73AF\u5883\u53D8\u91CF").action(async (options) => {
|
|
460
|
+
try {
|
|
461
|
+
if (options?.envPath) {
|
|
462
|
+
process.env.VERCEL_DEPLOY_TOOL_ENV_PATH = options.envPath;
|
|
463
|
+
dotenvxConfig2({ path: options.envPath });
|
|
464
|
+
consola10.info(`\u5DF2\u4ECE --env-path \u52A0\u8F7D\u73AF\u5883\u53D8\u91CF: ${options.envPath}`);
|
|
465
|
+
}
|
|
466
|
+
consola10.start("\u5F00\u59CB\u52A0\u8F7D\u914D\u7F6E...");
|
|
467
|
+
const config = await loadConfig();
|
|
468
|
+
consola10.start("\u5F00\u59CB\u6267\u884C\u90E8\u7F72\u5DE5\u4F5C\u6D41...");
|
|
469
|
+
await executeDeploymentWorkflow(config);
|
|
470
|
+
consola10.success("\u90E8\u7F72\u5B8C\u6210\uFF01");
|
|
471
|
+
} catch (error) {
|
|
472
|
+
consola10.error("\u90E8\u7F72\u5931\u8D25:");
|
|
473
|
+
consola10.error(error);
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
return command;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/commands/init.ts
|
|
481
|
+
import { Command as Command2 } from "commander";
|
|
482
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
483
|
+
import { join, dirname } from "path";
|
|
484
|
+
import { fileURLToPath } from "url";
|
|
485
|
+
import { consola as consola11 } from "consola";
|
|
486
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
487
|
+
var __dirname2 = dirname(__filename2);
|
|
488
|
+
function createInitCommand() {
|
|
489
|
+
const command = new Command2("init");
|
|
490
|
+
command.description("\u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6").option("-f, --force", "\u5F3A\u5236\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u6587\u4EF6").action((options) => {
|
|
491
|
+
const cwd = process.cwd();
|
|
492
|
+
const configFile = "vercel-deploy-tool.config.ts";
|
|
493
|
+
const targetPath = join(cwd, configFile);
|
|
494
|
+
if (existsSync(targetPath) && !options.force) {
|
|
495
|
+
consola11.warn(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728: ${configFile}`);
|
|
496
|
+
consola11.info("\u4F7F\u7528 --force \u9009\u9879\u53EF\u4EE5\u8986\u76D6");
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
const templatePath = join(__dirname2, "..", "templates", configFile);
|
|
500
|
+
if (!existsSync(templatePath)) {
|
|
501
|
+
consola11.error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${templatePath}`);
|
|
502
|
+
consola11.error("\u8BF7\u786E\u4FDD @ruan-cat/vercel-deploy-tool \u5305\u5DF2\u6B63\u786E\u5B89\u88C5");
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
const content = readFileSync(templatePath, "utf-8");
|
|
506
|
+
writeFileSync(targetPath, content, "utf-8");
|
|
507
|
+
consola11.success(`\u5DF2\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ${configFile}`);
|
|
508
|
+
const pkgPath = join(cwd, "package.json");
|
|
509
|
+
if (existsSync(pkgPath)) {
|
|
510
|
+
try {
|
|
511
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
512
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
513
|
+
pkg.scripts["deploy-vercel"] = "vercel-deploy-tool deploy";
|
|
514
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
515
|
+
consola11.success('\u5DF2\u6DFB\u52A0\u811A\u672C: "deploy-vercel"');
|
|
516
|
+
} catch (error) {
|
|
517
|
+
consola11.warn("\u66F4\u65B0 package.json \u5931\u8D25:", error);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
consola11.box(`\u{1F389} \u521D\u59CB\u5316\u5B8C\u6210\uFF01
|
|
521
|
+
|
|
522
|
+
\u521B\u5EFA\u7684\u6587\u4EF6:
|
|
523
|
+
\u2022 ${configFile} - Vercel \u90E8\u7F72\u914D\u7F6E\u6587\u4EF6
|
|
524
|
+
|
|
525
|
+
\u6DFB\u52A0\u7684\u811A\u672C:
|
|
526
|
+
\u2022 deploy-vercel: vercel-deploy-tool deploy
|
|
527
|
+
|
|
528
|
+
\u4E0B\u4E00\u6B65:
|
|
529
|
+
1. \u7F16\u8F91 ${configFile} \u586B\u5199\u4F60\u7684\u914D\u7F6E
|
|
530
|
+
2. \u786E\u4FDD\u73AF\u5883\u53D8\u91CF\u5DF2\u8BBE\u7F6E:
|
|
531
|
+
- VERCEL_TOKEN
|
|
532
|
+
- VERCEL_ORG_ID
|
|
533
|
+
- VERCEL_PROJECT_ID
|
|
534
|
+
3. \u8FD0\u884C\u90E8\u7F72:
|
|
535
|
+
pnpm run deploy-vercel`);
|
|
536
|
+
});
|
|
537
|
+
return command;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/cli.ts
|
|
541
|
+
var __filename3 = fileURLToPath2(import.meta.url);
|
|
542
|
+
var __dirname3 = path.dirname(__filename3);
|
|
543
|
+
var packageJsonPath = path.join(__dirname3, "..", "package.json");
|
|
544
|
+
var packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
545
|
+
var { version } = packageJson;
|
|
546
|
+
var program = new Command3();
|
|
547
|
+
program.name("vercel-deploy-tool").description("Vercel \u90E8\u7F72\u5DE5\u5177 - \u652F\u6301 monorepo \u7684\u81EA\u52A8\u5316\u90E8\u7F72").version(version);
|
|
548
|
+
program.addCommand(createDeployCommand());
|
|
549
|
+
program.addCommand(createInitCommand());
|
|
550
|
+
program.on("--help", () => {
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log("\u4F7F\u7528\u793A\u4F8B / Usage Examples:");
|
|
553
|
+
console.log("");
|
|
554
|
+
console.log(" # \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6");
|
|
555
|
+
console.log(" vercel-deploy-tool init");
|
|
556
|
+
console.log(" vdt init");
|
|
557
|
+
console.log("");
|
|
558
|
+
console.log(" # \u90E8\u7F72\u9879\u76EE");
|
|
559
|
+
console.log(" vercel-deploy-tool deploy");
|
|
560
|
+
console.log(" vdt deploy");
|
|
561
|
+
console.log("");
|
|
562
|
+
console.log(" # \u67E5\u770B\u5E2E\u52A9");
|
|
563
|
+
console.log(" vercel-deploy-tool --help");
|
|
564
|
+
console.log(" vdt --help");
|
|
565
|
+
console.log("");
|
|
566
|
+
console.log("\u73AF\u5883\u53D8\u91CF / Environment Variables:");
|
|
567
|
+
console.log(" VERCEL_TOKEN - Vercel API Token");
|
|
568
|
+
console.log(" VERCEL_ORG_ID - Vercel \u7EC4\u7EC7 ID");
|
|
569
|
+
console.log(" VERCEL_PROJECT_ID - Vercel \u9879\u76EE ID");
|
|
570
|
+
console.log("");
|
|
571
|
+
});
|
|
572
|
+
async function main() {
|
|
573
|
+
await program.parseAsync();
|
|
574
|
+
}
|
|
575
|
+
main().catch((error) => {
|
|
576
|
+
console.error(error);
|
|
577
|
+
process.exit(1);
|
|
578
|
+
});
|