@seayoo-web/finder 2.2.2 → 2.2.3

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.js CHANGED
@@ -1,376 +1,350 @@
1
- import fs, { readdirSync, lstatSync, existsSync, readFileSync, writeFileSync } from "fs";
2
- import path, { relative, join, basename, normalize, sep, dirname, resolve } from "path";
1
+ import fs, { existsSync, lstatSync, readFileSync, readdirSync, writeFileSync } from "fs";
2
+ import path, { basename, dirname, join, normalize, relative, resolve, sep } from "path";
3
3
  import open from "open";
4
- import "colors";
4
+ import colors from "picocolors";
5
5
  import { zip } from "compressing";
6
6
  import os from "os";
7
- const presetIgnores = ["node_modules/", ".git/", ".vscode/", "__MACOSX/", ".DS_Store", ".gitkeep"];
7
+ //#region src/compress.ts
8
+ var presetIgnores = [
9
+ "node_modules/",
10
+ ".git/",
11
+ ".vscode/",
12
+ "__MACOSX/",
13
+ ".DS_Store",
14
+ ".gitkeep"
15
+ ];
16
+ /** 代码压缩 */
8
17
  function compressToBuffer(sourceDir, ignoreFiles, debug) {
9
- const ignoreFileList = [...presetIgnores, ...ignoreFiles || []];
10
- const filesToCompress = getAllFiles(sourceDir, ignoreFileList);
11
- const zipStream = new zip.Stream();
12
- filesToCompress.forEach((file) => {
13
- zipStream.addEntry(file, { relativePath: relative(sourceDir, file) });
14
- });
15
- if (debug) {
16
- console.log({
17
- method: "compressToBuffer",
18
- sourceDir,
19
- ignores: ignoreFileList,
20
- filesCount: filesToCompress.length
21
- });
22
- }
23
- const chunks = [];
24
- return new Promise(function(resolve2, reject) {
25
- zipStream.on("data", (chunk) => chunks.push(chunk)).on("end", () => resolve2(Buffer.concat(chunks))).on("error", reject);
26
- });
18
+ const ignoreFileList = [...presetIgnores, ...ignoreFiles || []];
19
+ const filesToCompress = getAllFiles(sourceDir, ignoreFileList);
20
+ const zipStream = new zip.Stream();
21
+ filesToCompress.forEach((file) => {
22
+ zipStream.addEntry(file, { relativePath: relative(sourceDir, file) });
23
+ });
24
+ if (debug) console.log({
25
+ method: "compressToBuffer",
26
+ sourceDir,
27
+ ignores: ignoreFileList,
28
+ filesCount: filesToCompress.length
29
+ });
30
+ const chunks = [];
31
+ return new Promise(function(resolve, reject) {
32
+ zipStream.on("data", (chunk) => chunks.push(chunk)).on("end", () => resolve(Buffer.concat(chunks))).on("error", reject);
33
+ });
27
34
  }
28
35
  function getAllFiles(dir, ignores = []) {
29
- const list = [];
30
- readdirSync(dir).forEach((file) => {
31
- const filePath = join(dir, file);
32
- const stats = lstatSync(filePath);
33
- if (stats.isDirectory()) {
34
- list.push(...getAllFiles(filePath, ignores));
35
- } else if (!isIgnoreFile(filePath, ignores)) {
36
- list.push(filePath);
37
- }
38
- });
39
- return list;
36
+ const list = [];
37
+ readdirSync(dir).forEach((file) => {
38
+ const filePath = join(dir, file);
39
+ if (lstatSync(filePath).isDirectory()) list.push(...getAllFiles(filePath, ignores));
40
+ else if (!isIgnoreFile(filePath, ignores)) list.push(filePath);
41
+ });
42
+ return list;
40
43
  }
