vite-plugin-deploy-oss 0.0.12 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,13 +1,13 @@
1
1
  import oss from 'ali-oss';
2
2
  import { Plugin } from 'vite';
3
3
 
4
- type vitePluginDeployOssOption = oss.Options & {
4
+ interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'accessKeySecret' | 'bucket' | 'region'> {
5
5
  configBase?: string;
6
6
  accessKeyId: string;
7
7
  accessKeySecret: string;
8
- region?: string;
8
+ region: string;
9
9
  secure?: boolean;
10
- bucket?: string;
10
+ bucket: string;
11
11
  overwrite?: boolean;
12
12
  uploadDir: string;
13
13
  alias?: string;
@@ -15,7 +15,10 @@ type vitePluginDeployOssOption = oss.Options & {
15
15
  skip?: string | string[];
16
16
  open?: boolean;
17
17
  noCache?: boolean;
18
- };
18
+ concurrency?: number;
19
+ retryTimes?: number;
20
+ showProgress?: boolean;
21
+ }
19
22
  declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
20
23
 
21
24
  export { vitePluginDeployOss as default, type vitePluginDeployOssOption };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import oss from 'ali-oss';
2
2
  import { Plugin } from 'vite';
3
3
 
4
- type vitePluginDeployOssOption = oss.Options & {
4
+ interface vitePluginDeployOssOption extends Omit<oss.Options, 'accessKeyId' | 'accessKeySecret' | 'bucket' | 'region'> {
5
5
  configBase?: string;
6
6
  accessKeyId: string;
7
7
  accessKeySecret: string;
8
- region?: string;
8
+ region: string;
9
9
  secure?: boolean;
10
- bucket?: string;
10
+ bucket: string;
11
11
  overwrite?: boolean;
12
12
  uploadDir: string;
13
13
  alias?: string;
@@ -15,7 +15,10 @@ type vitePluginDeployOssOption = oss.Options & {
15
15
  skip?: string | string[];
16
16
  open?: boolean;
17
17
  noCache?: boolean;
18
- };
18
+ concurrency?: number;
19
+ retryTimes?: number;
20
+ showProgress?: boolean;
21
+ }
19
22
  declare function vitePluginDeployOss(option: vitePluginDeployOssOption): Plugin;
20
23
 
21
24
  export { vitePluginDeployOss as default, type vitePluginDeployOssOption };
package/dist/index.js CHANGED
@@ -55,18 +55,95 @@ function vitePluginDeployOss(option) {
55
55
  alias,
56
56
  open = true,
57
57
  noCache = false,
58
+ concurrency = 5,
59
+ retryTimes = 3,
60
+ showProgress = true,
58
61
  ...props
59
62
  } = option || {};
60
63
  let upload = false;
61
64
  let outDir = "";
65
+ const validateOptions = () => {
66
+ const errors = [];
67
+ if (!accessKeyId) errors.push("accessKeyId is required");
68
+ if (!accessKeySecret) errors.push("accessKeySecret is required");
69
+ if (!bucket) errors.push("bucket is required");
70
+ if (!region) errors.push("region is required");
71
+ if (!uploadDir) errors.push("uploadDir is required");
72
+ return errors;
73
+ };
74
+ const uploadFileWithRetry = async (client, name, filePath, maxRetries = retryTimes) => {
75
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
76
+ try {
77
+ const result = await client.put(name, filePath, {
78
+ timeout: 6e5,
79
+ headers: {
80
+ "x-oss-storage-class": "Standard",
81
+ "x-oss-object-acl": "default",
82
+ "Cache-Control": noCache ? "no-cache" : "public, max-age=86400, immutable",
83
+ ...overwrite && {
84
+ "x-oss-forbid-overwrite": "false"
85
+ }
86
+ }
87
+ });
88
+ if (result.res.status === 200) {
89
+ const url = alias ? alias + name : result.url;
90
+ console.log(`${import_chalk.default.green("\u2713")} ${filePath}`);
91
+ console.log(`=> ${import_chalk.default.cyan(url)}`);
92
+ if (autoDelete) {
93
+ try {
94
+ (0, import_node_fs.unlinkSync)(filePath);
95
+ } catch (error) {
96
+ console.warn(`${import_chalk.default.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${filePath}`);
97
+ }
98
+ }
99
+ return { success: true, file: filePath };
100
+ } else {
101
+ throw new Error(`Upload failed with status: ${result.res.status}`);
102
+ }
103
+ } catch (error) {
104
+ if (attempt === maxRetries) {
105
+ console.log(`${import_chalk.default.red("\u2717")} ${filePath} => ${error instanceof Error ? error.message : String(error)}`);
106
+ return { success: false, file: filePath, error };
107
+ } else {
108
+ console.log(`${import_chalk.default.yellow("\u26A0")} ${filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
109
+ await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
110
+ }
111
+ }
112
+ }
113
+ return { success: false, file: filePath, error: new Error("Max retries exceeded") };
114
+ };
115
+ const uploadFilesInBatches = async (client, files, batchSize = concurrency) => {
116
+ const results = [];
117
+ const totalFiles = files.length;
118
+ let completed = 0;
119
+ for (let i = 0; i < files.length; i += batchSize) {
120
+ const batch = files.slice(i, i + batchSize);
121
+ const batchPromises = batch.map(async (file) => {
122
+ const filePath = (0, import_vite.normalizePath)(file);
123
+ const name = filePath.replace(outDir, uploadDir).replace(/\/\//g, "/");
124
+ const result = await uploadFileWithRetry(client, name, filePath);
125
+ completed++;
126
+ if (showProgress) {
127
+ const progress = Math.round(completed / totalFiles * 100);
128
+ console.log(`${import_chalk.default.blue("\u8FDB\u5EA6:")} ${progress}% (${completed}/${totalFiles})`);
129
+ }
130
+ return result;
131
+ });
132
+ const batchResults = await Promise.all(batchPromises);
133
+ results.push(...batchResults);
134
+ }
135
+ return results;
136
+ };
62
137
  return {
63
138
  name: "vite-plugin-deploy-oss",
64
139
  apply: "build",
65
140
  enforce: "post",
66
141
  config(config) {
67
142
  if (!open) return;
68
- if (!accessKeyId || !accessKeySecret || !bucket || !region || !uploadDir) {
69
- console.log(`:: ${import_chalk.default.red("\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570")}`);
143
+ const validationErrors = validateOptions();
144
+ if (validationErrors.length > 0) {
145
+ console.log(`${import_chalk.default.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
146
+ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
70
147
  return;
71
148
  }
72
149
  upload = true;
@@ -78,42 +155,51 @@ function vitePluginDeployOss(option) {
78
155
  sequential: true,
79
156
  order: "post",
80
157
  async handler() {
81
- if (!open) return;
82
- if (!upload) return;
83
- console.log(`:: ${import_chalk.default.blue("\u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6")} =>
158
+ if (!open || !upload) return;
159
+ console.log(`${import_chalk.default.blue("\u{1F680} \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6\u5230 OSS...")}
84
160
  `);
161
+ const startTime = Date.now();
85
162
  const client = new import_ali_oss.default({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
86
163
  const files = (0, import_glob.globSync)(outDir + "/**/*", {
87
164
  nodir: true,
88
165
  ignore: Array.isArray(skip) ? skip : [skip]
89
166
  });
90
- for (const file of files) {
91
- const filePath = (0, import_vite.normalizePath)(file);
92
- const name = filePath.replace("dist", `${uploadDir}`).replace(/\/\//g, "/");
167
+ if (files.length === 0) {
168
+ console.log(`${import_chalk.default.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
169
+ return;
170
+ }
171
+ console.log(`${import_chalk.default.blue("\u{1F4C1} \u627E\u5230")} ${files.length} ${import_chalk.default.blue("\u4E2A\u6587\u4EF6\u9700\u8981\u4E0A\u4F20")}`);
172
+ try {
173
+ const results = await uploadFilesInBatches(client, files, concurrency);
174
+ const successCount = results.filter((r) => r.success).length;
175
+ const failedCount = results.length - successCount;
176
+ const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
177
+ console.log(`
178
+ ${import_chalk.default.blue("\u{1F4CA} \u4E0A\u4F20\u7EDF\u8BA1:")}`);
179
+ console.log(` ${import_chalk.default.green("\u2713 \u6210\u529F:")} ${successCount}`);
180
+ if (failedCount > 0) {
181
+ console.log(` ${import_chalk.default.red("\u2717 \u5931\u8D25:")} ${failedCount}`);
182
+ }
183
+ console.log(` ${import_chalk.default.blue("\u23F1 \u8017\u65F6:")} ${duration}s`);
93
184
  try {
94
- const result = await client.put(name, filePath, {
95
- timeout: 6e5,
96
- headers: {
97
- "x-oss-storage-class": "Standard",
98
- "x-oss-object-acl": "default",
99
- "Cache-Control": noCache ? "no-cache" : "public, max-age=3600, immutable",
100
- ...overwrite && {
101
- "x-oss-forbid-overwrite": "false"
102
- }
103
- }
104
- });
105
- if (result.res.status === 200) {
106
- console.log(`\u4E0A\u4F20\u6210\u529F => ${import_chalk.default.green(alias ? alias + name : result.url)}`);
107
- if (autoDelete) (0, import_node_fs.unlinkSync)(filePath);
108
- }
185
+ (0, import_delete_empty.default)((0, import_node_path.resolve)(outDir));
109
186
  } catch (error) {
110
- console.log(`${import_chalk.default.red("\u4E0A\u4F20\u5931\u8D25")} => ${error}`);
187
+ console.warn(`${import_chalk.default.yellow("\u26A0 \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25:")} ${error}`);
111
188
  }
112
- }
113
- (0, import_delete_empty.default)((0, import_node_path.resolve)(outDir));
114
- console.log(`
115
- :: ${import_chalk.default.blue("\u4E0A\u4F20\u5B8C\u6210")}
189
+ if (failedCount === 0) {
190
+ console.log(`
191
+ ${import_chalk.default.green("\u{1F389} \u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210!")}
192
+ `);
193
+ } else {
194
+ console.log(`
195
+ ${import_chalk.default.yellow("\u26A0 \u90E8\u5206\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u65E5\u5FD7")}
116
196
  `);
197
+ }
198
+ } catch (error) {
199
+ console.log(`
200
+ ${import_chalk.default.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
201
+ `);
202
+ }
117
203
  }
118
204
  }
119
205
  };
package/dist/index.mjs CHANGED
@@ -21,18 +21,95 @@ function vitePluginDeployOss(option) {
21
21
  alias,
22
22
  open = true,
23
23
  noCache = false,
24
+ concurrency = 5,
25
+ retryTimes = 3,
26
+ showProgress = true,
24
27
  ...props
25
28
  } = option || {};
26
29
  let upload = false;
27
30
  let outDir = "";
31
+ const validateOptions = () => {
32
+ const errors = [];
33
+ if (!accessKeyId) errors.push("accessKeyId is required");
34
+ if (!accessKeySecret) errors.push("accessKeySecret is required");
35
+ if (!bucket) errors.push("bucket is required");
36
+ if (!region) errors.push("region is required");
37
+ if (!uploadDir) errors.push("uploadDir is required");
38
+ return errors;
39
+ };
40
+ const uploadFileWithRetry = async (client, name, filePath, maxRetries = retryTimes) => {
41
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
42
+ try {
43
+ const result = await client.put(name, filePath, {
44
+ timeout: 6e5,
45
+ headers: {
46
+ "x-oss-storage-class": "Standard",
47
+ "x-oss-object-acl": "default",
48
+ "Cache-Control": noCache ? "no-cache" : "public, max-age=86400, immutable",
49
+ ...overwrite && {
50
+ "x-oss-forbid-overwrite": "false"
51
+ }
52
+ }
53
+ });
54
+ if (result.res.status === 200) {
55
+ const url = alias ? alias + name : result.url;
56
+ console.log(`${chalk.green("\u2713")} ${filePath}`);
57
+ console.log(`=> ${chalk.cyan(url)}`);
58
+ if (autoDelete) {
59
+ try {
60
+ unlinkSync(filePath);
61
+ } catch (error) {
62
+ console.warn(`${chalk.yellow("\u26A0")} \u5220\u9664\u672C\u5730\u6587\u4EF6\u5931\u8D25: ${filePath}`);
63
+ }
64
+ }
65
+ return { success: true, file: filePath };
66
+ } else {
67
+ throw new Error(`Upload failed with status: ${result.res.status}`);
68
+ }
69
+ } catch (error) {
70
+ if (attempt === maxRetries) {
71
+ console.log(`${chalk.red("\u2717")} ${filePath} => ${error instanceof Error ? error.message : String(error)}`);
72
+ return { success: false, file: filePath, error };
73
+ } else {
74
+ console.log(`${chalk.yellow("\u26A0")} ${filePath} \u4E0A\u4F20\u5931\u8D25\uFF0C\u6B63\u5728\u91CD\u8BD5 (${attempt}/${maxRetries})...`);
75
+ await new Promise((resolve2) => setTimeout(resolve2, 1e3 * attempt));
76
+ }
77
+ }
78
+ }
79
+ return { success: false, file: filePath, error: new Error("Max retries exceeded") };
80
+ };
81
+ const uploadFilesInBatches = async (client, files, batchSize = concurrency) => {
82
+ const results = [];
83
+ const totalFiles = files.length;
84
+ let completed = 0;
85
+ for (let i = 0; i < files.length; i += batchSize) {
86
+ const batch = files.slice(i, i + batchSize);
87
+ const batchPromises = batch.map(async (file) => {
88
+ const filePath = normalizePath(file);
89
+ const name = filePath.replace(outDir, uploadDir).replace(/\/\//g, "/");
90
+ const result = await uploadFileWithRetry(client, name, filePath);
91
+ completed++;
92
+ if (showProgress) {
93
+ const progress = Math.round(completed / totalFiles * 100);
94
+ console.log(`${chalk.blue("\u8FDB\u5EA6:")} ${progress}% (${completed}/${totalFiles})`);
95
+ }
96
+ return result;
97
+ });
98
+ const batchResults = await Promise.all(batchPromises);
99
+ results.push(...batchResults);
100
+ }
101
+ return results;
102
+ };
28
103
  return {
29
104
  name: "vite-plugin-deploy-oss",
30
105
  apply: "build",
31
106
  enforce: "post",
32
107
  config(config) {
33
108
  if (!open) return;
34
- if (!accessKeyId || !accessKeySecret || !bucket || !region || !uploadDir) {
35
- console.log(`:: ${chalk.red("\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570")}`);
109
+ const validationErrors = validateOptions();
110
+ if (validationErrors.length > 0) {
111
+ console.log(`${chalk.red("\u2717 \u914D\u7F6E\u9519\u8BEF:")}
112
+ ${validationErrors.map((err) => ` - ${err}`).join("\n")}`);
36
113
  return;
37
114
  }
38
115
  upload = true;
@@ -44,42 +121,51 @@ function vitePluginDeployOss(option) {
44
121
  sequential: true,
45
122
  order: "post",
46
123
  async handler() {
47
- if (!open) return;
48
- if (!upload) return;
49
- console.log(`:: ${chalk.blue("\u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6")} =>
124
+ if (!open || !upload) return;
125
+ console.log(`${chalk.blue("\u{1F680} \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6\u5230 OSS...")}
50
126
  `);
127
+ const startTime = Date.now();
51
128
  const client = new oss({ region, accessKeyId, accessKeySecret, secure, bucket, ...props });
52
129
  const files = globSync(outDir + "/**/*", {
53
130
  nodir: true,
54
131
  ignore: Array.isArray(skip) ? skip : [skip]
55
132
  });
56
- for (const file of files) {
57
- const filePath = normalizePath(file);
58
- const name = filePath.replace("dist", `${uploadDir}`).replace(/\/\//g, "/");
133
+ if (files.length === 0) {
134
+ console.log(`${chalk.yellow("\u26A0 \u6CA1\u6709\u627E\u5230\u9700\u8981\u4E0A\u4F20\u7684\u6587\u4EF6")}`);
135
+ return;
136
+ }
137
+ console.log(`${chalk.blue("\u{1F4C1} \u627E\u5230")} ${files.length} ${chalk.blue("\u4E2A\u6587\u4EF6\u9700\u8981\u4E0A\u4F20")}`);
138
+ try {
139
+ const results = await uploadFilesInBatches(client, files, concurrency);
140
+ const successCount = results.filter((r) => r.success).length;
141
+ const failedCount = results.length - successCount;
142
+ const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
143
+ console.log(`
144
+ ${chalk.blue("\u{1F4CA} \u4E0A\u4F20\u7EDF\u8BA1:")}`);
145
+ console.log(` ${chalk.green("\u2713 \u6210\u529F:")} ${successCount}`);
146
+ if (failedCount > 0) {
147
+ console.log(` ${chalk.red("\u2717 \u5931\u8D25:")} ${failedCount}`);
148
+ }
149
+ console.log(` ${chalk.blue("\u23F1 \u8017\u65F6:")} ${duration}s`);
59
150
  try {
60
- const result = await client.put(name, filePath, {
61
- timeout: 6e5,
62
- headers: {
63
- "x-oss-storage-class": "Standard",
64
- "x-oss-object-acl": "default",
65
- "Cache-Control": noCache ? "no-cache" : "public, max-age=3600, immutable",
66
- ...overwrite && {
67
- "x-oss-forbid-overwrite": "false"
68
- }
69
- }
70
- });
71
- if (result.res.status === 200) {
72
- console.log(`\u4E0A\u4F20\u6210\u529F => ${chalk.green(alias ? alias + name : result.url)}`);
73
- if (autoDelete) unlinkSync(filePath);
74
- }
151
+ deleteEmpty(resolve(outDir));
75
152
  } catch (error) {
76
- console.log(`${chalk.red("\u4E0A\u4F20\u5931\u8D25")} => ${error}`);
153
+ console.warn(`${chalk.yellow("\u26A0 \u6E05\u7406\u7A7A\u76EE\u5F55\u5931\u8D25:")} ${error}`);
77
154
  }
78
- }
79
- deleteEmpty(resolve(outDir));
80
- console.log(`
81
- :: ${chalk.blue("\u4E0A\u4F20\u5B8C\u6210")}
155
+ if (failedCount === 0) {
156
+ console.log(`
157
+ ${chalk.green("\u{1F389} \u6240\u6709\u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210!")}
158
+ `);
159
+ } else {
160
+ console.log(`
161
+ ${chalk.yellow("\u26A0 \u90E8\u5206\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u65E5\u5FD7")}
82
162
  `);
163
+ }
164
+ } catch (error) {
165
+ console.log(`
166
+ ${chalk.red("\u274C \u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:")} ${error}
167
+ `);
168
+ }
83
169
  }
84
170
  }
85
171
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-deploy-oss",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",