vite-plugin-deploy-oss 1.2.3 → 3.0.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 +16 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +268 -115
- package/package.json +16 -14
- package/dist/index.d.mts +0 -23
- package/dist/index.mjs +0 -199
package/README.md
CHANGED
|
@@ -24,15 +24,31 @@ export default {
|
|
|
24
24
|
plugins: [
|
|
25
25
|
// 在最后一个插件中使用
|
|
26
26
|
vitePluginDeployOss({
|
|
27
|
+
// 建议按环境变量开关上传,避免本地/CI误上传
|
|
28
|
+
open: process.env.DEPLOY_OSS === '1',
|
|
29
|
+
// 终端实时动效进度面板(默认 true)
|
|
30
|
+
fancy: true,
|
|
31
|
+
|
|
27
32
|
accessKeyId: '***',
|
|
28
33
|
accessKeySecret: '***',
|
|
29
34
|
bucket: '***',
|
|
30
35
|
region: '***',
|
|
31
36
|
uploadDir: `H5/zz/test`,
|
|
32
37
|
skip: ['**/index.html'],
|
|
38
|
+
|
|
39
|
+
// 默认 true:有上传失败时抛错并让构建失败
|
|
40
|
+
failOnError: true,
|
|
41
|
+
|
|
33
42
|
// 修改打包后的资源路径
|
|
34
43
|
configBase: `https://oss.eventnet.cn/H5/zz/test/`,
|
|
35
44
|
}),
|
|
36
45
|
],
|
|
37
46
|
}
|
|
38
47
|
```
|
|
48
|
+
|
|
49
|
+
## 说明
|
|
50
|
+
|
|
51
|
+
- 当前版本仅支持 ESM(`import`),不再提供 CommonJS(`require`)入口。
|
|
52
|
+
- `open` 默认 `true`,建议通过环境变量控制开关(例如 `DEPLOY_OSS=1` 时再上传)。
|
|
53
|
+
- `fancy` 默认 `true`,TTY 终端下会显示实时动效进度(速度、预计剩余、并发、当前文件)。
|
|
54
|
+
- `failOnError` 默认 `true`,上传有失败会抛错,适合 CI 场景保证发布质量。
|
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,12 @@ interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'a
|
|
|
14
14
|
autoDelete?: boolean;
|
|
15
15
|
skip?: string | string[];
|
|
16
16
|
open?: boolean;
|
|
17
|
+
fancy?: boolean;
|
|
17
18
|
noCache?: boolean;
|
|
19
|
+
failOnError?: boolean;
|
|
18
20
|
concurrency?: number;
|
|
19
21
|
retryTimes?: number;
|
|
22
|
+
multipartThreshold?: number;
|
|
20
23
|
}
|
|
21
24
|
declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
|
|
22
25
|
|
package/dist/index.js
CHANGED
|
@@ -1,46 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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`;
|
|
11
30
|
};
|
|
12
|
-
var
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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));
|
|
17
43
|
}
|
|
18
|
-
|
|
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}`;
|
|
19
49
|
};
|
|
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
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
default: () => vitePluginDeployOss
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(index_exports);
|
|
36
|
-
var import_ali_oss = __toESM(require("ali-oss"));
|
|
37
|
-
var import_chalk = __toESM(require("chalk"));
|
|
38
|
-
var import_delete_empty = __toESM(require("delete-empty"));
|
|
39
|
-
var import_glob = require("glob");
|
|
40
|
-
var import_node_fs = require("fs");
|
|
41
|
-
var import_node_path = require("path");
|
|
42
|
-
var import_ora = __toESM(require("ora"));
|
|
43
|
-
var import_vite = require("vite");
|
|
44
50
|
function vitePluginDeployOss(option) {
|
|
45
51
|
const {
|
|
46
52
|
accessKeyId,
|
|
@@ -55,17 +61,23 @@ function vitePluginDeployOss(option) {
|
|
|
55
61
|
autoDelete = false,
|
|
56
62
|
alias,
|
|
57
63
|
open = true,
|
|
64
|
+
fancy = true,
|
|
58
65
|
noCache = false,
|
|
66
|
+
failOnError = true,
|
|
59
67
|
concurrency = 5,
|
|
60
68
|
retryTimes = 3,
|
|
69
|
+
multipartThreshold = 10 * 1024 * 1024,
|
|
61
70
|
...props
|
|
62
71
|
} = option || {};
|
|
63
72
|
let buildFailed = false;
|
|
64
73
|
let upload = false;
|
|
65
|
-
let outDir = "";
|
|
66
|
-
|
|
67
|
-
process.stdout?.
|
|
68
|
-
|
|
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
|
+
};
|
|
69
81
|
const validateOptions = () => {
|
|
70
82
|
const errors = [];
|
|
71
83
|
if (!accessKeyId) errors.push("accessKeyId is required");
|
|
@@ -73,79 +85,185 @@ function vitePluginDeployOss(option) {
|
|
|
73
85
|
if (!bucket) errors.push("bucket is required");
|
|
74
86
|
if (!region) errors.push("region is required");
|
|
75
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");
|
|
76
92
|
return errors;
|
|
77
93
|
};
|
|
78
|
-
const uploadFileWithRetry = async (client,
|
|
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
|
+
};
|
|
79
102
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
80
103
|
try {
|
|
81
|
-
const result = await client.
|
|
104
|
+
const result = shouldUseMultipart ? await client.multipartUpload(task.name, task.filePath, {
|
|
82
105
|
timeout: 6e5,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
}
|
|
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
|
|
91
112
|
});
|
|
92
113
|
if (result.res.status === 200) {
|
|
93
|
-
const url = alias ? alias + name : result.url;
|
|
94
114
|
if (autoDelete) {
|
|
95
115
|
try {
|
|
96
|
-
(
|
|
116
|
+
await unlink(task.filePath);
|
|
97
117
|
} catch (error) {
|
|
98
|
-
console.warn(`${
|
|
118
|
+
console.warn(`${chalk.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${task.filePath}`);
|
|
99
119
|
}
|
|
100
120
|
}
|
|
101
|
-
return { success: true, file: filePath };
|
|
121
|
+
return { success: true, file: task.filePath, name: task.name, size: task.size, retries: attempt - 1 };
|
|
102
122
|
} else {
|
|
103
123
|
throw new Error(`Upload failed with status: ${result.res.status}`);
|
|
104
124
|
}
|
|
105
125
|
} catch (error) {
|
|
106
126
|
if (attempt === maxRetries) {
|
|
107
|
-
|
|
108
|
-
|
|
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
|
+
};
|
|
109
140
|
} else {
|
|
110
|
-
|
|
141
|
+
if (!silentLogs) {
|
|
142
|
+
console.log(`${chalk.yellow("\u26A0")} ${task.filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
|
|
143
|
+
}
|
|
111
144
|
await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
|
|
112
145
|
}
|
|
113
146
|
}
|
|
114
147
|
}
|
|
115
|
-
return {
|
|
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
|
+
};
|
|
116
156
|
};
|
|
117
|
-
const uploadFilesInBatches = async (client, files,
|
|
157
|
+
const uploadFilesInBatches = async (client, files, windowSize = concurrency) => {
|
|
118
158
|
const results = [];
|
|
119
159
|
const totalFiles = files.length;
|
|
160
|
+
const tasks = [];
|
|
120
161
|
let completed = 0;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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;
|
|
130
227
|
};
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const
|
|
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);
|
|
138
238
|
completed++;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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})`);
|
|
144
266
|
}
|
|
145
|
-
const width = 30;
|
|
146
|
-
const bar = import_chalk.default.green("\u2588".repeat(width));
|
|
147
|
-
spinner.succeed(`\u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210!
|
|
148
|
-
${bar} 100% (${totalFiles}/${totalFiles})`);
|
|
149
267
|
return results;
|
|
150
268
|
};
|
|
151
269
|
return {
|
|
@@ -157,74 +275,109 @@ ${bar} 100% (${totalFiles}/${totalFiles})`);
|
|
|
157
275
|
},
|
|
158
276
|
config(config) {
|
|
159
277
|
if (!open || buildFailed) return;
|
|
160
|
-
|
|
278
|
+
clearScreen();
|
|
161
279
|
const validationErrors = validateOptions();
|
|
162
280
|
if (validationErrors.length > 0) {
|
|
163
|
-
console.log(`${
|
|
281
|
+
console.log(`${chalk.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
|
|
164
282
|
${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
165
283
|
return;
|
|
166
284
|
}
|
|
167
285
|
upload = true;
|
|
168
286
|
config.base = configBase || config.base;
|
|
169
|
-
outDir = config.build?.outDir || "dist";
|
|
170
287
|
return config;
|
|
171
288
|
},
|
|
289
|
+
configResolved(config) {
|
|
290
|
+
resolvedConfig = config;
|
|
291
|
+
outDir = normalizePath(resolve(config.root, config.build.outDir));
|
|
292
|
+
},
|
|
172
293
|
closeBundle: {
|
|
173
294
|
sequential: true,
|
|
174
295
|
order: "post",
|
|
175
296
|
async handler() {
|
|
176
|
-
if (!open || !upload || buildFailed) return;
|
|
297
|
+
if (!open || !upload || buildFailed || !resolvedConfig) return;
|
|
177
298
|
const startTime = Date.now();
|
|
178
|
-
const client = new
|
|
179
|
-
const files =
|
|
299
|
+
const client = new oss({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
|
|
300
|
+
const files = globSync("**/*", {
|
|
301
|
+
cwd: outDir,
|
|
180
302
|
nodir: true,
|
|
181
303
|
ignore: Array.isArray(skip) ? skip : [skip]
|
|
182
|
-
});
|
|
304
|
+
}).map((file) => normalizePath(file));
|
|
183
305
|
if (files.length === 0) {
|
|
184
|
-
console.log(`${
|
|
306
|
+
console.log(`${chalk.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
|
|
185
307
|
return;
|
|
186
308
|
}
|
|
187
|
-
|
|
188
|
-
console.log(
|
|
309
|
+
clearScreen();
|
|
310
|
+
console.log(chalk.cyan(`
|
|
189
311
|
\u{1F680} OSS \u90E8\u7F72\u5F00\u59CB
|
|
190
312
|
`));
|
|
191
|
-
console.log(`${
|
|
192
|
-
console.log(`${
|
|
193
|
-
console.log(`${
|
|
194
|
-
console.log(`${
|
|
195
|
-
console.log(`${
|
|
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)}
|
|
196
319
|
`);
|
|
197
320
|
try {
|
|
198
321
|
const results = await uploadFilesInBatches(client, files, concurrency);
|
|
199
322
|
const successCount = results.filter((r) => r.success).length;
|
|
200
323
|
const failedCount = results.length - successCount;
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
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");
|
|
204
331
|
if (failedCount === 0) {
|
|
205
|
-
console.log(`${
|
|
332
|
+
console.log(`${chalk.green("\u{1F389} \u90E8\u7F72\u6210\u529F!")}`);
|
|
206
333
|
} else {
|
|
207
|
-
console.log(`${
|
|
334
|
+
console.log(`${chalk.yellow("\u26A0 \u90E8\u7F72\u5B8C\u6210\u4F46\u5B58\u5728\u9519\u8BEF")}`);
|
|
208
335
|
}
|
|
209
336
|
console.log(`
|
|
210
|
-
${
|
|
211
|
-
console.log(` ${
|
|
337
|
+
${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
338
|
+
console.log(` ${chalk.green("\u2714")} \u6210\u529F: ${chalk.bold(successCount)}`);
|
|
212
339
|
if (failedCount > 0) {
|
|
213
|
-
console.log(` ${
|
|
340
|
+
console.log(` ${chalk.red("\u2717")} \u5931\u8D25: ${chalk.bold(failedCount)}`);
|
|
214
341
|
}
|
|
215
|
-
console.log(` ${
|
|
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`);
|
|
216
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
|
+
}
|
|
217
361
|
try {
|
|
218
|
-
|
|
362
|
+
await deleteEmpty(resolve(outDir));
|
|
219
363
|
} catch (error) {
|
|
220
|
-
console.warn(`${
|
|
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`);
|
|
221
368
|
}
|
|
222
369
|
} catch (error) {
|
|
223
370
|
console.log(`
|
|
224
|
-
${
|
|
371
|
+
${chalk.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
|
|
225
372
|
`);
|
|
373
|
+
if (failOnError) {
|
|
374
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
375
|
+
}
|
|
226
376
|
}
|
|
227
377
|
}
|
|
228
378
|
}
|
|
229
379
|
};
|
|
230
380
|
}
|
|
381
|
+
export {
|
|
382
|
+
vitePluginDeployOss as default
|
|
383
|
+
};
|
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-deploy-oss",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
|
-
"module": "./dist/index.mjs",
|
|
6
5
|
"types": "./dist/index.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/yulin96/vite-plugin-deploy-oss",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/yulin96/vite-plugin-deploy-oss"
|
|
10
|
+
"url": "git+https://github.com/yulin96/vite-plugin-deploy-oss.git"
|
|
11
11
|
},
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/yulin96/vite-plugin-deploy-oss/issues"
|
|
14
14
|
},
|
|
15
15
|
"exports": {
|
|
16
16
|
".": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
@@ -31,25 +31,27 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"description": "将dist目录下的文件上传到阿里云oss",
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@types/
|
|
35
|
-
"
|
|
36
|
-
"
|
|
34
|
+
"@types/ali-oss": "^6.23.3",
|
|
35
|
+
"@types/delete-empty": "^3.0.5",
|
|
36
|
+
"@types/node": "^22.19.11",
|
|
37
|
+
"tsup": "^8.5.1",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
37
39
|
},
|
|
38
40
|
"peerDependencies": {
|
|
39
41
|
"vite": "^6.0.3 || ^7"
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
42
|
-
"@types/ali-oss": "^6.16.11",
|
|
43
|
-
"@types/delete-empty": "^3.0.5",
|
|
44
44
|
"ali-oss": "^6.23.0",
|
|
45
|
-
"chalk": "^5.
|
|
45
|
+
"chalk": "^5.6.2",
|
|
46
46
|
"delete-empty": "^3.0.0",
|
|
47
|
-
"glob": "^13.0.
|
|
48
|
-
"ora": "^9.
|
|
47
|
+
"glob": "^13.0.6",
|
|
48
|
+
"ora": "^9.3.0"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsup",
|
|
52
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
52
53
|
"pack": "pnpm run build && pnpm pack",
|
|
53
|
-
"build:test": "cd playground && vite build"
|
|
54
|
+
"build:test": "cd playground && vite build",
|
|
55
|
+
"build:test:deploy": "cd playground && vite build --mode deploy"
|
|
54
56
|
}
|
|
55
57
|
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,23 +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
|
-
noCache?: boolean;
|
|
18
|
-
concurrency?: number;
|
|
19
|
-
retryTimes?: number;
|
|
20
|
-
}
|
|
21
|
-
declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
|
|
22
|
-
|
|
23
|
-
export { vitePluginDeployOss as default, type vitePluginDeployOssOption };
|
package/dist/index.mjs
DELETED
|
@@ -1,199 +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 { unlinkSync } from "fs";
|
|
7
|
-
import { resolve } from "path";
|
|
8
|
-
import ora from "ora";
|
|
9
|
-
import { normalizePath } from "vite";
|
|
10
|
-
function vitePluginDeployOss(option) {
|
|
11
|
-
const {
|
|
12
|
-
accessKeyId,
|
|
13
|
-
accessKeySecret,
|
|
14
|
-
region,
|
|
15
|
-
bucket,
|
|
16
|
-
configBase,
|
|
17
|
-
skip = "**/index.html",
|
|
18
|
-
uploadDir,
|
|
19
|
-
overwrite = true,
|
|
20
|
-
secure = true,
|
|
21
|
-
autoDelete = false,
|
|
22
|
-
alias,
|
|
23
|
-
open = true,
|
|
24
|
-
noCache = false,
|
|
25
|
-
concurrency = 5,
|
|
26
|
-
retryTimes = 3,
|
|
27
|
-
...props
|
|
28
|
-
} = option || {};
|
|
29
|
-
let buildFailed = false;
|
|
30
|
-
let upload = false;
|
|
31
|
-
let outDir = "";
|
|
32
|
-
const maxListeners = Math.max(20, concurrency * 3);
|
|
33
|
-
process.stdout?.setMaxListeners?.(maxListeners);
|
|
34
|
-
process.stderr?.setMaxListeners?.(maxListeners);
|
|
35
|
-
const validateOptions = () => {
|
|
36
|
-
const errors = [];
|
|
37
|
-
if (!accessKeyId) errors.push("accessKeyId is required");
|
|
38
|
-
if (!accessKeySecret) errors.push("accessKeySecret is required");
|
|
39
|
-
if (!bucket) errors.push("bucket is required");
|
|
40
|
-
if (!region) errors.push("region is required");
|
|
41
|
-
if (!uploadDir) errors.push("uploadDir is required");
|
|
42
|
-
return errors;
|
|
43
|
-
};
|
|
44
|
-
const uploadFileWithRetry = async (client, name, filePath, maxRetries = retryTimes) => {
|
|
45
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
46
|
-
try {
|
|
47
|
-
const result = await client.put(name, filePath, {
|
|
48
|
-
timeout: 6e5,
|
|
49
|
-
headers: {
|
|
50
|
-
"x-oss-storage-class": "Standard",
|
|
51
|
-
"x-oss-object-acl": "default",
|
|
52
|
-
"Cache-Control": noCache ? "no-cache" : "public, max-age=86400, immutable",
|
|
53
|
-
...overwrite && {
|
|
54
|
-
"x-oss-forbid-overwrite": "false"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
if (result.res.status === 200) {
|
|
59
|
-
const url = alias ? alias + name : result.url;
|
|
60
|
-
if (autoDelete) {
|
|
61
|
-
try {
|
|
62
|
-
unlinkSync(filePath);
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.warn(`${chalk.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${filePath}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return { success: true, file: filePath };
|
|
68
|
-
} else {
|
|
69
|
-
throw new Error(`Upload failed with status: ${result.res.status}`);
|
|
70
|
-
}
|
|
71
|
-
} catch (error) {
|
|
72
|
-
if (attempt === maxRetries) {
|
|
73
|
-
console.log(`${chalk.red("\u2717")} ${filePath} => ${error instanceof Error ? error.message : String(error)}`);
|
|
74
|
-
return { success: false, file: filePath, error };
|
|
75
|
-
} else {
|
|
76
|
-
console.log(`${chalk.yellow("\u26A0")} ${filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
|
|
77
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return { success: false, file: filePath, error: new Error("Max retries exceeded") };
|
|
82
|
-
};
|
|
83
|
-
const uploadFilesInBatches = async (client, files, batchSize = concurrency) => {
|
|
84
|
-
const results = [];
|
|
85
|
-
const totalFiles = files.length;
|
|
86
|
-
let completed = 0;
|
|
87
|
-
const spinner = ora("\u51C6\u5907\u4E0A\u4F20...").start();
|
|
88
|
-
const updateSpinner = (currentFile) => {
|
|
89
|
-
const percentage = Math.round(completed / totalFiles * 100);
|
|
90
|
-
const width2 = 30;
|
|
91
|
-
const filled = Math.round(width2 * completed / totalFiles);
|
|
92
|
-
const empty = width2 - filled;
|
|
93
|
-
const bar2 = chalk.green("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(empty));
|
|
94
|
-
spinner.text = `\u6B63\u5728\u4E0A\u4F20: ${chalk.cyan(currentFile)}
|
|
95
|
-
${bar2} ${percentage}% (${completed}/${totalFiles})`;
|
|
96
|
-
};
|
|
97
|
-
for (let i = 0; i < files.length; i += batchSize) {
|
|
98
|
-
const batch = files.slice(i, i + batchSize);
|
|
99
|
-
const batchPromises = batch.map(async (file) => {
|
|
100
|
-
const filePath = normalizePath(file);
|
|
101
|
-
const name = filePath.replace(outDir, uploadDir).replace(/\/\//g, "/");
|
|
102
|
-
updateSpinner(name);
|
|
103
|
-
const result = await uploadFileWithRetry(client, name, filePath);
|
|
104
|
-
completed++;
|
|
105
|
-
updateSpinner(name);
|
|
106
|
-
return result;
|
|
107
|
-
});
|
|
108
|
-
const batchResults = await Promise.all(batchPromises);
|
|
109
|
-
results.push(...batchResults);
|
|
110
|
-
}
|
|
111
|
-
const width = 30;
|
|
112
|
-
const bar = chalk.green("\u2588".repeat(width));
|
|
113
|
-
spinner.succeed(`\u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210!
|
|
114
|
-
${bar} 100% (${totalFiles}/${totalFiles})`);
|
|
115
|
-
return results;
|
|
116
|
-
};
|
|
117
|
-
return {
|
|
118
|
-
name: "vite-plugin-deploy-oss",
|
|
119
|
-
apply: "build",
|
|
120
|
-
enforce: "post",
|
|
121
|
-
buildEnd(error) {
|
|
122
|
-
if (error) buildFailed = true;
|
|
123
|
-
},
|
|
124
|
-
config(config) {
|
|
125
|
-
if (!open || buildFailed) return;
|
|
126
|
-
process.stdout.write("\x1B[2J\x1B[0f");
|
|
127
|
-
const validationErrors = validateOptions();
|
|
128
|
-
if (validationErrors.length > 0) {
|
|
129
|
-
console.log(`${chalk.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
|
|
130
|
-
${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
upload = true;
|
|
134
|
-
config.base = configBase || config.base;
|
|
135
|
-
outDir = config.build?.outDir || "dist";
|
|
136
|
-
return config;
|
|
137
|
-
},
|
|
138
|
-
closeBundle: {
|
|
139
|
-
sequential: true,
|
|
140
|
-
order: "post",
|
|
141
|
-
async handler() {
|
|
142
|
-
if (!open || !upload || buildFailed) return;
|
|
143
|
-
const startTime = Date.now();
|
|
144
|
-
const client = new oss({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
|
|
145
|
-
const files = globSync(outDir + "/**/*", {
|
|
146
|
-
nodir: true,
|
|
147
|
-
ignore: Array.isArray(skip) ? skip : [skip]
|
|
148
|
-
});
|
|
149
|
-
if (files.length === 0) {
|
|
150
|
-
console.log(`${chalk.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
process.stdout.write("\x1B[2J\x1B[0f");
|
|
154
|
-
console.log(chalk.cyan(`
|
|
155
|
-
\u{1F680} OSS \u90E8\u7F72\u5F00\u59CB
|
|
156
|
-
`));
|
|
157
|
-
console.log(`${chalk.gray("Bucket:")} ${chalk.green(bucket)}`);
|
|
158
|
-
console.log(`${chalk.gray("Region:")} ${chalk.green(region)}`);
|
|
159
|
-
console.log(`${chalk.gray("Source:")} ${chalk.yellow(outDir)}`);
|
|
160
|
-
console.log(`${chalk.gray("Target:")} ${chalk.yellow(uploadDir)}`);
|
|
161
|
-
console.log(`${chalk.gray("Files:")} ${chalk.blue(files.length)}
|
|
162
|
-
`);
|
|
163
|
-
try {
|
|
164
|
-
const results = await uploadFilesInBatches(client, files, concurrency);
|
|
165
|
-
const successCount = results.filter((r) => r.success).length;
|
|
166
|
-
const failedCount = results.length - successCount;
|
|
167
|
-
const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
168
|
-
process.stdout.write("\x1B[2J\x1B[0f");
|
|
169
|
-
console.log("\n" + chalk.gray("\u2500".repeat(40)) + "\n");
|
|
170
|
-
if (failedCount === 0) {
|
|
171
|
-
console.log(`${chalk.green("\u{1F389} \u90E8\u7F72\u6210\u529F!")}`);
|
|
172
|
-
} else {
|
|
173
|
-
console.log(`${chalk.yellow("\u26A0 \u90E8\u7F72\u5B8C\u6210\u4F46\u5B58\u5728\u9519\u8BEF")}`);
|
|
174
|
-
}
|
|
175
|
-
console.log(`
|
|
176
|
-
${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
177
|
-
console.log(` ${chalk.green("\u2714")} \u6210\u529F: ${chalk.bold(successCount)}`);
|
|
178
|
-
if (failedCount > 0) {
|
|
179
|
-
console.log(` ${chalk.red("\u2717")} \u5931\u8D25: ${chalk.bold(failedCount)}`);
|
|
180
|
-
}
|
|
181
|
-
console.log(` ${chalk.blue("\u23F1")} \u8017\u65F6: ${chalk.bold(duration)}s`);
|
|
182
|
-
console.log("");
|
|
183
|
-
try {
|
|
184
|
-
deleteEmpty(resolve(outDir));
|
|
185
|
-
} catch (error) {
|
|
186
|
-
console.warn(`${chalk.yellow("\u26A0 \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25:")} ${error}`);
|
|
187
|
-
}
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.log(`
|
|
190
|
-
${chalk.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
|
|
191
|
-
`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
export {
|
|
198
|
-
vitePluginDeployOss as default
|
|
199
|
-
};
|