41
44
  function isIgnoreFile(filePath, ignores) {
42
- const filename = basename(filePath);
43
- const dirs = normalize(filePath).split(sep);
44
- return ignores.some((pattern) => {
45
- if (pattern.endsWith("/")) {
46
- return pattern.includes("*") ? dirs.some((dir) => getRegexp(pattern.slice(0, -1)).test(dir)) : dirs.includes(pattern.slice(0, -1));
47
- }
48
- return pattern.includes("*") ? getRegexp(pattern).test(filename) : filename === pattern;
49
- });
45
+ const filename = basename(filePath);
46
+ const dirs = normalize(filePath).split(sep);
47
+ return ignores.some((pattern) => {
48
+ if (pattern.endsWith("/")) return pattern.includes("*") ? dirs.some((dir) => getRegexp(pattern.slice(0, -1)).test(dir)) : dirs.includes(pattern.slice(0, -1));
49
+ return pattern.includes("*") ? getRegexp(pattern).test(filename) : filename === pattern;
50
+ });
50
51
  }
51
- const pathRegCache = {};
52
- const getRegexp = function(path2) {
53
- if (path2 && pathRegCache[path2]) {
54
- return pathRegCache[path2];
55
- }
56
- const fixRegStr = path2.replace(/([\\(){}\[\]\^\$\+\-\?\.|])/g, "\\$1").replace(/\*{1,}/g, ".*");
57
- return pathRegCache[path2] = new RegExp("^" + fixRegStr + "$");
52
+ var pathRegCache = {};
53
+ var getRegexp = function(path) {
54
+ if (path && pathRegCache[path]) return pathRegCache[path];
55
+ const fixRegStr = path.replace(/([\\(){}[\]^$+\-?.|])/g, "\\$1").replace(/\*{1,}/g, ".*");
56
+ return pathRegCache[path] = new RegExp("^" + fixRegStr + "$");
58
57
  };
58
+ //#endregion
59
+ //#region src/utils.ts
59
60
  function pure(url) {
60
- return url.replace(/(?:^https?:\/\/|\/*$)/gi, "");
61
+ return url.replace(/(?:^https?:\/\/|\/*$)/gi, "");
61
62
  }
62
63
  function getSystemTempDir() {
63
- const dir = path.resolve(os.tmpdir(), "webfinder");
64
- if (!fs.existsSync(dir)) {
65
- fs.mkdirSync(dir, { recursive: true });
66
- }
67
- return dir;
64
+ const dir = path.resolve(os.tmpdir(), "webfinder");
65
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
66
+ return dir;
68
67
  }
69
- const nodeVersion = +process.version.replace(/\..+/, "").slice(1);
70
- if (nodeVersion < 20) {
71
- process.emitWarning = function() {
72
- };
68
+ if (+process.version.replace(/\..+/, "").slice(1) < 20) process.emitWarning = function() {};
69
+ async function request({ url, method, headers, data }) {
70
+ const hasFileUpload = method === "POST" && data && Object.values(data).some((value) => typeof value === "object" && "buffer" in value);
71
+ const reqHeaders = new Headers();
72
+ if (headers) Object.entries(headers).forEach(([key, value]) => {
73
+ reqHeaders.set(key, value);
74
+ });
75
+ const requestInit = {
76
+ method,
77
+ headers: reqHeaders
78
+ };
79
+ try {
80
+ if (data) if (hasFileUpload) {
81
+ const formData = new FormData();
82
+ Object.entries(data).forEach(([key, value]) => {
83
+ if (typeof value === "object" && "buffer" in value) {
84
+ const { buffer, filename, contentType } = value;
85
+ const blob = new Blob([new Uint8Array(buffer)], { type: contentType });
86
+ formData.append(key, blob, filename);
87
+ } else formData.append(key, String(value));
88
+ });
89
+ requestInit.headers = reqHeaders;
90
+ requestInit.body = formData;
91
+ } else {
92
+ reqHeaders.set("content-type", reqHeaders.get("content-type") || "application/json");
93
+ requestInit.headers = reqHeaders;
94
+ requestInit.body = JSON.stringify(data);
95
+ }
96
+ const response = await fetch(url, requestInit);
97
+ let responseData;
98
+ if (response.headers.get("content-type")?.includes("application/json")) responseData = await response.json();
99
+ else responseData = await response.text();
100
+ return {
101
+ status: response.status,
102
+ message: response.statusText,
103
+ data: responseData
104
+ };
105
+ } catch (err) {
106
+ return {
107
+ status: 500,
108
+ message: err instanceof Error ? err.message : String(err),
109
+ data: null
110
+ };
111
+ }
73
112
  }
74
- async function request({
75
- url,
76
- method,
77
- headers,
78
- data
79
- }) {
80
- const hasFileUpload = method === "POST" && data && Object.values(data).some((value) => typeof value === "object" && "buffer" in value);
81
- const reqHeaders = new Headers();
82
- if (headers) {
83
- Object.entries(headers).forEach(([key, value]) => {
84
- reqHeaders.set(key, value);
85
- });
86
- }
87
- const requestInit = { method, headers: reqHeaders };
88
- try {
89
- if (data) {
90
- if (hasFileUpload) {
91
- const formData = new FormData();
92
- Object.entries(data).forEach(([key, value]) => {
93
- if (typeof value === "object" && "buffer" in value) {
94
- const { buffer, filename, contentType: contentType2 } = value;
95
- const blob = new Blob([new Uint8Array(buffer)], { type: contentType2 });
96
- formData.append(key, blob, filename);
97
- } else {
98
- formData.append(key, String(value));
99
- }
100
- });
101
- requestInit.headers = reqHeaders;
102
- requestInit.body = formData;
103
- } else {
104
- reqHeaders.set("content-type", reqHeaders.get("content-type") || "application/json");
105
- requestInit.headers = reqHeaders;
106
- requestInit.body = JSON.stringify(data);
107
- }
108
- }
109
- const response = await fetch(url, requestInit);
110
- let responseData;
111
- const contentType = response.headers.get("content-type");
112
- if (contentType?.includes("application/json")) {
113
- responseData = await response.json();
114
- } else {
115
- responseData = await response.text();
116
- }
117
- return {
118
- status: response.status,
119
- message: response.statusText,
120
- data: responseData
121
- };
122
- } catch (err) {
123
- return {
124
- status: 500,
125
- message: err instanceof Error ? err.message : String(err),
126
- data: null
127
- };
128
- }
129
- }
130
- const FinderServers = {
131
- "finder.seayoo.io": [],
132
- "finder.seayoo.com": [],
133
- "finder.seayoo.internal": [],
134
- "finder.dev.seayoo.com": [],
135
- "finder.dev.seayoo.io": []
113
+ //#endregion
114
+ //#region src/service.ts
115
+ /** finder 服务器列表以及所支持的域名 */
116
+ var FinderServers = {
117
+ "finder.seayoo.io": [],
118
+ "finder.seayoo.com": [],
119
+ "finder.seayoo.internal": [],
120
+ "finder.dev.seayoo.com": [],
121
+ "finder.dev.seayoo.io": []
136
122
  };
137
- const FinderApiPaths = {
138
- deploy: "/service/deploy",
139
- inspect: "/inspect/supported/projects",
140
- upload: "/service/upload"
123
+ /** finder api path */
124
+ var FinderApiPaths = {
125
+ deploy: "/service/deploy",
126
+ inspect: "/inspect/supported/projects",
127
+ upload: "/service/upload"
141
128
  };
129
+ /** 将指定的 zip buffer 部署到指定目录 */
142
130
  async function deploy(option) {
143
- const { debug, target, buffer, user, key, payload, ignoreCache } = option;
144
- const targetServer = await findTargetServer(target, debug, ignoreCache);
145
- if (!targetServer) {
146
- throw `finder不支持该域名部署,请检查 ${target}`.bgRed;
147
- }
148
- if (!user || !key) {
149
- throw `部署缺少认证信息(user & key)`.bgRed;
150
- }
151
- const zipMockName = `${Date.now()}${Math.random().toString(16).slice(-3)}.zip`;
152
- const { status, data } = await request({
153
- url: `${getFinderServerFullPath(targetServer)}${FinderApiPaths.deploy}?target=${encodeURIComponent(pure(target))}`,
154
- method: "POST",
155
- headers: { user, key },
156
- data: {
157
- path: zipMockName,
158
- file: { buffer, filename: zipMockName, contentType: "application/octet-stream" },
159
- payload: payload ? JSON.stringify(payload) : ""
160
- }
161
- });
162
- if (status !== 200) {
163
- throw `部署接口错误,Server: ${targetServer},Status: ${status},Response: ${JSON.stringify(data)}`.red;
164
- }
165
- if (!data || typeof data !== "object" || "err" in data && data.err || !("data" in data) || typeof data.data !== "string") {
166
- throw `部署接口响应错误。Server: ${targetServer},Response: ${JSON.stringify(data)}`.red;
167
- }
168
- const url = data.data;
169
- if (debug) {
170
- console.log("部署完毕,接口返回内容", data);
171
- }
172
- return {
173
- previewUrl: url.endsWith("/") ? url.replace(/\/*$/, "/") + "index.html?" + Math.random().toString(16).slice(2) : url.startsWith("http") ? url : ""
174
- };
131
+ const { debug, target, buffer, user, key, payload, ignoreCache } = option;
132
+ const targetServer = await findTargetServer(target, debug, ignoreCache);
133
+ if (!targetServer) throw colors.bgRed(`finder不支持该域名部署,请检查 ${target}`);
134
+ if (!user || !key) throw colors.bgRed("部署缺少认证信息(user & key)");
135
+ const zipMockName = `${Date.now()}${Math.random().toString(16).slice(-3)}.zip`;
136
+ const { status, data } = await request({
137
+ url: `${getFinderServerFullPath(targetServer)}${FinderApiPaths.deploy}?target=${encodeURIComponent(pure(target))}`,
138
+ method: "POST",
139
+ headers: {
140
+ user,
141
+ key
142
+ },
143
+ data: {
144
+ path: zipMockName,
145
+ file: {
146
+ buffer,
147
+ filename: zipMockName,
148
+ contentType: "application/octet-stream"
149
+ },
150
+ payload: payload ? JSON.stringify(payload) : ""
151
+ }
152
+ });
153
+ if (status !== 200) throw colors.bgRed(`部署接口错误,Server: ${targetServer},Status: ${status},Response: ${JSON.stringify(data)}`);
154
+ if (!data || typeof data !== "object" || "err" in data && data.err || !("data" in data) || typeof data.data !== "string") throw colors.bgRed(`部署接口响应错误。Server: ${targetServer},Response: ${JSON.stringify(data)}`);
155
+ const url = data.data;
156
+ if (debug) console.log("部署完毕,接口返回内容", data);
157
+ return { previewUrl: url.endsWith("/") ? url.replace(/\/*$/, "/") + "index.html?" + Math.random().toString(16).slice(2) : url.startsWith("http") ? url : "" };
175
158
  }
159
+ /** 将文件上传到指定位置 */
176
160
  async function upload(option) {
177
- const { debug, target, buffer, user, key, ignoreCache } = option;
178
- const targetServer = await findTargetServer(target, debug, ignoreCache);
179
- if (!targetServer) {
180
- throw `finder不支持该域名部署,请检查 ${target}`.bgRed;
181
- }
182
- if (!user || !key) {
183
- throw `部署缺少认证信息(user & key)`.bgRed;
184
- }
185
- const filename = basename(target);
186
- const deployTarget = dirname(pure(target));
187
- const { status, data } = await request({
188
- url: `${getFinderServerFullPath(targetServer)}${FinderApiPaths.upload}?target=${encodeURIComponent(deployTarget)}`,
189
- method: "POST",
190
- headers: { user, key },
191
- data: {
192
- path: filename,
193
- file: { buffer, filename, contentType: "application/octet-stream" }
194
- }
195
- });
196
- if (status !== 200) {
197
- throw `上传接口错误,Server: ${targetServer},Status: ${status}`.red;
198
- }
199
- if (!data || typeof data !== "object" || "err" in data && data.err || !("data" in data) || typeof data.data !== "string") {
200
- throw `上传接口响应错误,Server: ${targetServer},Response: ${JSON.stringify(data)}`.red;
201
- }
202
- return { previewUrl: `https://${pure(target)}` };
161
+ const { debug, target, buffer, user, key, ignoreCache } = option;
162
+ const targetServer = await findTargetServer(target, debug, ignoreCache);
163
+ if (!targetServer) throw colors.bgRed(`finder不支持该域名部署,请检查 ${target}`);
164
+ if (!user || !key) throw colors.bgRed("部署缺少认证信息(user & key)");
165
+ const filename = basename(target);
166
+ const deployTarget = dirname(pure(target));
167
+ const { status, data } = await request({
168
+ url: `${getFinderServerFullPath(targetServer)}${FinderApiPaths.upload}?target=${encodeURIComponent(deployTarget)}`,
169
+ method: "POST",
170
+ headers: {
171
+ user,
172
+ key
173
+ },
174
+ data: {
175
+ path: filename,
176
+ file: {
177
+ buffer,
178
+ filename,
179
+ contentType: "application/octet-stream"
180
+ }
181
+ }
182
+ });
183
+ if (status !== 200) throw colors.bgRed(`上传接口错误,Server: ${targetServer},Status: ${status}`);
184
+ if (!data || typeof data !== "object" || "err" in data && data.err || !("data" in data) || typeof data.data !== "string") throw colors.bgRed(`上传接口响应错误,Server: ${targetServer},Response: ${JSON.stringify(data)}`);
185
+ return { previewUrl: `https://${pure(target)}` };
203
186
  }
204
- const getFinderServerFullPath = function(domain) {
205
- return (domain.endsWith("internal") ? "http://" : "https://") + domain;
187
+ var getFinderServerFullPath = function(domain) {
188
+ return (domain.endsWith("internal") ? "http://" : "https://") + domain;
206
189
  };
207
190
  async function findTargetServer(target, debug, ignoreCache) {
208
- const t = pure(target);
209
- await updateSupportedProjects(!!ignoreCache, debug);
210
- for (const domain in FinderServers) {
211
- if (FinderServers[domain].find((url) => t.startsWith(url))) {
212
- return domain;
213
- }
214
- }
215
- if (!ignoreCache) {
216
- await updateSupportedProjects(true, debug);
217
- for (const domain in FinderServers) {
218
- if (FinderServers[domain].find((url) => t.startsWith(url))) {
219
- return domain;
220
- }
221
- }
222
- }
223
- return null;
191
+ const t = pure(target);
192
+ await updateSupportedProjects(!!ignoreCache, debug);
193
+ for (const domain in FinderServers) if (FinderServers[domain].find((url) => t.startsWith(url))) return domain;
194
+ if (!ignoreCache) {
195
+ await updateSupportedProjects(true, debug);
196
+ for (const domain in FinderServers) if (FinderServers[domain].find((url) => t.startsWith(url))) return domain;
197
+ }
198
+ return null;
224
199
  }
225
200
  async function updateSupportedProjects(force = false, debug) {
226
- const domains = Object.keys(FinderServers);
227
- for (const domain of domains) {
228
- FinderServers[domain] = await getServerSupportedProjects(domain, force, debug) || [];
229
- }
201
+ const domains = Object.keys(FinderServers);
202
+ await Promise.all(domains.map((domain) => getServerSupportedProjects(domain, force, debug).then((r) => FinderServers[domain] = r, () => FinderServers[domain] = [])));
230
203
  }
231
204
  async function getServerSupportedProjects(serverDomain, ignoreCache = false, debug) {
232
- const cacheFile = resolve(getSystemTempDir(), `${serverDomain}.json`);
233
- if (existsSync(cacheFile) && !ignoreCache) {
234
- try {
235
- const cache = JSON.parse(readFileSync(cacheFile).toString());
236
- if (Array.isArray(cache) && cache.every((d) => typeof d === "string")) {
237
- if (debug) {
238
- console.log({ method: "getServerSupportedProjects", serverDomain, cache });
239
- }
240
- return cache;
241
- }
242
- } catch (e) {
243
- console.error("ReadFinderCacheError", e);
244
- }
245
- }
246
- const inspectURL = `${getFinderServerFullPath(serverDomain)}${FinderApiPaths.inspect}`;
247
- const { status, message, data } = await request({
248
- url: inspectURL,
249
- method: "GET",
250
- headers: { "user-agent": `web finder agent v2` }
251
- });
252
- if (status !== 200) {
253
- if (debug) {
254
- console.error(`服务器 ${inspectURL} 检查接口错误`.bgRed, (message || "").red);
255
- }
256
- return [];
257
- }
258
- if (!Array.isArray(data) || !data.every((d) => typeof d === "string")) {
259
- console.error(`服务器 ${inspectURL} 接口返回内容错误`.bgRed, JSON.stringify(data).red);
260
- return [];
261
- }
262
- if (debug) {
263
- console.log({ method: "getServerSupportedProjects", serverDomain, list: data });
264
- }
265
- const pureList = data.map(pure);
266
- writeFileSync(cacheFile, JSON.stringify(pureList));
267
- return pureList;
205
+ const cacheFile = resolve(getSystemTempDir(), `${serverDomain}.json`);
206
+ if (existsSync(cacheFile) && !ignoreCache) try {
207
+ const cache = JSON.parse(readFileSync(cacheFile).toString());
208
+ if (Array.isArray(cache) && cache.every((d) => typeof d === "string")) {
209
+ if (debug) console.log({
210
+ method: "getServerSupportedProjects",
211
+ serverDomain,
212
+ cache
213
+ });
214
+ return cache;
215
+ }
216
+ } catch (e) {
217
+ console.error(colors.bgRed("ReadFinderCacheError"), e);
218
+ }
219
+ const inspectURL = `${getFinderServerFullPath(serverDomain)}${FinderApiPaths.inspect}`;
220
+ const { status, message, data } = await request({
221
+ url: inspectURL,
222
+ method: "GET",
223
+ headers: { "user-agent": `web finder agent v2` }
224
+ });
225
+ if (status !== 200) {
226
+ if (debug) console.error(colors.bgRed(`服务器 ${inspectURL} 检查接口错误`), colors.red(message || ""));
227
+ return [];
228
+ }
229
+ if (!Array.isArray(data) || !data.every((d) => typeof d === "string")) {
230
+ console.error(colors.bgRed(`服务器 ${inspectURL} 接口返回内容错误`), colors.red(JSON.stringify(data)));
231
+ return [];
232
+ }
233
+ if (debug) console.log({
234
+ method: "getServerSupportedProjects",
235
+ serverDomain,
236
+ list: data
237
+ });
238
+ const pureList = data.map(pure);
239
+ writeFileSync(cacheFile, JSON.stringify(pureList));
240
+ return pureList;
268
241
  }
242
+ //#endregion
243
+ //#region src/core.ts
244
+ /** 部署一个目录 */
269
245
  async function finderDeploy(option) {
270
- const { dist, ignoreFiles, deployTo, user, key, debug, preview, commitLogs, ignoreCache } = option;
271
- if (!dist) {
272
- throw "部署参数 dist 缺失".bgRed;
273
- }
274
- if (!existsSync(resolve(dist)) || !lstatSync(resolve(dist)).isDirectory()) {
275
- throw "部署参数错误,dist 需要是一个存在的文件目录".bgRed + " " + dist.red;
276
- }
277
- const payload = commitLogs ? { 更新内容: commitLogs } : void 0;
278
- if (debug) {
279
- console.log({
280
- method: "finderDeploy",
281
- dist,
282
- deployTo,
283
- ignoreFiles,
284
- payload,
285
- user,
286
- preview
287
- });
288
- }
289
- const buffer = await compressToBuffer(dist, ignoreFiles, debug).catch((e) => {
290
- throw "部署预处理之压缩代码失败".bgRed + " " + (e instanceof Error ? e.message : String(e));
291
- });
292
- if (Array.isArray(deployTo)) {
293
- const results = await Promise.all(
294
- deployTo.map((target) => {
295
- return deploy({ debug, target, buffer, user, key, payload, ignoreCache });
296
- })
297
- );
298
- const lastDeployResult = results[results.length - 1];
299
- if (lastDeployResult && lastDeployResult.previewUrl) {
300
- doPreview(lastDeployResult.previewUrl, preview);
301
- }
302
- return deployTo.join(",");
303
- }
304
- const deployResult = await deploy({ debug, target: deployTo, buffer, user, key, payload, ignoreCache });
305
- if (deployResult && deployResult.previewUrl) {
306
- doPreview(deployResult.previewUrl, preview);
307
- }
308
- return deployTo;
246
+ const { dist, ignoreFiles, deployTo, user, key, debug, preview, commitLogs, ignoreCache } = option;
247
+ if (!dist) throw colors.bgRed("部署参数 dist 缺失");
248
+ if (!existsSync(resolve(dist)) || !lstatSync(resolve(dist)).isDirectory()) throw colors.bgRed("部署参数错误,dist 需要是一个存在的文件目录") + " " + colors.red(dist);
249
+ const payload = commitLogs ? { 更新内容: commitLogs } : void 0;
250
+ if (debug) console.log({
251
+ method: "finderDeploy",
252
+ dist,
253
+ deployTo,
254
+ ignoreFiles,
255
+ payload,
256
+ user,
257
+ preview
258
+ });
259
+ const buffer = await compressToBuffer(dist, ignoreFiles, debug).catch((e) => {
260
+ throw colors.bgRed("部署预处理之压缩代码失败") + " " + (e instanceof Error ? e.message : String(e));
261
+ });
262
+ if (Array.isArray(deployTo)) {
263
+ const results = await Promise.all(deployTo.map((target) => {
264
+ return deploy({
265
+ debug,
266
+ target,
267
+ buffer,
268
+ user,
269
+ key,
270
+ payload,
271
+ ignoreCache
272
+ });
273
+ }));
274
+ const lastDeployResult = results[results.length - 1];
275
+ if (lastDeployResult && lastDeployResult.previewUrl) doPreview(lastDeployResult.previewUrl, preview);
276
+ return deployTo.join(",");
277
+ }
278
+ const deployResult = await deploy({
279
+ debug,
280
+ target: deployTo,
281
+ buffer,
282
+ user,
283
+ key,
284
+ payload,
285
+ ignoreCache
286
+ });
287
+ if (deployResult && deployResult.previewUrl) doPreview(deployResult.previewUrl, preview);
288
+ return deployTo;
309
289
  }
310
290
  function doPreview(defaultPreviewUrl, option) {
311
- if (!option) {
312
- return;
313
- }
314
- if (option === true) {
315
- open(defaultPreviewUrl);
316
- return;
317
- }
318
- const base = defaultPreviewUrl.replace(/index\.html.*$/i, "");
319
- const files = Array.isArray(option) ? option : [option];
320
- files.forEach((file) => {
321
- open(base + file);
322
- });
291
+ if (!option) return;
292
+ if (option === true) {
293
+ open(defaultPreviewUrl);
294
+ return;
295
+ }
296
+ const base = defaultPreviewUrl.replace(/index\.html.*$/i, "");
297
+ (Array.isArray(option) ? option : [option]).forEach((file) => {
298
+ open(base + file);
299
+ });
323
300
  }
301
+ /** 上传一个文件到 finder */
324
302
  async function finderUpload(option) {
325
- const { filePath, fileContent, deployTo, user, key, preview, debug, ignoreCache } = option;
326
- if (!filePath && !fileContent) {
327
- throw `部署缺少参数 filePath(文件全路径) fileContent(文件内容)`.bgRed;
328
- }
329
- if (filePath && !existsSync(filePath)) {
330
- throw `部署文件不存在(请确保传入完整文件路径)`.bgRed + " " + filePath;
331
- }
332
- if (!deployTo) {
333
- throw `部署缺少参数 deployTo(部署目标)`.bgRed;
334
- }
335
- const content = filePath ? Buffer.from(readFileSync(filePath)) : Buffer.isBuffer(fileContent) ? fileContent : Buffer.from(fileContent || "");
336
- const resp = await upload({ debug, target: pure(deployTo), buffer: content, user, key, ignoreCache });
337
- if (preview && resp.previewUrl) {
338
- open(resp.previewUrl);
339
- }
303
+ const { filePath, fileContent, deployTo, user, key, preview, debug, ignoreCache } = option;
304
+ if (!filePath && !fileContent) throw colors.bgRed("部署缺少参数 filePath(文件全路径) 或 fileContent(文件内容)");
305
+ if (filePath && !existsSync(filePath)) throw colors.bgRed("部署文件不存在(请确保传入完整文件路径)") + " " + colors.red(filePath);
306
+ if (!deployTo) throw colors.bgRed("部署缺少参数 deployTo(部署目标)");
307
+ const content = filePath ? Buffer.from(readFileSync(filePath)) : Buffer.isBuffer(fileContent) ? fileContent : Buffer.from(fileContent || "");
308
+ const resp = await upload({
309
+ debug,
310
+ target: pure(deployTo),
311
+ buffer: content,
312
+ user,
313
+ key,
314
+ ignoreCache
315
+ });
316
+ if (preview && resp.previewUrl) open(resp.previewUrl);
340
317
  }
318
+ //#endregion
319
+ //#region src/plugin.ts
341
320
  function viteDeployPlugin(option) {
342
- let distDir = null;
343
- return {
344
- name: "finerDeployAgent",
345
- generateBundle({ dir }) {
346
- distDir = process.cwd();
347
- if (dir) {
348
- distDir = resolve(distDir, dir);
349
- }
350
- },
351
- async closeBundle() {
352
- if (!distDir) {
353
- console.error("没有找到部署资源,请尝试检查 build 是否生成了正确的资源".bgRed);
354
- return;
355
- }
356
- await option.onBeforeDeploy?.(distDir);
357
- const result = await finderDeploy({
358
- preview: true,
359
- ...option,
360
- dist: distDir
361
- }).catch((e) => e instanceof Error ? e : typeof e === "string" ? new Error(e) : new Error(e + ""));
362
- if (result instanceof Error) {
363
- option.onError?.();
364
- console.log("部署失败".bgRed, result.message);
365
- } else {
366
- option.onFinished?.();
367
- console.log("部署成功".bgGreen, (result || "").green);
368
- }
369
- }
370
- };
321
+ let distDir = null;
322
+ return {
323
+ name: "finerDeployAgent",
324
+ generateBundle({ dir }) {
325
+ distDir = process.cwd();
326
+ if (dir) distDir = resolve(distDir, dir);
327
+ },
328
+ async closeBundle() {
329
+ if (!distDir) {
330
+ console.error(colors.bgRed("没有找到部署资源,请尝试检查 build 是否生成了正确的资源"));
331
+ return;
332
+ }
333
+ await option.onBeforeDeploy?.(distDir);
334
+ const result = await finderDeploy({
335
+ preview: true,
336
+ ...option,
337
+ dist: distDir
338
+ }).catch((e) => e instanceof Error ? e : typeof e === "string" ? new Error(e) : /* @__PURE__ */ new Error(e + ""));
339
+ if (result instanceof Error) {
340
+ option.onError?.();
341
+ console.log(colors.bgRed("部署失败"), colors.red(result.message));
342
+ } else {
343
+ option.onFinished?.();
344
+ console.log(colors.bgGreen("部署成功"), colors.green(result || ""));
345
+ }
346
+ }
347
+ };
371
348
  }
372
- export {
373
- finderDeploy,
374
- finderUpload,
375
- viteDeployPlugin
376
- };
349
+ //#endregion
350
+ export { finderDeploy, finderUpload, viteDeployPlugin };
package/package.json CHANGED
@@ -1,34 +1,34 @@
1
1
  {
2
2
  "name": "@seayoo-web/finder",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
4
4
  "description": "agent for web finder",
5
- "type": "module",
5
+ "license": "MIT",
6
+ "author": "web@seayoo.com",
6
7
  "source": "index.ts",
7
- "main": "./dist/index.js",
8
- "module": "./dist/index.js",
9
- "types": "./types/index.d.ts",
10
8
  "files": [
11
9
  "dist",
12
10
  "types",
13
11
  "README.md"
14
12
  ],
15
- "engines": {
16
- "node": ">=22"
17
- },
18
- "author": "web@seayoo.com",
19
- "license": "MIT",
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "module": "./dist/index.js",
16
+ "types": "./types/index.d.ts",
20
17
  "publishConfig": {
21
18
  "access": "public"
22
19
  },
23
20
  "dependencies": {
24
- "colors": "^1.4.0",
25
21
  "compressing": "^1.10.1",
26
- "open": "^10.1.0"
22
+ "open": "^10.1.0",
23
+ "picocolors": "^1.1.1"
27
24
  },
28
25
  "devDependencies": {
29
26
  "@types/node": "^22.13.1",
30
- "vitest": "^3.0.5",
31
- "@seayoo-web/tsconfig": "^1.0.5"
27
+ "vitest": "^4.1.4",
28
+ "@seayoo-web/tsconfig": "^1.0.6"
29
+ },
30
+ "engines": {
31
+ "node": ">=22"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "vite build && tsc --emitDeclarationOnly",
@@ -1,4 +1,3 @@
1
- import "colors";
2
1
  /** 部署一个目录 */
3
2
  export declare function finderDeploy(option: {
4
3
  /** 需要推送的代码目录 */