vite-plugin-deploy-oss 2.0.0 → 3.0.1
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 +1 -0
- package/dist/index.js +84 -91
- package/package.json +5 -14
- package/dist/index.d.mts +0 -26
- package/dist/index.mjs +0 -383
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,47 +1,37 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
1
|
// src/index.ts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
var
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
2
|
+
import oss from "ali-oss";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { globSync } from "glob";
|
|
5
|
+
import { readdir, rm, stat, unlink } from "fs/promises";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import { normalizePath } from "vite";
|
|
9
|
+
var GARBAGE_FILE_REGEX = /(?:Thumbs\.db|\.DS_Store)$/i;
|
|
10
|
+
var removeEmptyDirectories = async (rootDir) => {
|
|
11
|
+
const deletedDirectories = [];
|
|
12
|
+
const visit = async (dirPath) => {
|
|
13
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
14
|
+
let hasNonEmptyContent = false;
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const entryPath = resolve(dirPath, entry.name);
|
|
17
|
+
if (entry.isDirectory()) {
|
|
18
|
+
const removed = await visit(entryPath);
|
|
19
|
+
if (!removed) hasNonEmptyContent = true;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (!GARBAGE_FILE_REGEX.test(entry.name)) {
|
|
23
|
+
hasNonEmptyContent = true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (hasNonEmptyContent) return false;
|
|
27
|
+
await rm(dirPath, { recursive: true, force: true });
|
|
28
|
+
deletedDirectories.push(dirPath);
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
await visit(resolve(rootDir));
|
|
32
|
+
return deletedDirectories;
|
|
33
|
+
};
|
|
34
|
+
var normalizeObjectKey = (targetDir, relativeFilePath) => normalizePath(`${targetDir}/${relativeFilePath}`).replace(/\/{2,}/g, "/").replace(/^\/+/, "");
|
|
45
35
|
var formatBytes = (bytes) => {
|
|
46
36
|
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
47
37
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
@@ -73,12 +63,12 @@ var buildCapsuleBar = (ratio, width = 30) => {
|
|
|
73
63
|
const safeRatio = Math.max(0, Math.min(1, ratio));
|
|
74
64
|
if (width <= 0) return "";
|
|
75
65
|
if (safeRatio >= 1) {
|
|
76
|
-
return
|
|
66
|
+
return chalk.green("\u2588".repeat(width));
|
|
77
67
|
}
|
|
78
68
|
const pointerIndex = Math.min(width - 1, Math.floor(width * safeRatio));
|
|
79
|
-
const done = pointerIndex > 0 ?
|
|
80
|
-
const pointer =
|
|
81
|
-
const pending = pointerIndex < width - 1 ?
|
|
69
|
+
const done = pointerIndex > 0 ? chalk.green("\u2588".repeat(pointerIndex)) : "";
|
|
70
|
+
const pointer = chalk.cyanBright("\u25B8");
|
|
71
|
+
const pending = pointerIndex < width - 1 ? chalk.gray("\u2591".repeat(width - pointerIndex - 1)) : "";
|
|
82
72
|
return `${done}${pointer}${pending}`;
|
|
83
73
|
};
|
|
84
74
|
function vitePluginDeployOss(option) {
|
|
@@ -105,7 +95,7 @@ function vitePluginDeployOss(option) {
|
|
|
105
95
|
} = option || {};
|
|
106
96
|
let buildFailed = false;
|
|
107
97
|
let upload = false;
|
|
108
|
-
let outDir =
|
|
98
|
+
let outDir = normalizePath(resolve("dist"));
|
|
109
99
|
let resolvedConfig = null;
|
|
110
100
|
const useInteractiveOutput = fancy && Boolean(process.stdout?.isTTY) && Boolean(process.stderr?.isTTY) && !process.env.CI;
|
|
111
101
|
const clearScreen = () => {
|
|
@@ -147,9 +137,9 @@ function vitePluginDeployOss(option) {
|
|
|
147
137
|
if (result.res.status === 200) {
|
|
148
138
|
if (autoDelete) {
|
|
149
139
|
try {
|
|
150
|
-
await
|
|
140
|
+
await unlink(task.filePath);
|
|
151
141
|
} catch (error) {
|
|
152
|
-
console.warn(`${
|
|
142
|
+
console.warn(`${chalk.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${task.filePath}`);
|
|
153
143
|
}
|
|
154
144
|
}
|
|
155
145
|
return { success: true, file: task.filePath, name: task.name, size: task.size, retries: attempt - 1 };
|
|
@@ -160,7 +150,7 @@ function vitePluginDeployOss(option) {
|
|
|
160
150
|
if (attempt === maxRetries) {
|
|
161
151
|
if (!silentLogs) {
|
|
162
152
|
console.log(
|
|
163
|
-
`${
|
|
153
|
+
`${chalk.red("\u2717")} ${task.filePath} => ${error instanceof Error ? error.message : String(error)}`
|
|
164
154
|
);
|
|
165
155
|
}
|
|
166
156
|
return {
|
|
@@ -173,7 +163,7 @@ function vitePluginDeployOss(option) {
|
|
|
173
163
|
};
|
|
174
164
|
} else {
|
|
175
165
|
if (!silentLogs) {
|
|
176
|
-
console.log(`${
|
|
166
|
+
console.log(`${chalk.yellow("\u26A0")} ${task.filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
|
|
177
167
|
}
|
|
178
168
|
await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
|
|
179
169
|
}
|
|
@@ -198,10 +188,10 @@ function vitePluginDeployOss(option) {
|
|
|
198
188
|
let retries = 0;
|
|
199
189
|
const taskCandidates = await Promise.all(
|
|
200
190
|
files.map(async (relativeFilePath) => {
|
|
201
|
-
const filePath =
|
|
191
|
+
const filePath = normalizePath(resolve(outDir, relativeFilePath));
|
|
202
192
|
const name = normalizeObjectKey(uploadDir, relativeFilePath);
|
|
203
193
|
try {
|
|
204
|
-
const fileStats = await
|
|
194
|
+
const fileStats = await stat(filePath);
|
|
205
195
|
return { task: { filePath, name, size: fileStats.size } };
|
|
206
196
|
} catch (error) {
|
|
207
197
|
return { task: null, error, filePath, name };
|
|
@@ -229,7 +219,7 @@ function vitePluginDeployOss(option) {
|
|
|
229
219
|
const activeFiles = /* @__PURE__ */ new Set();
|
|
230
220
|
const safeWindowSize = Math.max(1, Math.min(windowSize, tasks.length || 1));
|
|
231
221
|
const silentLogs = Boolean(useInteractiveOutput);
|
|
232
|
-
const spinner = useInteractiveOutput ? (
|
|
222
|
+
const spinner = useInteractiveOutput ? ora({ text: "\u51C6\u5907\u4E0A\u4F20...", spinner: "dots12" }).start() : null;
|
|
233
223
|
const reportEvery = Math.max(1, Math.ceil(totalFiles / 10));
|
|
234
224
|
let lastReportedCompleted = -1;
|
|
235
225
|
const updateProgress = () => {
|
|
@@ -244,7 +234,7 @@ function vitePluginDeployOss(option) {
|
|
|
244
234
|
if (completed === lastReportedCompleted) return;
|
|
245
235
|
if (completed === totalFiles || completed % reportEvery === 0) {
|
|
246
236
|
console.log(
|
|
247
|
-
`${
|
|
237
|
+
`${chalk.gray("\u8FDB\u5EA6:")} ${completed}/${totalFiles} (${percentage}%) | ${chalk.gray("\u6570\u636E:")} ${formatBytes(uploadedBytes)}/${formatBytes(totalBytes)} | ${chalk.gray("\u901F\u5EA6:")} ${formatBytes(speed)}/s`
|
|
248
238
|
);
|
|
249
239
|
lastReportedCompleted = completed;
|
|
250
240
|
}
|
|
@@ -252,10 +242,10 @@ function vitePluginDeployOss(option) {
|
|
|
252
242
|
}
|
|
253
243
|
const bar = buildCapsuleBar(progressRatio);
|
|
254
244
|
const warnLine = retries > 0 || failed > 0 ? `
|
|
255
|
-
${
|
|
245
|
+
${chalk.yellow("\u91CD\u8BD5")}: ${retries} ${chalk.yellow("\u5931\u8D25")}: ${failed}` : "";
|
|
256
246
|
spinner.text = [
|
|
257
|
-
`${
|
|
258
|
-
`${bar} ${
|
|
247
|
+
`${chalk.cyan("\u6B63\u5728\u4E0A\u4F20:")} ${chalk.white(currentFile)}`,
|
|
248
|
+
`${bar} ${chalk.bold(`${percentage}%`)} ${chalk.gray(`(${completed}/${totalFiles})`)} ${chalk.gray("|")} ${chalk.blue(formatBytes(uploadedBytes))}/${chalk.blue(formatBytes(totalBytes))} ${chalk.gray("|")} ${chalk.magenta(`${formatBytes(speed)}/s`)} ${chalk.gray("|")} \u9884\u8BA1 ${chalk.yellow(formatDuration(etaSeconds))}`
|
|
259
249
|
].join("\n");
|
|
260
250
|
spinner.text += warnLine;
|
|
261
251
|
};
|
|
@@ -292,11 +282,11 @@ ${import_chalk.default.yellow("\u91CD\u8BD5")}: ${retries} ${import_chalk.defau
|
|
|
292
282
|
const successCount = results.filter((item) => item.success).length;
|
|
293
283
|
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
294
284
|
spinner.succeed(
|
|
295
|
-
`${
|
|
296
|
-
${buildCapsuleBar(1)} 100% (${totalFiles}/${totalFiles}) ${
|
|
285
|
+
`${chalk.green("\u4E0A\u4F20\u6210\u529F")} ${successCount} \u4E2A\u6587\u4EF6\u3002
|
|
286
|
+
${buildCapsuleBar(1)} 100% (${totalFiles}/${totalFiles}) ${chalk.gray("|")} \u901F\u5EA6 ${chalk.magenta(`${formatBytes(speed)}/s`)} ${chalk.gray("|")} \u8017\u65F6 ${chalk.yellow(formatDuration(elapsedSeconds))}`
|
|
297
287
|
);
|
|
298
288
|
} else {
|
|
299
|
-
console.log(`${
|
|
289
|
+
console.log(`${chalk.green("\u2714")} \u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210 (${totalFiles}/${totalFiles})`);
|
|
300
290
|
}
|
|
301
291
|
return results;
|
|
302
292
|
};
|
|
@@ -312,7 +302,7 @@ ${buildCapsuleBar(1)} 100% (${totalFiles}/${totalFiles}) ${import_chalk.default.
|
|
|
312
302
|
clearScreen();
|
|
313
303
|
const validationErrors = validateOptions();
|
|
314
304
|
if (validationErrors.length > 0) {
|
|
315
|
-
console.log(`${
|
|
305
|
+
console.log(`${chalk.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
|
|
316
306
|
${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
317
307
|
return;
|
|
318
308
|
}
|
|
@@ -322,7 +312,7 @@ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
|
322
312
|
},
|
|
323
313
|
configResolved(config) {
|
|
324
314
|
resolvedConfig = config;
|
|
325
|
-
outDir =
|
|
315
|
+
outDir = normalizePath(resolve(config.root, config.build.outDir));
|
|
326
316
|
},
|
|
327
317
|
closeBundle: {
|
|
328
318
|
sequential: true,
|
|
@@ -330,26 +320,26 @@ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
|
330
320
|
async handler() {
|
|
331
321
|
if (!open || !upload || buildFailed || !resolvedConfig) return;
|
|
332
322
|
const startTime = Date.now();
|
|
333
|
-
const client = new
|
|
334
|
-
const files =
|
|
323
|
+
const client = new oss({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
|
|
324
|
+
const files = globSync("**/*", {
|
|
335
325
|
cwd: outDir,
|
|
336
326
|
nodir: true,
|
|
337
327
|
ignore: Array.isArray(skip) ? skip : [skip]
|
|
338
|
-
}).map((file) =>
|
|
328
|
+
}).map((file) => normalizePath(file));
|
|
339
329
|
if (files.length === 0) {
|
|
340
|
-
console.log(`${
|
|
330
|
+
console.log(`${chalk.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
|
|
341
331
|
return;
|
|
342
332
|
}
|
|
343
333
|
clearScreen();
|
|
344
|
-
console.log(
|
|
334
|
+
console.log(chalk.cyan(`
|
|
345
335
|
\u{1F680} OSS \u90E8\u7F72\u5F00\u59CB
|
|
346
336
|
`));
|
|
347
|
-
console.log(`${
|
|
348
|
-
console.log(`${
|
|
349
|
-
console.log(`${
|
|
350
|
-
console.log(`${
|
|
351
|
-
if (alias) console.log(`${
|
|
352
|
-
console.log(`${
|
|
337
|
+
console.log(`${chalk.gray("Bucket:")} ${chalk.green(bucket)}`);
|
|
338
|
+
console.log(`${chalk.gray("Region:")} ${chalk.green(region)}`);
|
|
339
|
+
console.log(`${chalk.gray("Source:")} ${chalk.yellow(outDir)}`);
|
|
340
|
+
console.log(`${chalk.gray("Target:")} ${chalk.yellow(uploadDir)}`);
|
|
341
|
+
if (alias) console.log(`${chalk.gray("Alias:")} ${chalk.green(alias)}`);
|
|
342
|
+
console.log(`${chalk.gray("Files:")} ${chalk.blue(files.length)}
|
|
353
343
|
`);
|
|
354
344
|
try {
|
|
355
345
|
const results = await uploadFilesInBatches(client, files, concurrency);
|
|
@@ -361,48 +351,48 @@ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
|
361
351
|
const retryCount = results.reduce((sum, result) => sum + result.retries, 0);
|
|
362
352
|
const avgSpeed = durationSeconds > 0 ? uploadedBytes / durationSeconds : 0;
|
|
363
353
|
clearScreen();
|
|
364
|
-
console.log("\n" +
|
|
354
|
+
console.log("\n" + chalk.gray("\u2500".repeat(40)) + "\n");
|
|
365
355
|
if (failedCount === 0) {
|
|
366
|
-
console.log(`${
|
|
356
|
+
console.log(`${chalk.green("\u{1F389} \u90E8\u7F72\u6210\u529F!")}`);
|
|
367
357
|
} else {
|
|
368
|
-
console.log(`${
|
|
358
|
+
console.log(`${chalk.yellow("\u26A0 \u90E8\u7F72\u5B8C\u6210\u4F46\u5B58\u5728\u9519\u8BEF")}`);
|
|
369
359
|
}
|
|
370
360
|
console.log(`
|
|
371
|
-
${
|
|
372
|
-
console.log(` ${
|
|
361
|
+
${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
362
|
+
console.log(` ${chalk.green("\u2714")} \u6210\u529F: ${chalk.bold(successCount)}`);
|
|
373
363
|
if (failedCount > 0) {
|
|
374
|
-
console.log(` ${
|
|
364
|
+
console.log(` ${chalk.red("\u2717")} \u5931\u8D25: ${chalk.bold(failedCount)}`);
|
|
375
365
|
}
|
|
376
|
-
console.log(` ${
|
|
377
|
-
console.log(` ${
|
|
378
|
-
console.log(` ${
|
|
379
|
-
console.log(` ${
|
|
366
|
+
console.log(` ${chalk.cyan("\u21C4")} \u91CD\u8BD5: ${chalk.bold(retryCount)}`);
|
|
367
|
+
console.log(` ${chalk.blue("\u{1F4E6}")} \u6570\u636E: ${chalk.bold(formatBytes(uploadedBytes))}`);
|
|
368
|
+
console.log(` ${chalk.magenta("\u26A1")} \u5E73\u5747\u901F\u5EA6: ${chalk.bold(`${formatBytes(avgSpeed)}/s`)}`);
|
|
369
|
+
console.log(` ${chalk.blue("\u23F1")} \u8017\u65F6: ${chalk.bold(duration)}s`);
|
|
380
370
|
console.log("");
|
|
381
371
|
if (failedCount > 0) {
|
|
382
372
|
const failedItems = results.filter((result) => !result.success);
|
|
383
373
|
const previewCount = Math.min(5, failedItems.length);
|
|
384
|
-
console.log(
|
|
374
|
+
console.log(chalk.red("\u5931\u8D25\u660E\u7EC6:"));
|
|
385
375
|
for (let i = 0; i < previewCount; i++) {
|
|
386
376
|
const item = failedItems[i];
|
|
387
377
|
const reason = item.error?.message || "unknown error";
|
|
388
|
-
console.log(` ${
|
|
378
|
+
console.log(` ${chalk.red("\u2022")} ${item.name} => ${reason}`);
|
|
389
379
|
}
|
|
390
380
|
if (failedItems.length > previewCount) {
|
|
391
|
-
console.log(
|
|
381
|
+
console.log(chalk.gray(` ... \u8FD8\u6709 ${failedItems.length - previewCount} \u4E2A\u5931\u8D25\u6587\u4EF6`));
|
|
392
382
|
}
|
|
393
383
|
console.log("");
|
|
394
384
|
}
|
|
395
385
|
try {
|
|
396
|
-
await (
|
|
386
|
+
await removeEmptyDirectories(outDir);
|
|
397
387
|
} catch (error) {
|
|
398
|
-
console.warn(`${
|
|
388
|
+
console.warn(`${chalk.yellow("\u26A0 \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25:")} ${error}`);
|
|
399
389
|
}
|
|
400
390
|
if (failedCount > 0 && failOnError) {
|
|
401
391
|
throw new Error(`Failed to upload ${failedCount} of ${results.length} files`);
|
|
402
392
|
}
|
|
403
393
|
} catch (error) {
|
|
404
394
|
console.log(`
|
|
405
|
-
${
|
|
395
|
+
${chalk.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
|
|
406
396
|
`);
|
|
407
397
|
if (failOnError) {
|
|
408
398
|
throw error instanceof Error ? error : new Error(String(error));
|
|
@@ -412,3 +402,6 @@ ${import_chalk.default.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9
|
|
|
412
402
|
}
|
|
413
403
|
};
|
|
414
404
|
}
|
|
405
|
+
export {
|
|
406
|
+
vitePluginDeployOss as default
|
|
407
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-deploy-oss",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
|
-
"module": "./dist/index.mjs",
|
|
6
5
|
"types": "./dist/index.d.ts",
|
|
7
|
-
"type": "
|
|
6
|
+
"type": "module",
|
|
8
7
|
"homepage": "https://github.com/yulin96/vite-plugin-deploy-oss",
|
|
9
8
|
"repository": {
|
|
10
9
|
"type": "git",
|
|
@@ -15,14 +14,8 @@
|
|
|
15
14
|
},
|
|
16
15
|
"exports": {
|
|
17
16
|
".": {
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"default": "./dist/index.mjs"
|
|
21
|
-
},
|
|
22
|
-
"require": {
|
|
23
|
-
"types": "./dist/index.d.ts",
|
|
24
|
-
"default": "./dist/index.js"
|
|
25
|
-
}
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
26
19
|
}
|
|
27
20
|
},
|
|
28
21
|
"keywords": [
|
|
@@ -39,8 +32,7 @@
|
|
|
39
32
|
"description": "将dist目录下的文件上传到阿里云oss",
|
|
40
33
|
"devDependencies": {
|
|
41
34
|
"@types/ali-oss": "^6.23.3",
|
|
42
|
-
"@types/
|
|
43
|
-
"@types/node": "^22.19.11",
|
|
35
|
+
"@types/node": "^22.19.13",
|
|
44
36
|
"tsup": "^8.5.1",
|
|
45
37
|
"typescript": "^5.9.3"
|
|
46
38
|
},
|
|
@@ -50,7 +42,6 @@
|
|
|
50
42
|
"dependencies": {
|
|
51
43
|
"ali-oss": "^6.23.0",
|
|
52
44
|
"chalk": "^5.6.2",
|
|
53
|
-
"delete-empty": "^3.0.0",
|
|
54
45
|
"glob": "^13.0.6",
|
|
55
46
|
"ora": "^9.3.0"
|
|
56
47
|
},
|
package/dist/index.d.mts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import oss from 'ali-oss';
|
|
2
|
-
import { Plugin } from 'vite';
|
|
3
|
-
|
|
4
|
-
interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'accessKeySecret' | 'bucket' | 'region'> {
|
|
5
|
-
configBase?: string;
|
|
6
|
-
accessKeyId: string;
|
|
7
|
-
accessKeySecret: string;
|
|
8
|
-
region: string;
|
|
9
|
-
secure?: boolean;
|
|
10
|
-
bucket: string;
|
|
11
|
-
overwrite?: boolean;
|
|
12
|
-
uploadDir: string;
|
|
13
|
-
alias?: string;
|
|
14
|
-
autoDelete?: boolean;
|
|
15
|
-
skip?: string | string[];
|
|
16
|
-
open?: boolean;
|
|
17
|
-
fancy?: boolean;
|
|
18
|
-
noCache?: boolean;
|
|
19
|
-
failOnError?: boolean;
|
|
20
|
-
concurrency?: number;
|
|
21
|
-
retryTimes?: number;
|
|
22
|
-
multipartThreshold?: number;
|
|
23
|
-
}
|
|
24
|
-
declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
|
|
25
|
-
|
|
26
|
-
export { vitePluginDeployOss as default, type vitePluginDeployOssOption };
|
package/dist/index.mjs
DELETED
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import oss from "ali-oss";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import deleteEmpty from "delete-empty";
|
|
5
|
-
import { globSync } from "glob";
|
|
6
|
-
import { stat, unlink } from "fs/promises";
|
|
7
|
-
import { resolve } from "path";
|
|
8
|
-
import ora from "ora";
|
|
9
|
-
import { normalizePath } from "vite";
|
|
10
|
-
var normalizeObjectKey = (targetDir, relativeFilePath) => normalizePath(`${targetDir}/${relativeFilePath}`).replace(/\/{2,}/g, "/").replace(/^\/+/, "");
|
|
11
|
-
var formatBytes = (bytes) => {
|
|
12
|
-
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
13
|
-
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
14
|
-
let value = bytes;
|
|
15
|
-
let unitIndex = 0;
|
|
16
|
-
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
17
|
-
value /= 1024;
|
|
18
|
-
unitIndex++;
|
|
19
|
-
}
|
|
20
|
-
const digits = value >= 100 || unitIndex === 0 ? 0 : 1;
|
|
21
|
-
return `${value.toFixed(digits)} ${units[unitIndex]}`;
|
|
22
|
-
};
|
|
23
|
-
var formatDuration = (seconds) => {
|
|
24
|
-
if (!Number.isFinite(seconds) || seconds < 0) return "--";
|
|
25
|
-
const rounded = Math.round(seconds);
|
|
26
|
-
const mins = Math.floor(rounded / 60);
|
|
27
|
-
const secs = rounded % 60;
|
|
28
|
-
if (mins === 0) return `${secs}s`;
|
|
29
|
-
return `${mins}m${String(secs).padStart(2, "0")}s`;
|
|
30
|
-
};
|
|
31
|
-
var trimMiddle = (text, maxLength) => {
|
|
32
|
-
if (text.length <= maxLength) return text;
|
|
33
|
-
if (maxLength <= 10) return text.slice(0, maxLength);
|
|
34
|
-
const leftLength = Math.floor((maxLength - 3) / 2);
|
|
35
|
-
const rightLength = maxLength - 3 - leftLength;
|
|
36
|
-
return `${text.slice(0, leftLength)}...${text.slice(-rightLength)}`;
|
|
37
|
-
};
|
|
38
|
-
var buildCapsuleBar = (ratio, width = 30) => {
|
|
39
|
-
const safeRatio = Math.max(0, Math.min(1, ratio));
|
|
40
|
-
if (width <= 0) return "";
|
|
41
|
-
if (safeRatio >= 1) {
|
|
42
|
-
return chalk.green("\u2588".repeat(width));
|
|
43
|
-
}
|
|
44
|
-
const pointerIndex = Math.min(width - 1, Math.floor(width * safeRatio));
|
|
45
|
-
const done = pointerIndex > 0 ? chalk.green("\u2588".repeat(pointerIndex)) : "";
|
|
46
|
-
const pointer = chalk.cyanBright("\u25B8");
|
|
47
|
-
const pending = pointerIndex < width - 1 ? chalk.gray("\u2591".repeat(width - pointerIndex - 1)) : "";
|
|
48
|
-
return `${done}${pointer}${pending}`;
|
|
49
|
-
};
|
|
50
|
-
function vitePluginDeployOss(option) {
|
|
51
|
-
const {
|
|
52
|
-
accessKeyId,
|
|
53
|
-
accessKeySecret,
|
|
54
|
-
region,
|
|
55
|
-
bucket,
|
|
56
|
-
configBase,
|
|
57
|
-
skip = "**/index.html",
|
|
58
|
-
uploadDir,
|
|
59
|
-
overwrite = true,
|
|
60
|
-
secure = true,
|
|
61
|
-
autoDelete = false,
|
|
62
|
-
alias,
|
|
63
|
-
open = true,
|
|
64
|
-
fancy = true,
|
|
65
|
-
noCache = false,
|
|
66
|
-
failOnError = true,
|
|
67
|
-
concurrency = 5,
|
|
68
|
-
retryTimes = 3,
|
|
69
|
-
multipartThreshold = 10 * 1024 * 1024,
|
|
70
|
-
...props
|
|
71
|
-
} = option || {};
|
|
72
|
-
let buildFailed = false;
|
|
73
|
-
let upload = false;
|
|
74
|
-
let outDir = normalizePath(resolve("dist"));
|
|
75
|
-
let resolvedConfig = null;
|
|
76
|
-
const useInteractiveOutput = fancy && Boolean(process.stdout?.isTTY) && Boolean(process.stderr?.isTTY) && !process.env.CI;
|
|
77
|
-
const clearScreen = () => {
|
|
78
|
-
if (!useInteractiveOutput) return;
|
|
79
|
-
process.stdout.write("\x1B[2J\x1B[0f");
|
|
80
|
-
};
|
|
81
|
-
const validateOptions = () => {
|
|
82
|
-
const errors = [];
|
|
83
|
-
if (!accessKeyId) errors.push("accessKeyId is required");
|
|
84
|
-
if (!accessKeySecret) errors.push("accessKeySecret is required");
|
|
85
|
-
if (!bucket) errors.push("bucket is required");
|
|
86
|
-
if (!region) errors.push("region is required");
|
|
87
|
-
if (!uploadDir) errors.push("uploadDir is required");
|
|
88
|
-
if (!Number.isInteger(retryTimes) || retryTimes < 1) errors.push("retryTimes must be >= 1");
|
|
89
|
-
if (!Number.isInteger(concurrency) || concurrency < 1) errors.push("concurrency must be >= 1");
|
|
90
|
-
if (!Number.isFinite(multipartThreshold) || multipartThreshold <= 0)
|
|
91
|
-
errors.push("multipartThreshold must be > 0");
|
|
92
|
-
return errors;
|
|
93
|
-
};
|
|
94
|
-
const uploadFileWithRetry = async (client, task, silentLogs, maxRetries = retryTimes) => {
|
|
95
|
-
const shouldUseMultipart = task.size >= multipartThreshold;
|
|
96
|
-
const headers = {
|
|
97
|
-
"x-oss-storage-class": "Standard",
|
|
98
|
-
"x-oss-object-acl": "default",
|
|
99
|
-
"Cache-Control": noCache ? "no-cache" : "public, max-age=86400, immutable",
|
|
100
|
-
"x-oss-forbid-overwrite": overwrite ? "false" : "true"
|
|
101
|
-
};
|
|
102
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
103
|
-
try {
|
|
104
|
-
const result = shouldUseMultipart ? await client.multipartUpload(task.name, task.filePath, {
|
|
105
|
-
timeout: 6e5,
|
|
106
|
-
partSize: 1024 * 1024,
|
|
107
|
-
parallel: Math.max(1, Math.min(concurrency, 4)),
|
|
108
|
-
headers
|
|
109
|
-
}) : await client.put(task.name, task.filePath, {
|
|
110
|
-
timeout: 6e5,
|
|
111
|
-
headers
|
|
112
|
-
});
|
|
113
|
-
if (result.res.status === 200) {
|
|
114
|
-
if (autoDelete) {
|
|
115
|
-
try {
|
|
116
|
-
await unlink(task.filePath);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.warn(`${chalk.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${task.filePath}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return { success: true, file: task.filePath, name: task.name, size: task.size, retries: attempt - 1 };
|
|
122
|
-
} else {
|
|
123
|
-
throw new Error(`Upload failed with status: ${result.res.status}`);
|
|
124
|
-
}
|
|
125
|
-
} catch (error) {
|
|
126
|
-
if (attempt === maxRetries) {
|
|
127
|
-
if (!silentLogs) {
|
|
128
|
-
console.log(
|
|
129
|
-
`${chalk.red("\u2717")} ${task.filePath} => ${error instanceof Error ? error.message : String(error)}`
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
success: false,
|
|
134
|
-
file: task.filePath,
|
|
135
|
-
name: task.name,
|
|
136
|
-
size: task.size,
|
|
137
|
-
retries: attempt - 1,
|
|
138
|
-
error
|
|
139
|
-
};
|
|
140
|
-
} else {
|
|
141
|
-
if (!silentLogs) {
|
|
142
|
-
console.log(`${chalk.yellow("\u26A0")} ${task.filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
|
|
143
|
-
}
|
|
144
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
success: false,
|
|
150
|
-
file: task.filePath,
|
|
151
|
-
name: task.name,
|
|
152
|
-
size: task.size,
|
|
153
|
-
retries: maxRetries,
|
|
154
|
-
error: new Error("Max retries exceeded")
|
|
155
|
-
};
|
|
156
|
-
};
|
|
157
|
-
const uploadFilesInBatches = async (client, files, windowSize = concurrency) => {
|
|
158
|
-
const results = [];
|
|
159
|
-
const totalFiles = files.length;
|
|
160
|
-
const tasks = [];
|
|
161
|
-
let completed = 0;
|
|
162
|
-
let failed = 0;
|
|
163
|
-
let uploadedBytes = 0;
|
|
164
|
-
let retries = 0;
|
|
165
|
-
const taskCandidates = await Promise.all(
|
|
166
|
-
files.map(async (relativeFilePath) => {
|
|
167
|
-
const filePath = normalizePath(resolve(outDir, relativeFilePath));
|
|
168
|
-
const name = normalizeObjectKey(uploadDir, relativeFilePath);
|
|
169
|
-
try {
|
|
170
|
-
const fileStats = await stat(filePath);
|
|
171
|
-
return { task: { filePath, name, size: fileStats.size } };
|
|
172
|
-
} catch (error) {
|
|
173
|
-
return { task: null, error, filePath, name };
|
|
174
|
-
}
|
|
175
|
-
})
|
|
176
|
-
);
|
|
177
|
-
for (const candidate of taskCandidates) {
|
|
178
|
-
if (candidate.task) {
|
|
179
|
-
tasks.push(candidate.task);
|
|
180
|
-
} else {
|
|
181
|
-
failed++;
|
|
182
|
-
completed++;
|
|
183
|
-
results.push({
|
|
184
|
-
success: false,
|
|
185
|
-
file: candidate.filePath,
|
|
186
|
-
name: candidate.name,
|
|
187
|
-
size: 0,
|
|
188
|
-
retries: 0,
|
|
189
|
-
error: candidate.error
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const totalBytes = tasks.reduce((sum, task) => sum + task.size, 0);
|
|
194
|
-
const startAt = Date.now();
|
|
195
|
-
const activeFiles = /* @__PURE__ */ new Set();
|
|
196
|
-
const safeWindowSize = Math.max(1, Math.min(windowSize, tasks.length || 1));
|
|
197
|
-
const silentLogs = Boolean(useInteractiveOutput);
|
|
198
|
-
const spinner = useInteractiveOutput ? ora({ text: "\u51C6\u5907\u4E0A\u4F20...", spinner: "dots12" }).start() : null;
|
|
199
|
-
const reportEvery = Math.max(1, Math.ceil(totalFiles / 10));
|
|
200
|
-
let lastReportedCompleted = -1;
|
|
201
|
-
const updateProgress = () => {
|
|
202
|
-
const progressRatio = totalFiles > 0 ? completed / totalFiles : 1;
|
|
203
|
-
const percentage = Math.round(progressRatio * 100);
|
|
204
|
-
const elapsedSeconds = (Date.now() - startAt) / 1e3;
|
|
205
|
-
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
206
|
-
const etaSeconds = speed > 0 ? Math.max(0, (totalBytes - uploadedBytes) / speed) : 0;
|
|
207
|
-
const activeList = Array.from(activeFiles);
|
|
208
|
-
const currentFile = activeList.length > 0 ? trimMiddle(activeList[activeList.length - 1], 86) : "-";
|
|
209
|
-
if (!spinner) {
|
|
210
|
-
if (completed === lastReportedCompleted) return;
|
|
211
|
-
if (completed === totalFiles || completed % reportEvery === 0) {
|
|
212
|
-
console.log(
|
|
213
|
-
`${chalk.gray("\u8FDB\u5EA6:")} ${completed}/${totalFiles} (${percentage}%) | ${chalk.gray("\u6570\u636E:")} ${formatBytes(uploadedBytes)}/${formatBytes(totalBytes)} | ${chalk.gray("\u901F\u5EA6:")} ${formatBytes(speed)}/s`
|
|
214
|
-
);
|
|
215
|
-
lastReportedCompleted = completed;
|
|
216
|
-
}
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const bar = buildCapsuleBar(progressRatio);
|
|
220
|
-
const warnLine = retries > 0 || failed > 0 ? `
|
|
221
|
-
${chalk.yellow("\u91CD\u8BD5")}: ${retries} ${chalk.yellow("\u5931\u8D25")}: ${failed}` : "";
|
|
222
|
-
spinner.text = [
|
|
223
|
-
`${chalk.cyan("\u6B63\u5728\u4E0A\u4F20:")} ${chalk.white(currentFile)}`,
|
|
224
|
-
`${bar} ${chalk.bold(`${percentage}%`)} ${chalk.gray(`(${completed}/${totalFiles})`)} ${chalk.gray("|")} ${chalk.blue(formatBytes(uploadedBytes))}/${chalk.blue(formatBytes(totalBytes))} ${chalk.gray("|")} ${chalk.magenta(`${formatBytes(speed)}/s`)} ${chalk.gray("|")} \u9884\u8BA1 ${chalk.yellow(formatDuration(etaSeconds))}`
|
|
225
|
-
].join("\n");
|
|
226
|
-
spinner.text += warnLine;
|
|
227
|
-
};
|
|
228
|
-
const refreshTimer = spinner ? setInterval(updateProgress, 120) : null;
|
|
229
|
-
let currentIndex = 0;
|
|
230
|
-
const worker = async () => {
|
|
231
|
-
while (true) {
|
|
232
|
-
const index = currentIndex++;
|
|
233
|
-
if (index >= tasks.length) return;
|
|
234
|
-
const task = tasks[index];
|
|
235
|
-
activeFiles.add(task.name);
|
|
236
|
-
updateProgress();
|
|
237
|
-
const result = await uploadFileWithRetry(client, task, silentLogs);
|
|
238
|
-
completed++;
|
|
239
|
-
retries += result.retries;
|
|
240
|
-
if (result.success) {
|
|
241
|
-
uploadedBytes += result.size;
|
|
242
|
-
} else {
|
|
243
|
-
failed++;
|
|
244
|
-
}
|
|
245
|
-
results.push(result);
|
|
246
|
-
activeFiles.delete(task.name);
|
|
247
|
-
updateProgress();
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
updateProgress();
|
|
251
|
-
try {
|
|
252
|
-
await Promise.all(Array.from({ length: safeWindowSize }, () => worker()));
|
|
253
|
-
} finally {
|
|
254
|
-
if (refreshTimer) clearInterval(refreshTimer);
|
|
255
|
-
}
|
|
256
|
-
if (spinner) {
|
|
257
|
-
const elapsedSeconds = (Date.now() - startAt) / 1e3;
|
|
258
|
-
const successCount = results.filter((item) => item.success).length;
|
|
259
|
-
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
260
|
-
spinner.succeed(
|
|
261
|
-
`${chalk.green("\u4E0A\u4F20\u6210\u529F")} ${successCount} \u4E2A\u6587\u4EF6\u3002
|
|
262
|
-
${buildCapsuleBar(1)} 100% (${totalFiles}/${totalFiles}) ${chalk.gray("|")} \u901F\u5EA6 ${chalk.magenta(`${formatBytes(speed)}/s`)} ${chalk.gray("|")} \u8017\u65F6 ${chalk.yellow(formatDuration(elapsedSeconds))}`
|
|
263
|
-
);
|
|
264
|
-
} else {
|
|
265
|
-
console.log(`${chalk.green("\u2714")} \u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210 (${totalFiles}/${totalFiles})`);
|
|
266
|
-
}
|
|
267
|
-
return results;
|
|
268
|
-
};
|
|
269
|
-
return {
|
|
270
|
-
name: "vite-plugin-deploy-oss",
|
|
271
|
-
apply: "build",
|
|
272
|
-
enforce: "post",
|
|
273
|
-
buildEnd(error) {
|
|
274
|
-
if (error) buildFailed = true;
|
|
275
|
-
},
|
|
276
|
-
config(config) {
|
|
277
|
-
if (!open || buildFailed) return;
|
|
278
|
-
clearScreen();
|
|
279
|
-
const validationErrors = validateOptions();
|
|
280
|
-
if (validationErrors.length > 0) {
|
|
281
|
-
console.log(`${chalk.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
|
|
282
|
-
${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
upload = true;
|
|
286
|
-
config.base = configBase || config.base;
|
|
287
|
-
return config;
|
|
288
|
-
},
|
|
289
|
-
configResolved(config) {
|
|
290
|
-
resolvedConfig = config;
|
|
291
|
-
outDir = normalizePath(resolve(config.root, config.build.outDir));
|
|
292
|
-
},
|
|
293
|
-
closeBundle: {
|
|
294
|
-
sequential: true,
|
|
295
|
-
order: "post",
|
|
296
|
-
async handler() {
|
|
297
|
-
if (!open || !upload || buildFailed || !resolvedConfig) return;
|
|
298
|
-
const startTime = Date.now();
|
|
299
|
-
const client = new oss({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
|
|
300
|
-
const files = globSync("**/*", {
|
|
301
|
-
cwd: outDir,
|
|
302
|
-
nodir: true,
|
|
303
|
-
ignore: Array.isArray(skip) ? skip : [skip]
|
|
304
|
-
}).map((file) => normalizePath(file));
|
|
305
|
-
if (files.length === 0) {
|
|
306
|
-
console.log(`${chalk.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
clearScreen();
|
|
310
|
-
console.log(chalk.cyan(`
|
|
311
|
-
\u{1F680} OSS \u90E8\u7F72\u5F00\u59CB
|
|
312
|
-
`));
|
|
313
|
-
console.log(`${chalk.gray("Bucket:")} ${chalk.green(bucket)}`);
|
|
314
|
-
console.log(`${chalk.gray("Region:")} ${chalk.green(region)}`);
|
|
315
|
-
console.log(`${chalk.gray("Source:")} ${chalk.yellow(outDir)}`);
|
|
316
|
-
console.log(`${chalk.gray("Target:")} ${chalk.yellow(uploadDir)}`);
|
|
317
|
-
if (alias) console.log(`${chalk.gray("Alias:")} ${chalk.green(alias)}`);
|
|
318
|
-
console.log(`${chalk.gray("Files:")} ${chalk.blue(files.length)}
|
|
319
|
-
`);
|
|
320
|
-
try {
|
|
321
|
-
const results = await uploadFilesInBatches(client, files, concurrency);
|
|
322
|
-
const successCount = results.filter((r) => r.success).length;
|
|
323
|
-
const failedCount = results.length - successCount;
|
|
324
|
-
const durationSeconds = (Date.now() - startTime) / 1e3;
|
|
325
|
-
const duration = durationSeconds.toFixed(2);
|
|
326
|
-
const uploadedBytes = results.reduce((sum, result) => result.success ? sum + result.size : sum, 0);
|
|
327
|
-
const retryCount = results.reduce((sum, result) => sum + result.retries, 0);
|
|
328
|
-
const avgSpeed = durationSeconds > 0 ? uploadedBytes / durationSeconds : 0;
|
|
329
|
-
clearScreen();
|
|
330
|
-
console.log("\n" + chalk.gray("\u2500".repeat(40)) + "\n");
|
|
331
|
-
if (failedCount === 0) {
|
|
332
|
-
console.log(`${chalk.green("\u{1F389} \u90E8\u7F72\u6210\u529F!")}`);
|
|
333
|
-
} else {
|
|
334
|
-
console.log(`${chalk.yellow("\u26A0 \u90E8\u7F72\u5B8C\u6210\u4F46\u5B58\u5728\u9519\u8BEF")}`);
|
|
335
|
-
}
|
|
336
|
-
console.log(`
|
|
337
|
-
${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
338
|
-
console.log(` ${chalk.green("\u2714")} \u6210\u529F: ${chalk.bold(successCount)}`);
|
|
339
|
-
if (failedCount > 0) {
|
|
340
|
-
console.log(` ${chalk.red("\u2717")} \u5931\u8D25: ${chalk.bold(failedCount)}`);
|
|
341
|
-
}
|
|
342
|
-
console.log(` ${chalk.cyan("\u21C4")} \u91CD\u8BD5: ${chalk.bold(retryCount)}`);
|
|
343
|
-
console.log(` ${chalk.blue("\u{1F4E6}")} \u6570\u636E: ${chalk.bold(formatBytes(uploadedBytes))}`);
|
|
344
|
-
console.log(` ${chalk.magenta("\u26A1")} \u5E73\u5747\u901F\u5EA6: ${chalk.bold(`${formatBytes(avgSpeed)}/s`)}`);
|
|
345
|
-
console.log(` ${chalk.blue("\u23F1")} \u8017\u65F6: ${chalk.bold(duration)}s`);
|
|
346
|
-
console.log("");
|
|
347
|
-
if (failedCount > 0) {
|
|
348
|
-
const failedItems = results.filter((result) => !result.success);
|
|
349
|
-
const previewCount = Math.min(5, failedItems.length);
|
|
350
|
-
console.log(chalk.red("\u5931\u8D25\u660E\u7EC6:"));
|
|
351
|
-
for (let i = 0; i < previewCount; i++) {
|
|
352
|
-
const item = failedItems[i];
|
|
353
|
-
const reason = item.error?.message || "unknown error";
|
|
354
|
-
console.log(` ${chalk.red("\u2022")} ${item.name} => ${reason}`);
|
|
355
|
-
}
|
|
356
|
-
if (failedItems.length > previewCount) {
|
|
357
|
-
console.log(chalk.gray(` ... \u8FD8\u6709 ${failedItems.length - previewCount} \u4E2A\u5931\u8D25\u6587\u4EF6`));
|
|
358
|
-
}
|
|
359
|
-
console.log("");
|
|
360
|
-
}
|
|
361
|
-
try {
|
|
362
|
-
await deleteEmpty(resolve(outDir));
|
|
363
|
-
} catch (error) {
|
|
364
|
-
console.warn(`${chalk.yellow("\u26A0 \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25:")} ${error}`);
|
|
365
|
-
}
|
|
366
|
-
if (failedCount > 0 && failOnError) {
|
|
367
|
-
throw new Error(`Failed to upload ${failedCount} of ${results.length} files`);
|
|
368
|
-
}
|
|
369
|
-
} catch (error) {
|
|
370
|
-
console.log(`
|
|
371
|
-
${chalk.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
|
|
372
|
-
`);
|
|
373
|
-
if (failOnError) {
|
|
374
|
-
throw error instanceof Error ? error : new Error(String(error));
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
export {
|
|
382
|
-
vitePluginDeployOss as default
|
|
383
|
-
};
|