@ruan-cat/vercel-deploy-tool 1.2.7 → 1.4.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/dist/index.js CHANGED
@@ -59,7 +59,7 @@ async function getConfig() {
59
59
  // src/core/tasks/index.ts
60
60
  import fs4 from "fs";
61
61
  import { resolve as resolve5 } from "path";
62
- import { consola as consola9 } from "consola";
62
+ import { consola as consola10 } from "consola";
63
63
 
64
64
  // src/core/executor.ts
65
65
  import task from "tasuku";
@@ -115,12 +115,60 @@ var VERCEL_NULL_CONFIG = {
115
115
  var VERCEL_NULL_CONFIG_PATH = "./vercel.null.def.json";
116
116
  var VERCEL_OUTPUT_STATIC = ".vercel/output/static";
117
117
 
118
+ // src/core/git-diff-filter.ts
119
+ import { spawnSync } from "child_process";
120
+ import picomatch from "picomatch";
121
+ import { consola as consola2 } from "consola";
122
+ function getChangedFiles(diffBase) {
123
+ if (!diffBase) {
124
+ consola2.warn("\u672A\u63D0\u4F9B diffBase\uFF0C\u65E0\u6CD5\u68C0\u6D4B\u53D8\u66F4\u6587\u4EF6\uFF0C\u5C06\u964D\u7EA7\u4E3A\u5168\u91CF\u90E8\u7F72");
125
+ return null;
126
+ }
127
+ const result = spawnSync("git", ["diff", "--name-only", diffBase, "HEAD"], {
128
+ encoding: "utf-8"
129
+ });
130
+ if (result.error) {
131
+ consola2.warn(`git \u547D\u4EE4\u4E0D\u53EF\u7528\u6216\u6267\u884C\u5931\u8D25: ${result.error.message}\uFF0C\u5C06\u964D\u7EA7\u4E3A\u5168\u91CF\u90E8\u7F72`);
132
+ return null;
133
+ }
134
+ if (result.status !== 0) {
135
+ consola2.warn(`git diff \u8FD4\u56DE\u975E\u96F6\u9000\u51FA\u7801 ${result.status}\uFF0C\u5C06\u964D\u7EA7\u4E3A\u5168\u91CF\u90E8\u7F72`);
136
+ if (result.stderr?.trim()) {
137
+ consola2.warn(result.stderr.trim());
138
+ }
139
+ return null;
140
+ }
141
+ const output = result.stdout?.trim();
142
+ if (!output) {
143
+ return [];
144
+ }
145
+ return output.split("\n").filter(Boolean);
146
+ }
147
+ function filterTargetsByDiff(targets, changedFiles) {
148
+ const deploy = [];
149
+ const skipped = [];
150
+ for (const target of targets) {
151
+ if (!target.watchPaths || target.watchPaths.length === 0) {
152
+ deploy.push(target);
153
+ continue;
154
+ }
155
+ const isMatch = picomatch(target.watchPaths);
156
+ const hasChange = changedFiles.some((file) => isMatch(file));
157
+ if (hasChange) {
158
+ deploy.push(target);
159
+ } else {
160
+ skipped.push(target);
161
+ }
162
+ }
163
+ return { deploy, skipped };
164
+ }
165
+
118
166
  // src/core/tasks/link.ts
119
167
  import fs from "fs";
120
168
  import { resolve } from "path";
121
- import { spawnSync } from "child_process";
169
+ import { spawnSync as spawnSync2 } from "child_process";
122
170
  import { concat } from "lodash-es";
123
- import { consola as consola2 } from "consola";
171
+ import { consola as consola3 } from "consola";
124
172
 
125
173
  // src/core/vercel.ts
126
174
  function getVercelProjectNameArg(config) {
@@ -157,7 +205,7 @@ function createLinkTask(config, target) {
157
205
  const targetPath = resolve(target.targetCWD);
158
206
  if (!fs.existsSync(targetPath)) {
159
207
  const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
160
- consola2.error(err.message);
208
+ consola3.error(err.message);
161
209
  throw err;
162
210
  }
163
211
  const args = concat(
@@ -167,13 +215,13 @@ function createLinkTask(config, target) {
167
215
  getVercelProjectNameArg(config),
168
216
  getVercelTokenArg(config)
169
217
  );
170
- consola2.start(`\u5F00\u59CB link \u4EFB\u52A1: ${target.targetCWD}`);
171
- const result = spawnSync("vercel", args, createVercelSpawnOptions());
218
+ consola3.start(`\u5F00\u59CB link \u4EFB\u52A1: ${target.targetCWD}`);
219
+ const result = spawnSync2("vercel", args, createVercelSpawnOptions());
172
220
  if (result.error) {
173
- consola2.error(`link \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
221
+ consola3.error(`link \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
174
222
  throw result.error;
175
223
  }
176
- consola2.success(`\u5B8C\u6210 link \u4EFB\u52A1: ${target.targetCWD}`);
224
+ consola3.success(`\u5B8C\u6210 link \u4EFB\u52A1: ${target.targetCWD}`);
177
225
  return result.stdout;
178
226
  }
179
227
  };
@@ -182,9 +230,9 @@ function createLinkTask(config, target) {
182
230
  // src/core/tasks/build.ts
183
231
  import fs2 from "fs";
184
232
  import { resolve as resolve2 } from "path";
185
- import { spawnSync as spawnSync2 } from "child_process";
233
+ import { spawnSync as spawnSync3 } from "child_process";
186
234
  import { concat as concat2 } from "lodash-es";
187
- import { consola as consola3 } from "consola";
235
+ import { consola as consola4 } from "consola";
188
236
  function createBuildTask(config, target) {
189
237
  return {
190
238
  name: `Build: ${target.targetCWD}`,
@@ -192,7 +240,7 @@ function createBuildTask(config, target) {
192
240
  const targetPath = resolve2(target.targetCWD);
193
241
  if (!fs2.existsSync(targetPath)) {
194
242
  const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
195
- consola3.error(err.message);
243
+ consola4.error(err.message);
196
244
  throw err;
197
245
  }
198
246
  const args = concat2(
@@ -203,21 +251,21 @@ function createBuildTask(config, target) {
203
251
  getVercelLocalConfigArg(),
204
252
  getVercelTokenArg(config)
205
253
  );
206
- consola3.start(`\u5F00\u59CB build \u4EFB\u52A1: ${target.targetCWD}`);
207
- const result = spawnSync2("vercel", args, createVercelSpawnOptions());
254
+ consola4.start(`\u5F00\u59CB build \u4EFB\u52A1: ${target.targetCWD}`);
255
+ const result = spawnSync3("vercel", args, createVercelSpawnOptions());
208
256
  if (result.error) {
209
- consola3.error(`build \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
257
+ consola4.error(`build \u4EFB\u52A1\u5931\u8D25: ${target.targetCWD}`);
210
258
  throw result.error;
211
259
  }
212
- consola3.success(`\u5B8C\u6210 build \u4EFB\u52A1: ${target.targetCWD}`);
260
+ consola4.success(`\u5B8C\u6210 build \u4EFB\u52A1: ${target.targetCWD}`);
213
261
  return result.stdout;
214
262
  }
215
263
  };
216
264
  }
217
265
 
218
266
  // src/core/tasks/after-build.ts
219
- import { spawnSync as spawnSync3 } from "child_process";
220
- import { consola as consola4 } from "consola";
267
+ import { spawnSync as spawnSync4 } from "child_process";
268
+ import { consola as consola5 } from "consola";
221
269
  import { isUndefined as isUndefined2, isEmpty } from "lodash-es";
222
270
  function createAfterBuildTasks(config) {
223
271
  const afterBuildTasks = config.afterBuildTasks;
@@ -226,7 +274,7 @@ function createAfterBuildTasks(config) {
226
274
  {
227
275
  name: "AfterBuild: \u65E0\u4EFB\u52A1",
228
276
  fn: async () => {
229
- consola4.warn("\u5F53\u524D\u6CA1\u6709\u6709\u610F\u4E49\u7684 afterBuildTasks \u4EFB\u52A1\u914D\u7F6E");
277
+ consola5.warn("\u5F53\u524D\u6CA1\u6709\u6709\u610F\u4E49\u7684 afterBuildTasks \u4EFB\u52A1\u914D\u7F6E");
230
278
  return void 0;
231
279
  }
232
280
  }
@@ -235,40 +283,40 @@ function createAfterBuildTasks(config) {
235
283
  return afterBuildTasks.map((command) => ({
236
284
  name: `AfterBuild: ${command}`,
237
285
  fn: async () => {
238
- consola4.start(`\u5F00\u59CB afterBuild \u4EFB\u52A1: ${command}`);
239
- const result = spawnSync3(command, [], {
286
+ consola5.start(`\u5F00\u59CB afterBuild \u4EFB\u52A1: ${command}`);
287
+ const result = spawnSync4(command, [], {
240
288
  encoding: "utf-8",
241
289
  stdio: "inherit",
242
290
  shell: true
243
291
  });
244
292
  if (result.error) {
245
- consola4.error(`afterBuild \u4EFB\u52A1\u5931\u8D25: ${command}`);
293
+ consola5.error(`afterBuild \u4EFB\u52A1\u5931\u8D25: ${command}`);
246
294
  throw result.error;
247
295
  }
248
- consola4.success(`\u5B8C\u6210 afterBuild \u4EFB\u52A1: ${command}`);
296
+ consola5.success(`\u5B8C\u6210 afterBuild \u4EFB\u52A1: ${command}`);
249
297
  return result.stdout;
250
298
  }
251
299
  }));
252
300
  }
253
301
 
254
302
  // src/core/tasks/user-commands.ts
255
- import { spawnSync as spawnSync4 } from "child_process";
256
- import { consola as consola5 } from "consola";
303
+ import { spawnSync as spawnSync5 } from "child_process";
304
+ import { consola as consola6 } from "consola";
257
305
  function createUserCommandTasks(target) {
258
306
  return target.userCommands.map((command) => ({
259
307
  name: `UserCommand: ${command}`,
260
308
  fn: async () => {
261
- consola5.start(`\u5F00\u59CB\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
262
- const result = spawnSync4(command, [], {
309
+ consola6.start(`\u5F00\u59CB\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
310
+ const result = spawnSync5(command, [], {
263
311
  encoding: "utf-8",
264
312
  stdio: "inherit",
265
313
  shell: true
266
314
  });
267
315
  if (result.error) {
268
- consola5.error(`\u7528\u6237\u547D\u4EE4\u4EFB\u52A1\u5931\u8D25: ${command}`);
316
+ consola6.error(`\u7528\u6237\u547D\u4EE4\u4EFB\u52A1\u5931\u8D25: ${command}`);
269
317
  throw result.error;
270
318
  }
271
- consola5.success(`\u5B8C\u6210\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
319
+ consola6.success(`\u5B8C\u6210\u7528\u6237\u547D\u4EE4\u4EFB\u52A1: ${command}`);
272
320
  return result.stdout;
273
321
  }
274
322
  }));
@@ -277,7 +325,7 @@ function createUserCommandTasks(target) {
277
325
  // src/core/tasks/copy-dist.ts
278
326
  import { resolve as resolve3 } from "path";
279
327
  import { rmSync, mkdirSync, cpSync } from "fs";
280
- import { consola as consola6 } from "consola";
328
+ import { consola as consola7 } from "consola";
281
329
  function createCopyDistTasks(target) {
282
330
  const targetCWD = target.targetCWD;
283
331
  const outputDirectory = target.outputDirectory;
@@ -290,27 +338,27 @@ function createCopyDistTasks(target) {
290
338
  {
291
339
  name: `\u5220\u9664\u76EE\u5F55: ${pathVercelOutputStatic}`,
292
340
  fn: async () => {
293
- consola6.start(`\u5F00\u59CB\u5220\u9664\u6587\u4EF6\u4EFB\u52A1: ${pathVercelOutputStatic}`);
341
+ consola7.start(`\u5F00\u59CB\u5220\u9664\u6587\u4EF6\u4EFB\u52A1: ${pathVercelOutputStatic}`);
294
342
  rmSync(pathVercelOutputStatic, { recursive: true, force: true });
295
- consola6.success(`\u5220\u9664\u8BE5\u8DEF\u5F84\u7684\u6587\u4EF6: ${pathVercelOutputStatic}`);
343
+ consola7.success(`\u5220\u9664\u8BE5\u8DEF\u5F84\u7684\u6587\u4EF6: ${pathVercelOutputStatic}`);
296
344
  }
297
345
  },
298
346
  {
299
347
  name: `\u521B\u5EFA\u76EE\u5F55: ${pathVercelOutputStatic}`,
300
348
  fn: async () => {
301
- consola6.start(`\u5F00\u59CB\u521B\u5EFA\u6587\u4EF6\u5939\u4EFB\u52A1: ${pathVercelOutputStatic}`);
349
+ consola7.start(`\u5F00\u59CB\u521B\u5EFA\u6587\u4EF6\u5939\u4EFB\u52A1: ${pathVercelOutputStatic}`);
302
350
  mkdirSync(pathVercelOutputStatic, { recursive: true });
303
- consola6.success(`\u521B\u5EFA\u7684\u65B0\u76EE\u5F55\u4E3A: ${pathVercelOutputStatic}`);
351
+ consola7.success(`\u521B\u5EFA\u7684\u65B0\u76EE\u5F55\u4E3A: ${pathVercelOutputStatic}`);
304
352
  }
305
353
  },
306
354
  {
307
355
  name: `\u590D\u5236\u6587\u4EF6: ${pathOutputDirectory} -> ${pathVercelOutputStatic}`,
308
356
  fn: async () => {
309
- consola6.start(`\u5F00\u59CB\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
310
- consola6.info(`\u4ECE ${pathOutputDirectory} \u5F00\u59CB`);
311
- consola6.info(`\u590D\u5236\u5230 ${pathVercelOutputStatic} \u5185`);
357
+ consola7.start(`\u5F00\u59CB\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
358
+ consola7.info(`\u4ECE ${pathOutputDirectory} \u5F00\u59CB`);
359
+ consola7.info(`\u590D\u5236\u5230 ${pathVercelOutputStatic} \u5185`);
312
360
  cpSync(pathOutputDirectory, pathVercelOutputStatic, { recursive: true });
313
- consola6.success(`\u5B8C\u6210\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
361
+ consola7.success(`\u5B8C\u6210\u6587\u4EF6\u590D\u5236\u4EFB\u52A1`);
314
362
  }
315
363
  }
316
364
  ];
@@ -319,9 +367,9 @@ function createCopyDistTasks(target) {
319
367
  // src/core/tasks/deploy.ts
320
368
  import fs3 from "fs";
321
369
  import { resolve as resolve4 } from "path";
322
- import { spawnSync as spawnSync5 } from "child_process";
370
+ import { spawnSync as spawnSync6 } from "child_process";
323
371
  import { concat as concat3 } from "lodash-es";
324
- import { consola as consola7 } from "consola";
372
+ import { consola as consola8 } from "consola";
325
373
  function createDeployTask(config, target) {
326
374
  return {
327
375
  name: `Deploy: ${target.targetCWD}`,
@@ -329,7 +377,7 @@ function createDeployTask(config, target) {
329
377
  const targetPath = resolve4(target.targetCWD);
330
378
  if (!fs3.existsSync(targetPath)) {
331
379
  const err = new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6784\u5EFA: ${target.targetCWD}`);
332
- consola7.error(err.message);
380
+ consola8.error(err.message);
333
381
  throw err;
334
382
  }
335
383
  const args = concat3(
@@ -340,38 +388,38 @@ function createDeployTask(config, target) {
340
388
  getTargetCWDArg(target),
341
389
  getVercelTokenArg(config)
342
390
  );
343
- consola7.start(`\u5F00\u59CB\u90E8\u7F72\u4EFB\u52A1: ${target.targetCWD}`);
344
- const result = spawnSync5("vercel", args, createVercelSpawnOptions("pipe"));
391
+ consola8.start(`\u5F00\u59CB\u90E8\u7F72\u4EFB\u52A1: ${target.targetCWD}`);
392
+ const result = spawnSync6("vercel", args, createVercelSpawnOptions("pipe"));
345
393
  if (result.error) {
346
- consola7.error(`\u90E8\u7F72\u5931\u8D25\u4E86: ${target.targetCWD}`);
347
- consola7.error(result.error);
394
+ consola8.error(`\u90E8\u7F72\u5931\u8D25\u4E86: ${target.targetCWD}`);
395
+ consola8.error(result.error);
348
396
  throw result.error;
349
397
  }
350
398
  const vercelUrl = result.stdout.toString().trim();
351
- consola7.success(`\u5B8C\u6210\u90E8\u7F72\u4EFB\u52A1\uFF0C\u751F\u6210\u7684url\u4E3A:`);
352
- consola7.box(vercelUrl);
399
+ consola8.success(`\u5B8C\u6210\u90E8\u7F72\u4EFB\u52A1\uFF0C\u751F\u6210\u7684url\u4E3A:`);
400
+ consola8.box(vercelUrl);
353
401
  return vercelUrl;
354
402
  }
355
403
  };
356
404
  }
357
405
 
358
406
  // src/core/tasks/alias.ts
359
- import { spawnSync as spawnSync6 } from "child_process";
407
+ import { spawnSync as spawnSync7 } from "child_process";
360
408
  import { concat as concat4 } from "lodash-es";
361
- import { consola as consola8 } from "consola";
409
+ import { consola as consola9 } from "consola";
362
410
  function createAliasTask(config, vercelUrl, userUrl) {
363
411
  return {
364
412
  name: `Alias: ${userUrl}`,
365
413
  fn: async () => {
366
414
  const args = concat4(["alias", "set", vercelUrl, userUrl], getVercelTokenArg(config), getVercelScopeArg(config));
367
- consola8.start(`\u5F00\u59CB\u522B\u540D\u4EFB\u52A1: ${userUrl}`);
368
- const result = spawnSync6("vercel", args, createVercelSpawnOptions());
415
+ consola9.start(`\u5F00\u59CB\u522B\u540D\u4EFB\u52A1: ${userUrl}`);
416
+ const result = spawnSync7("vercel", args, createVercelSpawnOptions());
369
417
  if (result.error) {
370
- consola8.error(`\u522B\u540D\u4EFB\u52A1\u5931\u8D25: ${userUrl}`);
418
+ consola9.error(`\u522B\u540D\u4EFB\u52A1\u5931\u8D25: ${userUrl}`);
371
419
  throw result.error;
372
420
  }
373
- consola8.success(`\u5B8C\u6210\u522B\u540D\u4EFB\u52A1\uFF0C\u53EF\u7528\u7684\u522B\u540D\u5730\u5740\u4E3A:`);
374
- consola8.box(`https://${userUrl}`);
421
+ consola9.success(`\u5B8C\u6210\u522B\u540D\u4EFB\u52A1\uFF0C\u53EF\u7528\u7684\u522B\u540D\u5730\u5740\u4E3A:`);
422
+ consola9.box(`https://${userUrl}`);
375
423
  return result.stdout;
376
424
  }
377
425
  };
@@ -380,32 +428,59 @@ function createAliasTask(config, vercelUrl, userUrl) {
380
428
  // src/core/tasks/index.ts
381
429
  async function generateVercelNullConfig() {
382
430
  fs4.writeFileSync(VERCEL_NULL_CONFIG_PATH, JSON.stringify(VERCEL_NULL_CONFIG, null, 2));
383
- consola9.success(`\u751F\u6210 Vercel \u7A7A\u914D\u7F6E\u6587\u4EF6: ${VERCEL_NULL_CONFIG_PATH}`);
431
+ consola10.success(`\u751F\u6210 Vercel \u7A7A\u914D\u7F6E\u6587\u4EF6: ${VERCEL_NULL_CONFIG_PATH}`);
384
432
  }
385
- async function executeDeploymentWorkflow(config) {
433
+ async function executeDeploymentWorkflow(config, options) {
386
434
  await generateVercelNullConfig();
387
435
  const { deployTargets } = config;
388
436
  const availableTargets = deployTargets.filter((target) => {
389
437
  const targetPath = resolve5(target.targetCWD);
390
438
  if (!fs4.existsSync(targetPath)) {
391
- consola9.warn(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u5DF2\u8DF3\u8FC7: ${target.targetCWD}`);
439
+ consola10.warn(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u5DF2\u8DF3\u8FC7: ${target.targetCWD}`);
392
440
  return false;
393
441
  }
394
442
  return true;
395
443
  });
396
444
  if (availableTargets.length === 0) {
397
- consola9.error("\u6CA1\u6709\u53EF\u7528\u7684\u90E8\u7F72\u76EE\u6807\uFF0C\u8BF7\u5148\u6784\u5EFA\u4EA7\u7269");
445
+ consola10.error("\u6CA1\u6709\u53EF\u7528\u7684\u90E8\u7F72\u76EE\u6807\uFF0C\u8BF7\u5148\u6784\u5EFA\u4EA7\u7269");
398
446
  return;
399
447
  }
400
448
  await task("Vercel \u90E8\u7F72\u5DE5\u4F5C\u6D41", async ({ task: task2 }) => {
449
+ const { result: finalTargets } = await task2("0. \u68C0\u6D4B\u53D8\u66F4\u8303\u56F4", async ({ setTitle }) => {
450
+ if (options?.forceAll) {
451
+ setTitle("0. \u5F3A\u5236\u5168\u91CF\u90E8\u7F72\uFF08--force-all\uFF09");
452
+ return availableTargets;
453
+ }
454
+ if (!options?.diffBase) {
455
+ setTitle("0. \u5168\u91CF\u90E8\u7F72\uFF08\u672A\u6307\u5B9A --diff-base\uFF09");
456
+ return availableTargets;
457
+ }
458
+ const changedFiles = getChangedFiles(options.diffBase);
459
+ if (changedFiles === null) {
460
+ setTitle("0. Git \u4E0D\u53EF\u7528\uFF0C\u5DF2\u964D\u7EA7\u4E3A\u5168\u91CF\u90E8\u7F72");
461
+ return availableTargets;
462
+ }
463
+ if (changedFiles.length === 0) {
464
+ setTitle("0. \u65E0\u6587\u4EF6\u53D8\u66F4\uFF0C\u8DF3\u8FC7\u6240\u6709\u90E8\u7F72");
465
+ return [];
466
+ }
467
+ const { deploy, skipped } = filterTargetsByDiff(availableTargets, changedFiles);
468
+ skipped.forEach((t) => consola10.info(`\u8DF3\u8FC7\u672A\u53D8\u66F4\u76EE\u6807: ${t.targetCWD}`));
469
+ setTitle(`0. \u7CBE\u786E\u90E8\u7F72: ${deploy.length} / ${availableTargets.length} \u4E2A\u76EE\u6807`);
470
+ return deploy;
471
+ });
472
+ if (finalTargets.length === 0) {
473
+ consola10.success("\u6240\u6709\u76EE\u6807\u5747\u65E0\u53D8\u66F4\uFF0C\u65E0\u9700\u90E8\u7F72");
474
+ return;
475
+ }
401
476
  await task2("1. Link \u9879\u76EE", async () => {
402
- const linkTasks = availableTargets.map((target) => createLinkTask(config, target));
477
+ const linkTasks = finalTargets.map((target) => createLinkTask(config, target));
403
478
  await task2.group((task3) => linkTasks.map((t) => task3(t.name, t.fn)));
404
479
  });
405
480
  await task2("2. \u6784\u5EFA\u9879\u76EE", async () => {
406
- const buildTasks = availableTargets.filter(isNeedVercelBuild).map((target) => createBuildTask(config, target));
481
+ const buildTasks = finalTargets.filter(isNeedVercelBuild).map((target) => createBuildTask(config, target));
407
482
  if (buildTasks.length === 0) {
408
- consola9.warn("\u6CA1\u6709\u9700\u8981\u6267\u884C build \u7684\u76EE\u6807");
483
+ consola10.warn("\u6CA1\u6709\u9700\u8981\u6267\u884C build \u7684\u76EE\u6807");
409
484
  return;
410
485
  }
411
486
  await task2.group((task3) => buildTasks.map((t) => task3(t.name, t.fn)));
@@ -415,11 +490,11 @@ async function executeDeploymentWorkflow(config) {
415
490
  await executeSequential("AfterBuild", afterBuildTasks);
416
491
  });
417
492
  await task2("4. \u6267\u884C\u7528\u6237\u547D\u4EE4\u4E0E\u6587\u4EF6\u590D\u5236", async () => {
418
- const targetTasks = availableTargets.map((target) => ({
493
+ const targetTasks = finalTargets.map((target) => ({
419
494
  name: `\u5904\u7406\u76EE\u6807: ${target.targetCWD}`,
420
495
  fn: async () => {
421
496
  if (!isDeployTargetWithUserCommands(target)) {
422
- consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u5C5E\u4E8E userCommands \u7C7B\u578B`);
497
+ consola10.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u5C5E\u4E8E userCommands \u7C7B\u578B`);
423
498
  return;
424
499
  }
425
500
  const userCommandTasks = createUserCommandTasks(target);
@@ -428,14 +503,14 @@ async function executeDeploymentWorkflow(config) {
428
503
  const copyDistTasks = createCopyDistTasks(target);
429
504
  await executeSequential(`CopyDist: ${target.targetCWD}`, copyDistTasks);
430
505
  } else {
431
- consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u9700\u8981\u590D\u5236\u6587\u4EF6`);
506
+ consola10.warn(`\u76EE\u6807 ${target.targetCWD} \u4E0D\u9700\u8981\u590D\u5236\u6587\u4EF6`);
432
507
  }
433
508
  }
434
509
  }));
435
510
  await task2.group((task3) => targetTasks.map((t) => task3(t.name, t.fn)));
436
511
  });
437
512
  await task2("5. \u90E8\u7F72\u4E0E\u8BBE\u7F6E\u522B\u540D", async () => {
438
- const deployAliasTasks = availableTargets.map((target) => ({
513
+ const deployAliasTasks = finalTargets.map((target) => ({
439
514
  name: `\u90E8\u7F72\u4E0E\u522B\u540D: ${target.targetCWD}`,
440
515
  fn: async () => {
441
516
  const deployTask = createDeployTask(config, target);
@@ -445,37 +520,40 @@ async function executeDeploymentWorkflow(config) {
445
520
  const aliasTasks = target.url.map((userUrl) => createAliasTask(config, vercelUrl, userUrl));
446
521
  await task2.group((task3) => aliasTasks.map((t) => task3(t.name, t.fn)));
447
522
  } else {
448
- consola9.warn(`\u76EE\u6807 ${target.targetCWD} \u6CA1\u6709\u914D\u7F6E\u522B\u540D`);
523
+ consola10.warn(`\u76EE\u6807 ${target.targetCWD} \u6CA1\u6709\u914D\u7F6E\u522B\u540D`);
449
524
  }
450
525
  }
451
526
  }));
452
527
  await task2.group((task3) => deployAliasTasks.map((t) => task3(t.name, t.fn)));
453
528
  });
454
529
  });
455
- consola9.success("\u{1F389} Vercel \u90E8\u7F72\u5DE5\u4F5C\u6D41\u5B8C\u6210\uFF01");
530
+ consola10.success("\u{1F389} Vercel \u90E8\u7F72\u5DE5\u4F5C\u6D41\u5B8C\u6210\uFF01");
456
531
  }
457
532
 
458
533
  // src/commands/deploy.ts
459
534
  import { Command } from "commander";
460
- import { consola as consola10 } from "consola";
535
+ import { consola as consola11 } from "consola";
461
536
  import { config as dotenvxConfig2 } from "@dotenvx/dotenvx";
462
537
  function createDeployCommand() {
463
538
  const command = new Command("deploy");
464
- 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) => {
539
+ 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").option("--diff-base <ref>", "Git ref\uFF0C\u4E0E HEAD \u5BF9\u6BD4\u68C0\u6D4B\u53D8\u66F4\u6587\u4EF6\uFF0C\u4EC5\u90E8\u7F72\u6709\u53D8\u66F4\u7684\u76EE\u6807").option("--force-all", "\u5F3A\u5236\u90E8\u7F72\u6240\u6709\u76EE\u6807\uFF0C\u5FFD\u7565 watchPaths \u8FC7\u6EE4\uFF08\u4F18\u5148\u7EA7\u9AD8\u4E8E --diff-base\uFF09").action(async (options) => {
465
540
  try {
466
541
  if (options?.envPath) {
467
542
  process.env.VERCEL_DEPLOY_TOOL_ENV_PATH = options.envPath;
468
543
  dotenvxConfig2({ path: options.envPath });
469
- consola10.info(`\u5DF2\u4ECE --env-path \u52A0\u8F7D\u73AF\u5883\u53D8\u91CF: ${options.envPath}`);
544
+ consola11.info(`\u5DF2\u4ECE --env-path \u52A0\u8F7D\u73AF\u5883\u53D8\u91CF: ${options.envPath}`);
470
545
  }
471
- consola10.start("\u5F00\u59CB\u52A0\u8F7D\u914D\u7F6E...");
546
+ consola11.start("\u5F00\u59CB\u52A0\u8F7D\u914D\u7F6E...");
472
547
  const config = await loadConfig();
473
- consola10.start("\u5F00\u59CB\u6267\u884C\u90E8\u7F72\u5DE5\u4F5C\u6D41...");
474
- await executeDeploymentWorkflow(config);
475
- consola10.success("\u90E8\u7F72\u5B8C\u6210\uFF01");
548
+ consola11.start("\u5F00\u59CB\u6267\u884C\u90E8\u7F72\u5DE5\u4F5C\u6D41...");
549
+ await executeDeploymentWorkflow(config, {
550
+ diffBase: options?.diffBase,
551
+ forceAll: options?.forceAll
552
+ });
553
+ consola11.success("\u90E8\u7F72\u5B8C\u6210\uFF01");
476
554
  } catch (error) {
477
- consola10.error("\u90E8\u7F72\u5931\u8D25:");
478
- consola10.error(error);
555
+ consola11.error("\u90E8\u7F72\u5931\u8D25:");
556
+ consola11.error(error);
479
557
  process.exit(1);
480
558
  }
481
559
  });
@@ -487,7 +565,7 @@ import { Command as Command2 } from "commander";
487
565
  import { readFileSync, writeFileSync, existsSync } from "fs";
488
566
  import { join, dirname } from "path";
489
567
  import { fileURLToPath } from "url";
490
- import { consola as consola11 } from "consola";
568
+ import { consola as consola12 } from "consola";
491
569
  var __filename2 = fileURLToPath(import.meta.url);
492
570
  var __dirname2 = dirname(__filename2);
493
571
  function createInitCommand() {
@@ -497,19 +575,19 @@ function createInitCommand() {
497
575
  const configFile = "vercel-deploy-tool.config.ts";
498
576
  const targetPath = join(cwd, configFile);
499
577
  if (existsSync(targetPath) && !options.force) {
500
- consola11.warn(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728: ${configFile}`);
501
- consola11.info("\u4F7F\u7528 --force \u9009\u9879\u53EF\u4EE5\u8986\u76D6");
578
+ consola12.warn(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728: ${configFile}`);
579
+ consola12.info("\u4F7F\u7528 --force \u9009\u9879\u53EF\u4EE5\u8986\u76D6");
502
580
  return;
503
581
  }
504
582
  const templatePath = join(__dirname2, "..", "templates", configFile);
505
583
  if (!existsSync(templatePath)) {
506
- consola11.error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${templatePath}`);
507
- consola11.error("\u8BF7\u786E\u4FDD @ruan-cat/vercel-deploy-tool \u5305\u5DF2\u6B63\u786E\u5B89\u88C5");
584
+ consola12.error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${templatePath}`);
585
+ consola12.error("\u8BF7\u786E\u4FDD @ruan-cat/vercel-deploy-tool \u5305\u5DF2\u6B63\u786E\u5B89\u88C5");
508
586
  process.exit(1);
509
587
  }
510
588
  const content = readFileSync(templatePath, "utf-8");
511
589
  writeFileSync(targetPath, content, "utf-8");
512
- consola11.success(`\u5DF2\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ${configFile}`);
590
+ consola12.success(`\u5DF2\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ${configFile}`);
513
591
  const pkgPath = join(cwd, "package.json");
514
592
  if (existsSync(pkgPath)) {
515
593
  try {
@@ -517,12 +595,12 @@ function createInitCommand() {
517
595
  if (!pkg.scripts) pkg.scripts = {};
518
596
  pkg.scripts["deploy-vercel"] = "vercel-deploy-tool deploy";
519
597
  writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
520
- consola11.success('\u5DF2\u6DFB\u52A0\u811A\u672C: "deploy-vercel"');
598
+ consola12.success('\u5DF2\u6DFB\u52A0\u811A\u672C: "deploy-vercel"');
521
599
  } catch (error) {
522
- consola11.warn("\u66F4\u65B0 package.json \u5931\u8D25:", error);
600
+ consola12.warn("\u66F4\u65B0 package.json \u5931\u8D25:", error);
523
601
  }
524
602
  }
525
- consola11.box(`\u{1F389} \u521D\u59CB\u5316\u5B8C\u6210\uFF01
603
+ consola12.box(`\u{1F389} \u521D\u59CB\u5316\u5B8C\u6210\uFF01
526
604
 
527
605
  \u521B\u5EFA\u7684\u6587\u4EF6:
528
606
  \u2022 ${configFile} - Vercel \u90E8\u7F72\u914D\u7F6E\u6587\u4EF6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruan-cat/vercel-deploy-tool",
3
- "version": "1.2.7",
3
+ "version": "1.4.0",
4
4
  "description": "阮喵喵自用的vercel部署工具,用于实现复杂项目的部署。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -56,26 +56,28 @@
56
56
  "!src/**/*.md"
57
57
  ],
58
58
  "dependencies": {
59
- "@dotenvx/dotenvx": "^1.54.1",
60
- "c12": "^3.3.3",
59
+ "@dotenvx/dotenvx": "^1.59.1",
60
+ "c12": "^3.3.4",
61
61
  "commander": "^13.1.0",
62
62
  "consola": "^3.4.2",
63
63
  "gradient-string": "^3.0.0",
64
- "lodash-es": "^4.17.23",
64
+ "lodash-es": "^4.18.1",
65
65
  "pathe": "^2.0.3",
66
+ "picomatch": "^4.0.4",
66
67
  "rimraf": "^6.1.3",
67
68
  "tasuku": "^2.3.0",
68
69
  "vercel": "^41.7.8",
69
- "@ruan-cat/utils": "^4.24.0"
70
+ "@ruan-cat/utils": "^4.25.0"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@types/gulp": "^4.0.18",
73
74
  "@types/lodash-es": "^4.17.12",
74
75
  "@types/node": "^22.19.15",
76
+ "@types/picomatch": "^4.0.3",
75
77
  "automd": "^0.4.3",
76
78
  "execa": "^9.6.1",
77
79
  "vitepress": "^1.6.4",
78
- "@ruan-cat/vitepress-preset-config": "^3.1.4"
80
+ "@ruan-cat/vitepress-preset-config": "^3.2.0"
79
81
  },
80
82
  "scripts": {
81
83
  "build": "tsup",
@@ -21,6 +21,8 @@ export function createDeployCommand(): Command {
21
21
  command
22
22
  .description("部署项目到 Vercel")
23
23
  .option("--env-path <path>", "指定 dotenv 文件路径,用于覆盖默认环境变量")
24
+ .option("--diff-base <ref>", "Git ref,与 HEAD 对比检测变更文件,仅部署有变更的目标")
25
+ .option("--force-all", "强制部署所有目标,忽略 watchPaths 过滤(优先级高于 --diff-base)")
24
26
  .action(async (options) => {
25
27
  try {
26
28
  // 允许部署时显式指定 env 文件
@@ -36,7 +38,10 @@ export function createDeployCommand(): Command {
36
38
 
37
39
  consola.start("开始执行部署工作流...");
38
40
 
39
- await executeDeploymentWorkflow(config);
41
+ await executeDeploymentWorkflow(config, {
42
+ diffBase: options?.diffBase,
43
+ forceAll: options?.forceAll,
44
+ });
40
45
 
41
46
  consola.success("部署完成!");
42
47
  } catch (error) {
@@ -27,6 +27,18 @@ export interface DeployTargetBase {
27
27
  * @default true
28
28
  */
29
29
  isNeedVercelBuild?: boolean;
30
+
31
+ /**
32
+ * 监控路径(glob 模式)
33
+ * @description
34
+ * 配置后,部署前会通过 git diff 检测这些路径是否有变更。
35
+ * 仅在有变更时才部署该目标。未配置则始终部署(向后兼容)。
36
+ *
37
+ * 路径相对于 monorepo 根目录,使用 glob 语法。
38
+ * @example ["packages/utils/**"]
39
+ * @example ["packages/utils/src/docs/**", "packages/utils/src/.vitepress/**"]
40
+ */
41
+ watchPaths?: string[];
30
42
  }
31
43
 
32
44
  /**