vite-plugin-deploy-oss 3.2.0 → 3.3.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 +2 -1
- package/dist/index.d.ts +31 -3
- package/dist/index.js +278 -150
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -67,7 +67,8 @@ export default {
|
|
|
67
67
|
{
|
|
68
68
|
"file": "assets/index-abc123.js",
|
|
69
69
|
"key": "H5/zz/test/assets/index-abc123.js",
|
|
70
|
-
"url": "https://oss.eventnet.cn/H5/zz/test/assets/index-abc123.js"
|
|
70
|
+
"url": "https://oss.eventnet.cn/H5/zz/test/assets/index-abc123.js",
|
|
71
|
+
"md5": "d41d8cd98f00b204e9800998ecf8427e"
|
|
71
72
|
}
|
|
72
73
|
]
|
|
73
74
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import oss from 'ali-oss';
|
|
2
1
|
import { Plugin } from 'vite';
|
|
2
|
+
import oss from 'ali-oss';
|
|
3
3
|
|
|
4
4
|
interface ManifestOption {
|
|
5
5
|
fileName?: string;
|
|
6
6
|
}
|
|
7
|
+
type ManifestConfig = boolean | ManifestOption | undefined;
|
|
7
8
|
interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'accessKeySecret' | 'bucket' | 'region'> {
|
|
8
9
|
configBase?: string;
|
|
9
10
|
accessKeyId: string;
|
|
@@ -23,8 +24,35 @@ interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'a
|
|
|
23
24
|
concurrency?: number;
|
|
24
25
|
retryTimes?: number;
|
|
25
26
|
multipartThreshold?: number;
|
|
26
|
-
manifest?:
|
|
27
|
+
manifest?: ManifestConfig;
|
|
28
|
+
}
|
|
29
|
+
interface UploadResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
file: string;
|
|
32
|
+
relativeFilePath: string;
|
|
33
|
+
name: string;
|
|
34
|
+
size: number;
|
|
35
|
+
retries: number;
|
|
36
|
+
error?: Error;
|
|
37
|
+
}
|
|
38
|
+
interface UploadTask {
|
|
39
|
+
filePath: string;
|
|
40
|
+
relativeFilePath: string;
|
|
41
|
+
name: string;
|
|
42
|
+
size: number;
|
|
43
|
+
cacheControl?: string;
|
|
27
44
|
}
|
|
45
|
+
interface ManifestFileItem {
|
|
46
|
+
file: string;
|
|
47
|
+
key: string;
|
|
48
|
+
url: string;
|
|
49
|
+
md5: string;
|
|
50
|
+
}
|
|
51
|
+
interface ManifestPayload {
|
|
52
|
+
version: number;
|
|
53
|
+
files: ManifestFileItem[];
|
|
54
|
+
}
|
|
55
|
+
|
|
28
56
|
declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
|
|
29
57
|
|
|
30
|
-
export { vitePluginDeployOss as default, type vitePluginDeployOssOption };
|
|
58
|
+
export { type ManifestConfig, type ManifestFileItem, type ManifestOption, type ManifestPayload, type UploadResult, type UploadTask, vitePluginDeployOss as default, type vitePluginDeployOssOption };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import oss from "ali-oss";
|
|
3
|
-
import
|
|
3
|
+
import chalk3 from "chalk";
|
|
4
|
+
import cliProgress from "cli-progress";
|
|
4
5
|
import { globSync } from "glob";
|
|
5
|
-
import { mkdir,
|
|
6
|
-
import { dirname, resolve } from "path";
|
|
7
|
-
import ora from "ora";
|
|
6
|
+
import { mkdir, stat, unlink, writeFile } from "fs/promises";
|
|
7
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
8
8
|
import { normalizePath } from "vite";
|
|
9
|
+
|
|
10
|
+
// src/utils/file.ts
|
|
11
|
+
import { createHash } from "crypto";
|
|
12
|
+
import { createReadStream } from "fs";
|
|
13
|
+
import { readdir, rm } from "fs/promises";
|
|
14
|
+
import { resolve } from "path";
|
|
9
15
|
var GARBAGE_FILE_REGEX = /(?:Thumbs\.db|\.DS_Store)$/i;
|
|
10
|
-
var
|
|
16
|
+
var getFileMd5 = (filePath) => {
|
|
17
|
+
return new Promise((resolvePromise, reject) => {
|
|
18
|
+
const hash = createHash("md5");
|
|
19
|
+
const stream = createReadStream(filePath);
|
|
20
|
+
stream.on("error", (err) => reject(err));
|
|
21
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
22
|
+
stream.on("end", () => resolvePromise(hash.digest("hex")));
|
|
23
|
+
});
|
|
24
|
+
};
|
|
11
25
|
var removeEmptyDirectories = async (rootDir) => {
|
|
12
26
|
const deletedDirectories = [];
|
|
13
27
|
const visit = async (dirPath) => {
|
|
@@ -32,9 +46,53 @@ var removeEmptyDirectories = async (rootDir) => {
|
|
|
32
46
|
await visit(resolve(rootDir));
|
|
33
47
|
return deletedDirectories;
|
|
34
48
|
};
|
|
35
|
-
|
|
49
|
+
|
|
50
|
+
// src/utils/path.ts
|
|
51
|
+
var DEFAULT_MANIFEST_FILE_NAME = "oss-manifest.json";
|
|
52
|
+
var normalizeSlash = (value) => value.replace(/\\/g, "/").trim();
|
|
53
|
+
var normalizePathSegments = (...values) => values.filter((value) => Boolean(value)).flatMap((value) => normalizeSlash(value).split("/")).filter(Boolean).join("/");
|
|
54
|
+
var splitUrlLikeBase = (value) => {
|
|
55
|
+
const normalized = normalizeSlash(value);
|
|
56
|
+
const protocolMatch = normalized.match(/^([a-zA-Z][a-zA-Z\d+.-]*:\/\/[^/]+)(.*)$/);
|
|
57
|
+
if (protocolMatch) {
|
|
58
|
+
return {
|
|
59
|
+
prefix: protocolMatch[1],
|
|
60
|
+
path: protocolMatch[2] || ""
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const protocolRelativeMatch = normalized.match(/^(\/\/[^/]+)(.*)$/);
|
|
64
|
+
if (protocolRelativeMatch) {
|
|
65
|
+
return {
|
|
66
|
+
prefix: protocolRelativeMatch[1],
|
|
67
|
+
path: protocolRelativeMatch[2] || ""
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (normalized.startsWith("/")) {
|
|
71
|
+
return {
|
|
72
|
+
prefix: "/",
|
|
73
|
+
path: normalized
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
prefix: "",
|
|
78
|
+
path: normalized
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
var normalizeUrlLikeBase = (base) => {
|
|
82
|
+
const { prefix, path } = splitUrlLikeBase(base);
|
|
83
|
+
const normalizedPath = normalizePathSegments(path);
|
|
84
|
+
if (!prefix) return normalizedPath;
|
|
85
|
+
if (!normalizedPath) return prefix;
|
|
86
|
+
if (prefix === "/") return `/${normalizedPath}`;
|
|
87
|
+
return `${prefix}/${normalizedPath}`;
|
|
88
|
+
};
|
|
89
|
+
var ensureTrailingSlash = (value) => {
|
|
90
|
+
if (!value || value.endsWith("/")) return value;
|
|
91
|
+
return `${value}/`;
|
|
92
|
+
};
|
|
93
|
+
var normalizeObjectKey = (targetDir, relativeFilePath) => normalizePathSegments(targetDir, relativeFilePath);
|
|
36
94
|
var normalizeManifestFileName = (fileName) => {
|
|
37
|
-
const normalized =
|
|
95
|
+
const normalized = normalizePathSegments(fileName || DEFAULT_MANIFEST_FILE_NAME);
|
|
38
96
|
return normalized || DEFAULT_MANIFEST_FILE_NAME;
|
|
39
97
|
};
|
|
40
98
|
var resolveManifestFileName = (manifest) => {
|
|
@@ -42,36 +100,16 @@ var resolveManifestFileName = (manifest) => {
|
|
|
42
100
|
if (manifest === true) return DEFAULT_MANIFEST_FILE_NAME;
|
|
43
101
|
return normalizeManifestFileName(manifest.fileName);
|
|
44
102
|
};
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
const protocolSeparatorIndex = normalized.indexOf("://");
|
|
48
|
-
if (protocolSeparatorIndex >= 0) {
|
|
49
|
-
const pathIndex = normalized.indexOf("/", protocolSeparatorIndex + 3);
|
|
50
|
-
if (pathIndex < 0) return normalized;
|
|
51
|
-
return `${normalized.slice(0, pathIndex)}${normalized.slice(pathIndex).replace(/\/{2,}/g, "/")}`;
|
|
52
|
-
}
|
|
53
|
-
if (normalized.startsWith("//")) {
|
|
54
|
-
const pathIndex = normalized.indexOf("/", 2);
|
|
55
|
-
if (pathIndex < 0) return normalized;
|
|
56
|
-
return `${normalized.slice(0, pathIndex)}${normalized.slice(pathIndex).replace(/\/{2,}/g, "/")}`;
|
|
57
|
-
}
|
|
58
|
-
return normalized.replace(/\/{2,}/g, "/");
|
|
59
|
-
};
|
|
60
|
-
var encodeUrlPath = (path) => encodeURI(path.replace(/^\/+/, ""));
|
|
61
|
-
var joinUrlPath = (base, path) => `${normalizeUrlBase(base).replace(/\/+$/, "")}/${encodeUrlPath(path)}`;
|
|
103
|
+
var encodeUrlPath = (path) => encodeURI(normalizePathSegments(path));
|
|
104
|
+
var joinUrlPath = (base, path) => `${normalizeUrlLikeBase(base).replace(/\/+$/, "")}/${encodeUrlPath(path)}`;
|
|
62
105
|
var resolveUploadedFileUrl = (relativeFilePath, objectKey, configBase, alias) => {
|
|
63
106
|
if (configBase) return joinUrlPath(configBase, relativeFilePath);
|
|
64
107
|
if (alias) return joinUrlPath(alias, objectKey);
|
|
65
108
|
return objectKey;
|
|
66
109
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
file: result.relativeFilePath,
|
|
71
|
-
key: result.name,
|
|
72
|
-
url: resolveUploadedFileUrl(result.relativeFilePath, result.name, configBase, alias)
|
|
73
|
-
}))
|
|
74
|
-
});
|
|
110
|
+
|
|
111
|
+
// src/utils/progress.ts
|
|
112
|
+
import chalk from "chalk";
|
|
75
113
|
var formatBytes = (bytes) => {
|
|
76
114
|
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
77
115
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
@@ -92,24 +130,84 @@ var formatDuration = (seconds) => {
|
|
|
92
130
|
if (mins === 0) return `${secs}s`;
|
|
93
131
|
return `${mins}m${String(secs).padStart(2, "0")}s`;
|
|
94
132
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
133
|
+
|
|
134
|
+
// src/utils/terminal.ts
|
|
135
|
+
import chalk2 from "chalk";
|
|
136
|
+
import cliTruncate from "cli-truncate";
|
|
137
|
+
import logSymbols from "log-symbols";
|
|
138
|
+
import stringWidth from "string-width";
|
|
139
|
+
var panelBorderColor = {
|
|
140
|
+
info: "cyan",
|
|
141
|
+
success: "green",
|
|
142
|
+
warning: "yellow",
|
|
143
|
+
danger: "red"
|
|
101
144
|
};
|
|
102
|
-
var
|
|
103
|
-
|
|
145
|
+
var getTerminalWidth = () => process.stdout?.columns || 100;
|
|
146
|
+
var getPanelInnerWidth = () => Math.max(46, Math.min(84, getTerminalWidth() - 4));
|
|
147
|
+
var padVisual = (text, width) => `${text}${" ".repeat(Math.max(0, width - stringWidth(text)))}`;
|
|
148
|
+
var fitVisual = (text, width) => {
|
|
104
149
|
if (width <= 0) return "";
|
|
105
|
-
|
|
106
|
-
|
|
150
|
+
return padVisual(cliTruncate(text, width, { position: "middle" }), width);
|
|
151
|
+
};
|
|
152
|
+
var truncateTerminalText = (text, reservedWidth = 26) => {
|
|
153
|
+
const maxWidth = Math.max(24, Math.min(88, getTerminalWidth() - reservedWidth));
|
|
154
|
+
return cliTruncate(text, maxWidth, { position: "middle" });
|
|
155
|
+
};
|
|
156
|
+
var renderPanel = (title, rows, tone = "info", footer) => {
|
|
157
|
+
const color = chalk2[panelBorderColor[tone]];
|
|
158
|
+
const innerWidth = getPanelInnerWidth();
|
|
159
|
+
const labelWidth = rows.length > 0 ? Math.max(...rows.map((row) => stringWidth(row.label))) : 0;
|
|
160
|
+
const contentLines = [chalk2.bold(cliTruncate(title, innerWidth, { position: "end" }))];
|
|
161
|
+
if (rows.length > 0) {
|
|
162
|
+
contentLines.push("");
|
|
163
|
+
for (const row of rows) {
|
|
164
|
+
const paddedLabel = padVisual(row.label, labelWidth);
|
|
165
|
+
const prefix = `${paddedLabel} `;
|
|
166
|
+
const availableValueWidth = Math.max(8, innerWidth - stringWidth(prefix));
|
|
167
|
+
contentLines.push(`${chalk2.gray(prefix)}${fitVisual(row.value, availableValueWidth)}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (footer) {
|
|
171
|
+
contentLines.push("");
|
|
172
|
+
contentLines.push(chalk2.gray(cliTruncate(footer, innerWidth, { position: "middle" })));
|
|
107
173
|
}
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
174
|
+
const top = color(`\u256D${"\u2500".repeat(innerWidth + 2)}\u256E`);
|
|
175
|
+
const bottom = color(`\u2570${"\u2500".repeat(innerWidth + 2)}\u256F`);
|
|
176
|
+
const body = contentLines.map((line) => `${color("\u2502")} ${fitVisual(line, innerWidth)} ${color("\u2502")}`).join("\n");
|
|
177
|
+
return `${top}
|
|
178
|
+
${body}
|
|
179
|
+
${bottom}`;
|
|
180
|
+
};
|
|
181
|
+
var renderInlineStats = (items) => items.filter(Boolean).join(chalk2.gray(" \xB7 "));
|
|
182
|
+
var getLogSymbol = (tone) => {
|
|
183
|
+
switch (tone) {
|
|
184
|
+
case "success":
|
|
185
|
+
return logSymbols.success;
|
|
186
|
+
case "warning":
|
|
187
|
+
return logSymbols.warning;
|
|
188
|
+
case "danger":
|
|
189
|
+
return logSymbols.error;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// src/index.ts
|
|
194
|
+
var createManifestPayload = async (results, configBase, alias) => {
|
|
195
|
+
const successfulResults = results.filter((result) => result.success);
|
|
196
|
+
const files = await Promise.all(
|
|
197
|
+
successfulResults.map(async (result) => {
|
|
198
|
+
const md5 = await getFileMd5(result.file);
|
|
199
|
+
return {
|
|
200
|
+
file: result.relativeFilePath,
|
|
201
|
+
key: result.name,
|
|
202
|
+
url: resolveUploadedFileUrl(result.relativeFilePath, result.name, configBase, alias),
|
|
203
|
+
md5
|
|
204
|
+
};
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
return {
|
|
208
|
+
version: Date.now(),
|
|
209
|
+
files
|
|
210
|
+
};
|
|
113
211
|
};
|
|
114
212
|
function vitePluginDeployOss(option) {
|
|
115
213
|
const {
|
|
@@ -134,12 +232,15 @@ function vitePluginDeployOss(option) {
|
|
|
134
232
|
manifest = false,
|
|
135
233
|
...props
|
|
136
234
|
} = option || {};
|
|
235
|
+
const normalizedUploadDir = normalizePathSegments(uploadDir);
|
|
236
|
+
const normalizedConfigBase = configBase ? ensureTrailingSlash(normalizeUrlLikeBase(configBase)) : void 0;
|
|
237
|
+
const normalizedAlias = alias ? normalizeUrlLikeBase(alias) : void 0;
|
|
137
238
|
let buildFailed = false;
|
|
138
239
|
let upload = false;
|
|
139
|
-
let outDir = normalizePath(
|
|
240
|
+
let outDir = normalizePath(resolve2("dist"));
|
|
140
241
|
let resolvedConfig = null;
|
|
141
242
|
const useInteractiveOutput = fancy && Boolean(process.stdout?.isTTY) && Boolean(process.stderr?.isTTY) && !process.env.CI;
|
|
142
|
-
const
|
|
243
|
+
const clearViewport = () => {
|
|
143
244
|
if (!useInteractiveOutput) return;
|
|
144
245
|
process.stdout.write("\x1B[2J\x1B[0f");
|
|
145
246
|
};
|
|
@@ -152,8 +253,7 @@ function vitePluginDeployOss(option) {
|
|
|
152
253
|
if (!uploadDir) errors.push("uploadDir is required");
|
|
153
254
|
if (!Number.isInteger(retryTimes) || retryTimes < 1) errors.push("retryTimes must be >= 1");
|
|
154
255
|
if (!Number.isInteger(concurrency) || concurrency < 1) errors.push("concurrency must be >= 1");
|
|
155
|
-
if (!Number.isFinite(multipartThreshold) || multipartThreshold <= 0)
|
|
156
|
-
errors.push("multipartThreshold must be > 0");
|
|
256
|
+
if (!Number.isFinite(multipartThreshold) || multipartThreshold <= 0) errors.push("multipartThreshold must be > 0");
|
|
157
257
|
return errors;
|
|
158
258
|
};
|
|
159
259
|
const uploadSingleTask = async (client, task) => uploadFileWithRetry(client, task, false);
|
|
@@ -162,7 +262,7 @@ function vitePluginDeployOss(option) {
|
|
|
162
262
|
const headers = {
|
|
163
263
|
"x-oss-storage-class": "Standard",
|
|
164
264
|
"x-oss-object-acl": "default",
|
|
165
|
-
"Cache-Control": task.cacheControl || (noCache ? "no-cache" : "public, max-age=86400, immutable"),
|
|
265
|
+
"Cache-Control": task.cacheControl || (noCache || task.name.endsWith(".html") ? "no-cache" : "public, max-age=86400, immutable"),
|
|
166
266
|
"x-oss-forbid-overwrite": overwrite ? "false" : "true"
|
|
167
267
|
};
|
|
168
268
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
@@ -181,7 +281,9 @@ function vitePluginDeployOss(option) {
|
|
|
181
281
|
try {
|
|
182
282
|
await unlink(task.filePath);
|
|
183
283
|
} catch (error) {
|
|
184
|
-
console.warn(
|
|
284
|
+
console.warn(
|
|
285
|
+
`${getLogSymbol("warning")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${truncateTerminalText(task.relativeFilePath, 18)}`
|
|
286
|
+
);
|
|
185
287
|
}
|
|
186
288
|
}
|
|
187
289
|
return {
|
|
@@ -198,9 +300,8 @@ function vitePluginDeployOss(option) {
|
|
|
198
300
|
} catch (error) {
|
|
199
301
|
if (attempt === maxRetries) {
|
|
200
302
|
if (!silentLogs) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
);
|
|
303
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
304
|
+
console.log(`${getLogSymbol("danger")} ${truncateTerminalText(task.relativeFilePath, 18)} ${reason}`);
|
|
204
305
|
}
|
|
205
306
|
return {
|
|
206
307
|
success: false,
|
|
@@ -213,9 +314,11 @@ function vitePluginDeployOss(option) {
|
|
|
213
314
|
};
|
|
214
315
|
} else {
|
|
215
316
|
if (!silentLogs) {
|
|
216
|
-
console.log(
|
|
317
|
+
console.log(
|
|
318
|
+
`${getLogSymbol("warning")} ${truncateTerminalText(task.relativeFilePath, 18)} \u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})`
|
|
319
|
+
);
|
|
217
320
|
}
|
|
218
|
-
await new Promise((
|
|
321
|
+
await new Promise((resolve3) => setTimeout(resolve3, 1e3 * attempt));
|
|
219
322
|
}
|
|
220
323
|
}
|
|
221
324
|
}
|
|
@@ -239,8 +342,8 @@ function vitePluginDeployOss(option) {
|
|
|
239
342
|
let retries = 0;
|
|
240
343
|
const taskCandidates = await Promise.all(
|
|
241
344
|
files.map(async (relativeFilePath) => {
|
|
242
|
-
const filePath = normalizePath(
|
|
243
|
-
const name = normalizeObjectKey(
|
|
345
|
+
const filePath = normalizePath(resolve2(outDir, relativeFilePath));
|
|
346
|
+
const name = normalizeObjectKey(normalizedUploadDir, relativeFilePath);
|
|
244
347
|
try {
|
|
245
348
|
const fileStats = await stat(filePath);
|
|
246
349
|
return { task: { filePath, relativeFilePath, name, size: fileStats.size } };
|
|
@@ -268,47 +371,58 @@ function vitePluginDeployOss(option) {
|
|
|
268
371
|
}
|
|
269
372
|
const totalBytes = tasks.reduce((sum, task) => sum + task.size, 0);
|
|
270
373
|
const startAt = Date.now();
|
|
271
|
-
const activeFiles = /* @__PURE__ */ new Set();
|
|
272
374
|
const safeWindowSize = Math.max(1, Math.min(windowSize, tasks.length || 1));
|
|
273
375
|
const silentLogs = Boolean(useInteractiveOutput);
|
|
274
|
-
const
|
|
275
|
-
|
|
376
|
+
const progressBar = useInteractiveOutput ? new cliProgress.SingleBar({
|
|
377
|
+
hideCursor: true,
|
|
378
|
+
clearOnComplete: true,
|
|
379
|
+
stopOnComplete: true,
|
|
380
|
+
barsize: 18,
|
|
381
|
+
barCompleteChar: "\u2588",
|
|
382
|
+
barIncompleteChar: "\u2591",
|
|
383
|
+
format: `${chalk3.gray("\u4E0A\u4F20")} ${chalk3.bold("{percentage}%")} ${chalk3.cyan("{bar}")} ${chalk3.gray("\xB7")} ${chalk3.magenta("{speed}/s")} ${chalk3.gray("\xB7")} ${chalk3.gray("{elapsed}")}s`
|
|
384
|
+
}) : null;
|
|
385
|
+
const reportEvery = Math.max(1, Math.ceil(totalFiles / 6));
|
|
276
386
|
let lastReportedCompleted = -1;
|
|
387
|
+
if (progressBar) {
|
|
388
|
+
progressBar.start(totalFiles, 0, {
|
|
389
|
+
speed: formatBytes(0),
|
|
390
|
+
elapsed: "0"
|
|
391
|
+
});
|
|
392
|
+
}
|
|
277
393
|
const updateProgress = () => {
|
|
278
|
-
const progressRatio = totalFiles > 0 ? completed / totalFiles : 1;
|
|
279
|
-
const percentage = Math.round(progressRatio * 100);
|
|
280
394
|
const elapsedSeconds = (Date.now() - startAt) / 1e3;
|
|
281
395
|
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
396
|
+
if (!progressBar) {
|
|
397
|
+
const progressRatio = totalFiles > 0 ? completed / totalFiles : 1;
|
|
398
|
+
const percentage = Math.round(progressRatio * 100);
|
|
399
|
+
if (completed === 0 && totalFiles > 0) return;
|
|
286
400
|
if (completed === lastReportedCompleted) return;
|
|
287
401
|
if (completed === totalFiles || completed % reportEvery === 0) {
|
|
288
402
|
console.log(
|
|
289
|
-
`${
|
|
403
|
+
`${chalk3.gray("\u4E0A\u4F20\u8FDB\u5EA6")} ${renderInlineStats([
|
|
404
|
+
chalk3.bold(`${completed}/${totalFiles}`),
|
|
405
|
+
`${percentage}%`,
|
|
406
|
+
`${formatBytes(uploadedBytes)}/${formatBytes(totalBytes)}`,
|
|
407
|
+
`${formatBytes(speed)}/s`
|
|
408
|
+
])}`
|
|
290
409
|
);
|
|
291
410
|
lastReportedCompleted = completed;
|
|
292
411
|
}
|
|
293
412
|
return;
|
|
294
413
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
`${chalk.cyan("\u6B63\u5728\u4E0A\u4F20:")} ${chalk.white(currentFile)}`,
|
|
300
|
-
`${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))}`
|
|
301
|
-
].join("\n");
|
|
302
|
-
spinner.text += warnLine;
|
|
414
|
+
progressBar.update(completed, {
|
|
415
|
+
speed: chalk3.magenta(formatBytes(speed)),
|
|
416
|
+
elapsed: formatDuration(elapsedSeconds).replace(/s$/, "")
|
|
417
|
+
});
|
|
303
418
|
};
|
|
304
|
-
const refreshTimer =
|
|
419
|
+
const refreshTimer = progressBar ? setInterval(updateProgress, 120) : null;
|
|
305
420
|
let currentIndex = 0;
|
|
306
421
|
const worker = async () => {
|
|
307
422
|
while (true) {
|
|
308
423
|
const index = currentIndex++;
|
|
309
424
|
if (index >= tasks.length) return;
|
|
310
425
|
const task = tasks[index];
|
|
311
|
-
activeFiles.add(task.name);
|
|
312
426
|
updateProgress();
|
|
313
427
|
const result = await uploadFileWithRetry(client, task, silentLogs);
|
|
314
428
|
completed++;
|
|
@@ -319,7 +433,6 @@ ${chalk.yellow("\u91CD\u8BD5")}: ${retries} ${chalk.yellow("\u5931\u8D25")}: ${
|
|
|
319
433
|
failed++;
|
|
320
434
|
}
|
|
321
435
|
results.push(result);
|
|
322
|
-
activeFiles.delete(task.name);
|
|
323
436
|
updateProgress();
|
|
324
437
|
}
|
|
325
438
|
};
|
|
@@ -329,16 +442,16 @@ ${chalk.yellow("\u91CD\u8BD5")}: ${retries} ${chalk.yellow("\u5931\u8D25")}: ${
|
|
|
329
442
|
} finally {
|
|
330
443
|
if (refreshTimer) clearInterval(refreshTimer);
|
|
331
444
|
}
|
|
332
|
-
if (
|
|
445
|
+
if (progressBar) {
|
|
333
446
|
const elapsedSeconds = (Date.now() - startAt) / 1e3;
|
|
334
|
-
const successCount = results.filter((item) => item.success).length;
|
|
335
447
|
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
);
|
|
448
|
+
progressBar.update(totalFiles, {
|
|
449
|
+
speed: chalk3.magenta(formatBytes(speed)),
|
|
450
|
+
elapsed: formatDuration(elapsedSeconds).replace(/s$/, "")
|
|
451
|
+
});
|
|
452
|
+
progressBar.stop();
|
|
340
453
|
} else {
|
|
341
|
-
console.log(`${
|
|
454
|
+
console.log(`${getLogSymbol("success")} \u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210 (${totalFiles}/${totalFiles})`);
|
|
342
455
|
}
|
|
343
456
|
return results;
|
|
344
457
|
};
|
|
@@ -351,20 +464,19 @@ ${buildCapsuleBar(1)} 100% (${totalFiles}/${totalFiles}) ${chalk.gray("|")} \u90
|
|
|
351
464
|
},
|
|
352
465
|
config(config) {
|
|
353
466
|
if (!open || buildFailed) return;
|
|
354
|
-
clearScreen();
|
|
355
467
|
const validationErrors = validateOptions();
|
|
356
468
|
if (validationErrors.length > 0) {
|
|
357
|
-
console.log(`${
|
|
469
|
+
console.log(`${chalk3.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
|
|
358
470
|
${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
359
471
|
return;
|
|
360
472
|
}
|
|
361
473
|
upload = true;
|
|
362
|
-
config.base =
|
|
474
|
+
config.base = normalizedConfigBase || config.base;
|
|
363
475
|
return config;
|
|
364
476
|
},
|
|
365
477
|
configResolved(config) {
|
|
366
478
|
resolvedConfig = config;
|
|
367
|
-
outDir = normalizePath(
|
|
479
|
+
outDir = normalizePath(resolve2(config.root, config.build.outDir));
|
|
368
480
|
},
|
|
369
481
|
closeBundle: {
|
|
370
482
|
sequential: true,
|
|
@@ -380,69 +492,49 @@ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
|
|
|
380
492
|
ignore: Array.isArray(skip) ? skip : [skip]
|
|
381
493
|
}).map((file) => normalizePath(file)).filter((file) => file !== manifestFileName);
|
|
382
494
|
if (files.length === 0) {
|
|
383
|
-
console.log(`${
|
|
495
|
+
console.log(`${getLogSymbol("warning")} \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6`);
|
|
384
496
|
return;
|
|
385
497
|
}
|
|
386
|
-
|
|
387
|
-
console.log(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
`
|
|
498
|
+
clearViewport();
|
|
499
|
+
console.log(
|
|
500
|
+
renderPanel(
|
|
501
|
+
"\u51C6\u5907\u90E8\u7F72",
|
|
502
|
+
[
|
|
503
|
+
{ label: "\u4F4D\u7F6E:", value: chalk3.green(`${bucket} \xB7 ${region}`) },
|
|
504
|
+
{
|
|
505
|
+
label: "\u76EE\u6807:",
|
|
506
|
+
value: chalk3.yellow(
|
|
507
|
+
truncateTerminalText(
|
|
508
|
+
normalizedAlias ? `${normalizedUploadDir || "/"} \xB7 ${normalizedAlias}` : normalizedUploadDir || "/",
|
|
509
|
+
18
|
|
510
|
+
)
|
|
511
|
+
)
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
label: "\u6587\u4EF6:",
|
|
515
|
+
value: chalk3.blue(`${files.length} \u4E2A \xB7 ${truncateTerminalText(outDir, 30)}`)
|
|
516
|
+
}
|
|
517
|
+
],
|
|
518
|
+
"info"
|
|
519
|
+
)
|
|
520
|
+
);
|
|
397
521
|
try {
|
|
398
522
|
const results = await uploadFilesInBatches(client, files, concurrency);
|
|
399
523
|
const successCount = results.filter((r) => r.success).length;
|
|
400
524
|
const failedCount = results.length - successCount;
|
|
401
525
|
const durationSeconds = (Date.now() - startTime) / 1e3;
|
|
402
|
-
const duration = durationSeconds.toFixed(2);
|
|
403
526
|
const uploadedBytes = results.reduce((sum, result) => result.success ? sum + result.size : sum, 0);
|
|
404
527
|
const retryCount = results.reduce((sum, result) => sum + result.retries, 0);
|
|
405
528
|
const avgSpeed = durationSeconds > 0 ? uploadedBytes / durationSeconds : 0;
|
|
406
|
-
|
|
407
|
-
console.log("\n" + chalk.gray("\u2500".repeat(40)) + "\n");
|
|
408
|
-
if (failedCount === 0) {
|
|
409
|
-
console.log(`${chalk.green("\u{1F389} \u90E8\u7F72\u6210\u529F!")}`);
|
|
410
|
-
} else {
|
|
411
|
-
console.log(`${chalk.yellow("\u26A0 \u90E8\u7F72\u5B8C\u6210\u4F46\u5B58\u5728\u9519\u8BEF")}`);
|
|
412
|
-
}
|
|
413
|
-
console.log(`
|
|
414
|
-
${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
415
|
-
console.log(` ${chalk.green("\u2714")} \u6210\u529F: ${chalk.bold(successCount)}`);
|
|
416
|
-
if (failedCount > 0) {
|
|
417
|
-
console.log(` ${chalk.red("\u2717")} \u5931\u8D25: ${chalk.bold(failedCount)}`);
|
|
418
|
-
}
|
|
419
|
-
console.log(` ${chalk.cyan("\u21C4")} \u91CD\u8BD5: ${chalk.bold(retryCount)}`);
|
|
420
|
-
console.log(` ${chalk.blue("\u{1F4E6}")} \u6570\u636E: ${chalk.bold(formatBytes(uploadedBytes))}`);
|
|
421
|
-
console.log(` ${chalk.magenta("\u26A1")} \u5E73\u5747\u901F\u5EA6: ${chalk.bold(`${formatBytes(avgSpeed)}/s`)}`);
|
|
422
|
-
console.log(` ${chalk.blue("\u23F1")} \u8017\u65F6: ${chalk.bold(duration)}s`);
|
|
423
|
-
console.log("");
|
|
424
|
-
if (failedCount > 0) {
|
|
425
|
-
const failedItems = results.filter((result) => !result.success);
|
|
426
|
-
const previewCount = Math.min(5, failedItems.length);
|
|
427
|
-
console.log(chalk.red("\u5931\u8D25\u660E\u7EC6:"));
|
|
428
|
-
for (let i = 0; i < previewCount; i++) {
|
|
429
|
-
const item = failedItems[i];
|
|
430
|
-
const reason = item.error?.message || "unknown error";
|
|
431
|
-
console.log(` ${chalk.red("\u2022")} ${item.name} => ${reason}`);
|
|
432
|
-
}
|
|
433
|
-
if (failedItems.length > previewCount) {
|
|
434
|
-
console.log(chalk.gray(` ... \u8FD8\u6709 ${failedItems.length - previewCount} \u4E2A\u5931\u8D25\u6587\u4EF6`));
|
|
435
|
-
}
|
|
436
|
-
console.log("");
|
|
437
|
-
}
|
|
529
|
+
let manifestSummary = null;
|
|
438
530
|
if (manifestFileName) {
|
|
439
531
|
const manifestRelativeFilePath = manifestFileName;
|
|
440
|
-
const manifestFilePath = normalizePath(
|
|
441
|
-
const manifestObjectKey = normalizeObjectKey(
|
|
532
|
+
const manifestFilePath = normalizePath(resolve2(outDir, manifestRelativeFilePath));
|
|
533
|
+
const manifestObjectKey = normalizeObjectKey(normalizedUploadDir, manifestRelativeFilePath);
|
|
442
534
|
await mkdir(dirname(manifestFilePath), { recursive: true });
|
|
443
535
|
await writeFile(
|
|
444
536
|
manifestFilePath,
|
|
445
|
-
JSON.stringify(createManifestPayload(results,
|
|
537
|
+
JSON.stringify(await createManifestPayload(results, normalizedConfigBase, normalizedAlias), null, 2),
|
|
446
538
|
"utf8"
|
|
447
539
|
);
|
|
448
540
|
const manifestStats = await stat(manifestFilePath);
|
|
@@ -451,7 +543,7 @@ ${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
|
451
543
|
relativeFilePath: manifestRelativeFilePath,
|
|
452
544
|
name: manifestObjectKey,
|
|
453
545
|
size: manifestStats.size,
|
|
454
|
-
cacheControl: "no-cache"
|
|
546
|
+
cacheControl: "no-cache, no-store, must-revalidate"
|
|
455
547
|
});
|
|
456
548
|
if (!manifestResult.success) {
|
|
457
549
|
throw manifestResult.error || new Error(`Failed to upload manifest: ${manifestRelativeFilePath}`);
|
|
@@ -459,26 +551,62 @@ ${chalk.gray("\u7EDF\u8BA1:")}`);
|
|
|
459
551
|
const manifestUrl = resolveUploadedFileUrl(
|
|
460
552
|
manifestRelativeFilePath,
|
|
461
553
|
manifestObjectKey,
|
|
462
|
-
|
|
463
|
-
|
|
554
|
+
normalizedConfigBase,
|
|
555
|
+
normalizedAlias
|
|
464
556
|
);
|
|
465
|
-
|
|
466
|
-
console.log(` ${chalk.gray("File:")} ${chalk.yellow(manifestFilePath)}`);
|
|
467
|
-
console.log(` ${chalk.gray("Target:")} ${chalk.yellow(manifestObjectKey)}`);
|
|
468
|
-
console.log(` ${chalk.gray("URL:")} ${chalk.green(manifestUrl)}`);
|
|
469
|
-
console.log("");
|
|
557
|
+
manifestSummary = truncateTerminalText(manifestUrl || manifestObjectKey, 20);
|
|
470
558
|
}
|
|
471
559
|
try {
|
|
472
560
|
await removeEmptyDirectories(outDir);
|
|
473
561
|
} catch (error) {
|
|
474
|
-
console.warn(`${
|
|
562
|
+
console.warn(`${getLogSymbol("warning")} \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25: ${error}`);
|
|
475
563
|
}
|
|
564
|
+
const resultRows = [
|
|
565
|
+
{
|
|
566
|
+
label: "\u7ED3\u679C:",
|
|
567
|
+
value: failedCount === 0 ? chalk3.green(`${successCount}/${results.length} \u5168\u90E8\u6210\u529F`) : chalk3.yellow(`\u6210\u529F ${successCount} \u4E2A\uFF0C\u5931\u8D25 ${failedCount} \u4E2A`)
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
label: "\u7EDF\u8BA1:",
|
|
571
|
+
value: renderInlineStats([
|
|
572
|
+
`${retryCount} \u6B21\u91CD\u8BD5`,
|
|
573
|
+
formatBytes(uploadedBytes),
|
|
574
|
+
`${formatBytes(avgSpeed)}/s`,
|
|
575
|
+
formatDuration(durationSeconds)
|
|
576
|
+
])
|
|
577
|
+
},
|
|
578
|
+
...manifestSummary ? [{ label: "\u6E05\u5355:", value: chalk3.cyan(manifestSummary) }] : []
|
|
579
|
+
];
|
|
580
|
+
if (failedCount > 0) {
|
|
581
|
+
const failedItems = results.filter((result) => !result.success).slice(0, 2);
|
|
582
|
+
resultRows.push(
|
|
583
|
+
...failedItems.map((item, index) => ({
|
|
584
|
+
label: `\u5931\u8D25 ${index + 1}`,
|
|
585
|
+
value: chalk3.red(
|
|
586
|
+
`${truncateTerminalText(item.name, 26)} \xB7 ${truncateTerminalText(item.error?.message || "unknown error", 22)}`
|
|
587
|
+
)
|
|
588
|
+
}))
|
|
589
|
+
);
|
|
590
|
+
if (failedCount > failedItems.length) {
|
|
591
|
+
resultRows.push({
|
|
592
|
+
label: "\u5176\u4F59",
|
|
593
|
+
value: chalk3.gray(`\u8FD8\u6709 ${failedCount - failedItems.length} \u4E2A\u5931\u8D25\u9879\u672A\u5C55\u5F00`)
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
console.log(
|
|
598
|
+
renderPanel(
|
|
599
|
+
failedCount === 0 ? `${getLogSymbol("success")} \u90E8\u7F72\u5B8C\u6210` : `${getLogSymbol("warning")} \u90E8\u7F72\u5B8C\u6210`,
|
|
600
|
+
resultRows,
|
|
601
|
+
failedCount === 0 ? "success" : "warning"
|
|
602
|
+
)
|
|
603
|
+
);
|
|
476
604
|
if (failedCount > 0 && failOnError) {
|
|
477
605
|
throw new Error(`Failed to upload ${failedCount} of ${results.length} files`);
|
|
478
606
|
}
|
|
479
607
|
} catch (error) {
|
|
480
608
|
console.log(`
|
|
481
|
-
${
|
|
609
|
+
${getLogSymbol("danger")} \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF: ${error}
|
|
482
610
|
`);
|
|
483
611
|
if (failOnError) {
|
|
484
612
|
throw error instanceof Error ? error : new Error(String(error));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-deploy-oss",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -40,10 +40,14 @@
|
|
|
40
40
|
"vite": "^6.0.3 || ^7 || ^8"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@types/cli-progress": "^3.11.6",
|
|
43
44
|
"ali-oss": "^6.23.0",
|
|
44
45
|
"chalk": "^5.6.2",
|
|
46
|
+
"cli-progress": "^3.12.0",
|
|
47
|
+
"cli-truncate": "^5.2.0",
|
|
45
48
|
"glob": "^13.0.6",
|
|
46
|
-
"
|
|
49
|
+
"log-symbols": "^7.0.1",
|
|
50
|
+
"string-width": "^8.2.0"
|
|
47
51
|
},
|
|
48
52
|
"scripts": {
|
|
49
53
|
"build": "tsup",
|