vite-plugin-deploy-oss 0.0.14 → 0.0.16

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