xshell 1.0.9 → 1.0.11
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/file.d.ts +25 -2
- package/file.js +55 -3
- package/file.js.map +1 -1
- package/net.browser.d.ts +14 -0
- package/net.browser.js +57 -10
- package/net.browser.js.map +1 -1
- package/net.d.ts +18 -2
- package/net.js +11 -5
- package/net.js.map +1 -1
- package/package.json +9 -7
- package/utils.browser.d.ts +5 -0
- package/utils.browser.js +12 -1
- package/utils.browser.js.map +1 -1
- package/utils.d.ts +18 -3
- package/utils.js +36 -6
- package/utils.js.map +1 -1
package/file.d.ts
CHANGED
|
@@ -115,8 +115,8 @@ export declare function fdelete(fp: string, { print }?: {
|
|
|
115
115
|
- fp_src: 源 文件/文件夹 完整路径 src file/directory absolute path
|
|
116
116
|
- fp_dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path
|
|
117
117
|
- options?:
|
|
118
|
-
print?: `true`
|
|
119
|
-
overwrite?: `true`
|
|
118
|
+
- print?: `true`
|
|
119
|
+
- overwrite?: `true`
|
|
120
120
|
|
|
121
121
|
@example
|
|
122
122
|
fcopy('d:/temp/camera/', 'd:/camera/') */
|
|
@@ -165,6 +165,29 @@ export declare function flink(fp_real: string, fp_link: string, { junction, prin
|
|
|
165
165
|
junction?: boolean;
|
|
166
166
|
print?: boolean;
|
|
167
167
|
}): Promise<void>;
|
|
168
|
+
export interface ZipOptions {
|
|
169
|
+
dirname?: string;
|
|
170
|
+
print?: {
|
|
171
|
+
info: boolean;
|
|
172
|
+
files: boolean;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** 将文件夹压缩为 zip
|
|
176
|
+
- data:
|
|
177
|
+
- 被压缩文件夹路径 (fpd_src: string) 或
|
|
178
|
+
- 文件索引对象 (entries: Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Buffer)>)
|
|
179
|
+
- fp_zip?:
|
|
180
|
+
- 传压缩包完整路径时压缩到文件, 函数返回值为 Promise<zip 路径>
|
|
181
|
+
- 传 undefined 时压缩到内存, 函数返回值为 Promise<zip buffer>
|
|
182
|
+
- options?:
|
|
183
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字,如 'web', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
184
|
+
- print?:
|
|
185
|
+
- info?: `true` 开始压缩、压缩完成
|
|
186
|
+
- files?: `true` 打印压缩文件列表 */
|
|
187
|
+
export declare function fzip(entries: Record<string, string | Buffer>, fp_zip?: undefined, options?: ZipOptions): Promise<Buffer>;
|
|
188
|
+
export declare function fzip(entries: Record<string, string | Buffer>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
189
|
+
export declare function fzip(fpd_src: string, fp_zip?: undefined, options?: ZipOptions): Promise<Buffer>;
|
|
190
|
+
export declare function fzip(fpd_src: string, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
168
191
|
export declare let fwatchers: Record<string, fs.FSWatcher>;
|
|
169
192
|
/**
|
|
170
193
|
- fp: 文件或文件夹路径 path of file or directory
|
package/file.js
CHANGED
|
@@ -2,11 +2,12 @@ import { promises as fsp, default as fs, } from 'fs';
|
|
|
2
2
|
import path from 'upath';
|
|
3
3
|
import iconv from 'iconv-lite';
|
|
4
4
|
import fse from 'fs-extra';
|
|
5
|
+
import archiver from 'archiver';
|
|
5
6
|
import debounce from 'lodash/debounce.js';
|
|
6
7
|
import MFS from 'memfs';
|
|
7
8
|
import { t } from './i18n/instance.js';
|
|
8
9
|
import { to_json } from './prototype.js';
|
|
9
|
-
import { assert } from './utils.js';
|
|
10
|
+
import { assert, WritableMemoryStream } from './utils.js';
|
|
10
11
|
export * from './ufs.js';
|
|
11
12
|
export { MFS };
|
|
12
13
|
/** fp 所指向的 文件/ 文件夹 是否存在
|
|
@@ -188,8 +189,8 @@ export async function fdelete(fp, { print = true } = {}) {
|
|
|
188
189
|
- fp_src: 源 文件/文件夹 完整路径 src file/directory absolute path
|
|
189
190
|
- fp_dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path
|
|
190
191
|
- options?:
|
|
191
|
-
print?: `true`
|
|
192
|
-
overwrite?: `true`
|
|
192
|
+
- print?: `true`
|
|
193
|
+
- overwrite?: `true`
|
|
193
194
|
|
|
194
195
|
@example
|
|
195
196
|
fcopy('d:/temp/camera/', 'd:/camera/') */
|
|
@@ -272,6 +273,57 @@ export async function flink(fp_real, fp_link, { junction = false, print = true }
|
|
|
272
273
|
else
|
|
273
274
|
fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file');
|
|
274
275
|
}
|
|
276
|
+
export async function fzip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
277
|
+
let entries;
|
|
278
|
+
let fpd_src;
|
|
279
|
+
if (typeof data === 'string') {
|
|
280
|
+
if (!path.isAbsolute(data) || !data.endsWith('/'))
|
|
281
|
+
throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
|
|
282
|
+
fpd_src = data;
|
|
283
|
+
if (dirname === undefined)
|
|
284
|
+
dirname = fpd_src.fname;
|
|
285
|
+
entries = Object.fromEntries((await flist(fpd_src, { print: false }))
|
|
286
|
+
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
287
|
+
}
|
|
288
|
+
else
|
|
289
|
+
entries = data;
|
|
290
|
+
if (print.info)
|
|
291
|
+
console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} → ${fp_zip ? `${fp_zip}/${dirname}` : '内存'}`);
|
|
292
|
+
let archive = archiver('zip');
|
|
293
|
+
let ostream = fp_zip ? fs.createWriteStream(fp_zip) : new WritableMemoryStream();
|
|
294
|
+
const size = await new Promise((resolve, reject) => {
|
|
295
|
+
ostream.once('close', () => {
|
|
296
|
+
resolve(archive.pointer());
|
|
297
|
+
});
|
|
298
|
+
archive.once('error', reject);
|
|
299
|
+
archive.on('warning', error => {
|
|
300
|
+
console.log(error);
|
|
301
|
+
});
|
|
302
|
+
archive.pipe(ostream);
|
|
303
|
+
for (const fp in entries) {
|
|
304
|
+
const fdata = entries[fp];
|
|
305
|
+
if (fdata instanceof Buffer) {
|
|
306
|
+
if (print.files)
|
|
307
|
+
console.log(`压缩 ${fdata.length.to_fsize_str()} → ${fp}`);
|
|
308
|
+
archive.append(fdata, { name: fp });
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
assert(fp.endsWith('/') === fdata.endsWith('/'));
|
|
312
|
+
assert(path.isAbsolute(fdata));
|
|
313
|
+
if (print.files)
|
|
314
|
+
console.log(`压缩 ${fdata} → ${fp}`);
|
|
315
|
+
if (fp.endsWith('/'))
|
|
316
|
+
archive.directory(fdata, fp);
|
|
317
|
+
else
|
|
318
|
+
archive.file(fdata, { name: fp });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
archive.finalize();
|
|
322
|
+
});
|
|
323
|
+
if (print.info)
|
|
324
|
+
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
325
|
+
return fp_zip || ostream.pbuffer;
|
|
326
|
+
}
|
|
275
327
|
export let fwatchers = {};
|
|
276
328
|
/**
|
|
277
329
|
- fp: 文件或文件夹路径 path of file or directory
|
package/file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,QAAQ,IAAI,GAAG,EACf,OAAO,IAAI,EAAE,GAChB,MAAM,IAAI,CAAA;AAGX,OAAO,IAAI,MAAM,OAAO,CAAA;AACxB,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,GAAG,MAAM,UAAU,CAAA;AAE1B,OAAO,QAAQ,MAAM,oBAAoB,CAAA;AAGzC,OAAO,GAAG,MAAM,OAAO,CAAA;AASvB,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGnC,cAAc,UAAU,CAAA;AAExB,OAAO,EAAE,GAAG,EAAE,CAAA;AAKd;oDACoD;AACpD,MAAM,UAAU,OAAO,CAAE,EAAU,EAAE,EAAE,KAAK,GAAG,IAAI,KAA0B,EAAG;IAC5E,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAEhC,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAA;IAEjD,OAAO,MAAM,CAAA;AACjB,CAAC;AAGD;;;;;;;;qGAQqG;AACrG,MAAM,CAAC,KAAK,UAAU,KAAK,CACvB,EAAU,EACV,KAAsB,EACtB,EAAE,IAAI,EAAE,KAAK,KAA0C,EAAG;IAE1D,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IAE9B,OAAO,MAAM,CAAC,MAAM,CAChB,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAC/B,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CACtB,CAAA;AACL,CAAC;AAGD,MAAM,UAAU,UAAU;IACtB,IAAI,GAAG,GAAG,GAAG,CAAC,kBAAkB,CAC5B,IAAI,GAAG,CAAC,MAAM,EAAE,CACnB,CAAA;IAED,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/B,GAAG,CAAC,MAAM,GAAG,IAAI,CAAA;IAEjB,OAAO,GAAG,CAAA;AACd,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,EAAU,EAAE,EACrC,GAAG,EACH,QAAQ,GAAG,OAAO,EAClB,KAAK,GAAG,IAAI,KAIQ,EAAG;IAEvB,IAAI,GAAG;QACH,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;SACtB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,EAAE,CAAC,CAAA;IAEtD,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAE5B,QAAQ,QAAQ,EAAE;QACd,KAAK,OAAO;YACR,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;QAElD,KAAK,QAAQ;YACT,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QAE3B,OAAO,CAAC,CAAC;YACL,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;YAErC,IAAI,QAAQ,KAAK,MAAM,EAAE;gBACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;gBAC1C,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAQ,CAAA;gBAChC,IAAI,KAAK;oBACL,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;aAC/D;YAED,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;SACxC;KACJ;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAE,EAAU,EAAE,UAA8F,EAAG;IAC5I,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;SAC5B,WAAW,EAAE,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAY,EAAU,EAAE,UAAkE,EAAG;IACzH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;AAC/C,CAAC;AAKD,MAAM,CAAC,KAAK,UAAU,MAAM,CACxB,EAAuB,EACvB,IAAS,EACT,EACI,GAAG,EACH,QAAQ,GAAG,OAAO,EAClB,KAAK,GAAG,IAAI,EACZ,KAAK,GAAG,KAAK,MAMb,EAAG;IAEP,MAAM,SAAS,GAAG,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAA;IAC5D,IAAI,SAAS,EAAE;QACX,IAAI,KAAK;YACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAG,EAAiB,CAAC,EAAE,CAAC,CAAA;KAClD;SAAM;QACH,IAAI,GAAG;YACH,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;aACtB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAY,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,EAAE,CAAC,CAAA;QAEtD,IAAI,KAAK;YACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;KAC/B;IAED,IAAI,QAAQ,KAAK,SAAS;QACtB,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAEvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAClD,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAExB,IAAI;QACA,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;KAChC;IAAC,OAAO,KAAK,EAAE;QACZ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS;YAC9C,MAAM,KAAK,CAAA;QAEf,MAAM,MAAM,CAAE,EAAa,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;KAChC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAE,EAAU,EAAE,IAAS,EAAE,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,KAAwC,EAAG;IAChH,IAAI,GAAG;QACH,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;SACtB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,EAAE,CAAC,CAAA;IAEtD,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAE5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAClD,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAA;IAEjD,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC;AA0BD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,GAAW,EAAE,UAAwB,EAAG;IACjE,MAAM,EACF,MAAM,EACN,IAAI,GAAG,KAAK,EACZ,QAAQ,GAAG,KAAK,EAChB,KAAK,GAAG,IAAI,EACZ,KAAK,GAAG,KAAK,EAChB,GAAG,OAAO,CAAA;IAEX,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IAExD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;IAEzD,4CAA4C;IAC5C,sFAAsF;IACtF,sEAAsE;IACtE,wBAAwB;IAExB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;IAEhF,MAAM,aAAa,GAAG,MAAM,YAAY,MAAM,CAAA;IAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,CAAA;IAEnD,IAAI,GAAG,GAAa,EAAG,CAAA;IAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACtB,MAAM,EAAE,GACJ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI;YACT,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAEnC,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,SAAQ;QAEZ,IAAI,SAAS,IAAI,CAAE,MAAmB,CAAC,EAAE,CAAC;YACtC,SAAQ;QAEZ,IAAI,KAAK;YACL,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAEnB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;KACf;IAED,IAAI,IAAI;QACJ,OAAO,CACH,MAAM,OAAO,CAAC,GAAG,CACb,GAAG,CAAC,GAAG,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACf,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACd;gBACI,EAAE;gBACF,GAAI,CAAC,MAAM,KAAK,CACZ,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,EACxB,OAAO,CACV,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC;aAC3C;YACL,CAAC;gBACG,EAAE,CAAC,CAAC,CACnB,CAAC,IAAI,EAAE,CAAA;SAER,IAAI,KAAK;QACL,OAAO,OAAO,CAAC,GAAG,CACd,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CACjD,CAAA;;QAED,OAAO,GAAG,CAAA;AACtB,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,EAAU;IACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhD,IAAI,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAC9C;IAAC,IAAY,CAAC,EAAE,GAAG,EAAE,CAAA;IAEtB,OAAO,IAAW,CAAA;AACtB,CAAC;AAGD;;;;;;+DAM+D;AAC/D,MAAM,CAAC,KAAK,UAAU,OAAO,CAAE,EAAU,EAAE,EAAE,KAAK,GAAG,IAAI,KAA0B,EAAG;IAClF,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IACvD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAE5C,IAAI;QACA,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrC,IAAI,KAAK;YACL,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;;gBAErC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QAC5C,OAAO,IAAI,CAAA;KACd;IAAC,OAAO,KAAK,EAAE;QACZ,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YACzB,IAAI,KAAK;gBACL,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAChB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAA;;oBAEhC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAA;YACvC,OAAO,KAAK,CAAA;SACf;QAED,MAAM,KAAK,CAAA;KACd;AACL,CAAC;AAGD;;;;;;;;6CAQ6C;AAC7C,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,MAAc,EAAE,MAAc,EAAE,EACzD,KAAK,GAAG,IAAI,EACZ,SAAS,GAAG,IAAI,MAIhB,EAAG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAA;IAC1F,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAA;IAExF,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;IAE7C,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;AACrE,CAAC;AAGD;;;;6CAI6C;AAC7C,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,GAAW,EAAE,GAAW,EAAE,EACnD,SAAS,GAAG,KAAK,EACjB,KAAK,GAAG,IAAI,KAIZ,EAAG;IACH,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAA;IAElD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAE3C,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAEvC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;AAC3C,CAAC;AAGD;;;;;;gFAMgF;AAChF,MAAM,CAAC,KAAK,UAAU,OAAO,CACzB,EAAU,EACV,GAAW,EACX,EACI,GAAG,EACH,KAAK,GAAG,IAAI,EACZ,SAAS,GAAG,IAAI,KAKhB,EAAG;IAEP,IAAI,GAAG,EAAE;QACL,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QACvB,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;KAC5B;SAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAE1C,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAEvC,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAA;IAEtC,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;AAC7B,CAAC;AAGD;;;;;;;6BAO6B;AAC7B,MAAM,CAAC,KAAK,UAAU,MAAM,CACxB,GAAW,EACX,EACI,KAAK,GAAG,IAAI,EACZ,IAAI,MAMJ,EAAG;IAEP,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,CAAA;IACtD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,GAAG,CAAC,CAAA;IAEpD,sHAAsH;IACtH,MAAM,IAAI,GAAG,CACT,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAClD,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAExB,IAAI,IAAI,EAAE;QACN,IAAI,KAAK;YACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAA;KACpC;SACG,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAA;IAErC,OAAO,IAAI,CAAA;AACf,CAAC;AAGD;;2DAE2D;AAC3D,MAAM,CAAC,KAAK,UAAU,KAAK,CACvB,OAAe,EACf,OAAe,EACf,EACI,QAAQ,GAAG,KAAK,EAChB,KAAK,GAAG,IAAI,KAIhB,EAAG;IACH,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAE7E,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IACzC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IAEzC,MAAM,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAA;IAE1E,IAAI,OAAO,CAAC,OAAO,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;IAEnG,IAAI,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAA;IAE7D,IAAI,QAAQ;QACR,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAA;;QAEzC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AACnE,CAAC;AAGD,MAAM,CAAC,IAAI,SAAS,GAAiC,EAAG,CAAA;AAExD;;;;;;;;;;;;;kJAakJ;AAClJ,MAAM,CAAC,KAAK,UAAU,MAAM,CACxB,EAAU,EACV,QAA+C,EAC/C,EAAE,IAAI,GAAG,IAAI,KAAyB,EAAG;IAEzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAEpC,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC,CAAA;IAC9B,IAAI,QAAQ;QACR,QAAQ,CAAC,KAAK,EAAE,CAAA;IAEpB,IAAI,IAAI;QACJ,MAAM,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,CAAA;IAEtC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;IAElC,MAAM,kBAAkB,GAAG,QAAQ,CAC/B,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACb,IAAI,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,GAAG;YAClC,OAAM;QACV,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAA;QAChD,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;IAC1C,CAAC,EACD,GAAG,EACH,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CACrC,CAAA;IAED,IAAI,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAA;IAC9C,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;IACF,OAAO,SAAS,CAAC,EAAE,CAAC,GAAG,OAAO,CAAA;AAClC,CAAC;AAGD,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAE,EAAU,EAAE,OAAwB,EAAE,WAAmB;IACrF,MAAM,MAAM,CACR,EAAE,EACF,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;SACZ,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CACxC,CAAA;AACL,CAAC;AAED;;;;gCAIgC;AAChC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAE,EAAU,EAAE,EACtC,MAAM,GAAG,IAAI,EACb,QAAQ,GAAG,MAAM,MAIjB,EAAG;IACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC1C,IAAI,MAAM,EAAE;QACR,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;QACjC,OAAM;KACT;IAED,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,UAAU,CAAC,EAAE,CAAA;IAC9E,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAChB,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IAE3B,MAAM,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AAC1B,CAAC","sourcesContent":["import {\n promises as fsp,\n default as fs,\n} from 'fs'\ntype FileHandle = fsp.FileHandle & { fp: string }\n\nimport path from 'upath'\nimport iconv from 'iconv-lite'\nimport fse from 'fs-extra'\n\nimport debounce from 'lodash/debounce.js'\n\n\nimport MFS from 'memfs'\ndeclare module 'memfs' {\n interface IFs {\n join: typeof path.join\n is_mfs: true\n }\n}\n\n\nimport { t } from './i18n/instance.js'\nimport { to_json } from './prototype.js'\nimport { assert } from './utils.js'\n\n\nexport * from './ufs.js'\n\nexport { MFS }\n\nexport type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | 'binary'\n\n\n/** fp 所指向的 文件/ 文件夹 是否存在 \n Does the file/folder pointed to by fp exist? */\nexport function fexists (fp: string, { print = true }: { print?: boolean } = { }) {\n const exists = fs.existsSync(fp)\n \n if (print)\n console.log(exists ? t('已存在') : t('不存在'), fp)\n \n return exists\n}\n\n\n/** 打开文件,返回 FileHandle \n open file, return FileHandle \n Some characters (`< > : \" / \\ | ? *`) are reserved under Windows as documented\n by [Naming Files, Paths, and Namespaces](https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file). Under NTFS, if the filename contains\n a colon, Node.js will open a file system stream, as described by [this MSDN page](https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams).\n \n - flags: `'r'`\n - options?:\n - mode?: `'0o666'` Sets the file mode (permission and sticky bits) if the file is created. */\nexport async function fopen (\n fp: string,\n flags: string | number,\n { mode, print }: { mode?: fs.Mode, print?: boolean } = { }\n) {\n if (print)\n console.log(t('打开文件'), fp)\n \n return Object.assign(\n await fsp.open(fp, flags, mode),\n { fp, flags, mode }\n )\n}\n\n\nexport function create_mfs () {\n let mfs = MFS.createFsFromVolume(\n new MFS.Volume()\n )\n \n mfs.join = path.join.bind(path)\n mfs.is_mfs = true\n \n return mfs\n}\n\n\nexport async function fread (fp: string): Promise<string>\nexport async function fread (fp: string, { dir, encoding, print }?: { dir?: string, encoding: 'binary', print?: boolean }): Promise<Buffer>\nexport async function fread (fp: string, { dir, encoding, print }?: { dir?: string, encoding?: Encoding | 'auto', print?: boolean }): Promise<string>\nexport async function fread (fp: string, {\n dir, \n encoding = 'utf-8', \n print = true\n}: {\n dir?: string\n encoding?: Encoding | 'auto'\n print?: boolean } = { }\n) {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('读取'), fp)\n \n switch (encoding) {\n case 'utf-8':\n return fsp.readFile(fp, { encoding: 'utf-8' })\n \n case 'binary':\n return fsp.readFile(fp)\n \n default: {\n const buffer = await fsp.readFile(fp)\n \n if (encoding === 'auto') {\n const { detect } = await import('chardet')\n encoding = detect(buffer) as any\n if (print)\n console.log(fp + t(' 的编码可能是 ') + encoding.toLowerCase())\n }\n \n return iconv.decode(buffer, encoding)\n }\n }\n}\n\nexport async function fread_lines (fp: string, options: { dir?: string, encoding?: Exclude<Encoding, 'binary'> | 'auto', print?: boolean } = { }) {\n return (await fread(fp, options))\n .split_lines()\n}\n\nexport async function fread_json <T = any> (fp: string, options: { dir?: string, encoding?: Encoding, print?: boolean } = { }): Promise<T> {\n return JSON.parse(await fread(fp, options))\n}\n\n\nexport async function fwrite (fp: string | FileHandle, data: Buffer, options?: { dir?: string, print?: boolean, mkdir?: boolean }): Promise<void>\nexport async function fwrite (fp: string | FileHandle, data: any, options?: { dir?: string, encoding?: Encoding, print?: boolean, mkdir?: boolean }): Promise<void>\nexport async function fwrite (\n fp: string | FileHandle,\n data: any,\n {\n dir,\n encoding = 'utf-8',\n print = true,\n mkdir = false,\n }: {\n dir?: string\n encoding?: Encoding\n print?: boolean\n mkdir?: boolean\n } = { }\n) {\n const is_handle = typeof fp === 'object' && fp && 'fd' in fp\n if (is_handle) {\n if (print)\n console.log(t('写入'), (fp as FileHandle).fp)\n } else {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp as string))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('写入'), fp)\n }\n \n if (encoding === 'gb18030')\n data = iconv.encode(data, encoding)\n \n if (!Buffer.isBuffer(data) && typeof data !== 'string')\n data = to_json(data)\n \n try {\n await fsp.writeFile(fp, data)\n } catch (error) {\n if (!mkdir || error.code !== 'ENOENT' || is_handle)\n throw error\n \n await fmkdir((fp as string).fdir)\n await fsp.writeFile(fp, data)\n }\n}\n\nexport async function fappend (fp: string, data: any, { dir, print = true }: { dir?: string, print?: boolean } = { }) {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('追加'), fp)\n \n if (!Buffer.isBuffer(data) && typeof data !== 'string')\n throw new Error(t('data 不是 Buffer 或 string'))\n \n await fsp.appendFile(fp, data)\n}\n\n\nexport type FStats = fs.BigIntStats & { fp: string }\n\nexport interface FListOptions {\n filter?: RegExp | ((fp: string) => any)\n deep?: boolean\n absolute?: boolean\n print?: boolean\n stats?: boolean\n}\n\n/**\n - fpd: 文件夹完整路径 absolute path of directory\n - options?:\n - deep?: `false` 递归遍历 recursively\n - absolute?: `false` 返回、打印完整路径而不是相对路径 Return, print full path instead of relative path\n - print?: `true`\n - filter?: `true` RegExp | (fp: string) => any 注意当 deep = true 时被 filter 过滤掉的目录及目录中的文件不会包含在结果中 \n Note that when deep = true, directories and files in directories that are filtered out by the filter will not be included in the results \n - stats?: `false` 启用后返回 FStats 列表, 不能和 deep 一起使用 \n Returns the FStats list when enabled, cannot be used with deep */\nexport async function flist (fpd: string): Promise<string[]>\nexport async function flist (fpd: string, options?: FListOptions & { stats: true }): Promise<FStats[]>\nexport async function flist (fpd: string, options?: FListOptions): Promise<string[]>\nexport async function flist (fpd: string, options: FListOptions = { }): Promise<string[] | FStats[]> {\n const {\n filter,\n deep = false,\n absolute = false,\n print = true,\n stats = false\n } = options\n \n if (!path.isAbsolute(fpd))\n throw new Error(t('参数 fpd: ') + fpd + t(' 必须是绝对路径'))\n \n if (!fpd.endsWith('/'))\n throw new Error(t('参数 fpd: ') + fpd + t(' 必须以 / 结尾'))\n \n // readdir withFileTypes 参数在底层有什么区别,速度上有什么差异\n // 都调用了 uv_fs_scandir, 且调用参数相同,仅仅是 Node.js 侧的回调不同 AfterScanDir / AfterScanDirWithTypes\n // 回调中通过 uv_fs_scandir_next 获取到每个条目的信息,而 uv_fs_scandir_next 中都会读取 type\n // 速度上:都在 0.2 ms 左右就可以完成\n \n const files = await fsp.readdir(fpd, { withFileTypes: true, encoding: 'utf-8' })\n \n const filter_regexp = filter instanceof RegExp\n const filter_fn = Boolean(filter && !filter_regexp)\n \n let fps: string[] = [ ]\n \n for (const file of files) {\n const fp = \n (absolute ? fpd : '') +\n file.name +\n (file.isDirectory() ? '/' : '')\n \n if (filter_regexp && !filter.test(fp))\n continue\n \n if (filter_fn && !(filter as Function)(fp))\n continue\n \n if (print)\n console.log(fp)\n \n fps.push(fp)\n }\n \n if (deep)\n return (\n await Promise.all(\n fps.map(async fp => \n fp.endsWith('/') ?\n [\n fp,\n ... (await flist(\n absolute ? fp : fpd + fp,\n options\n )).map(fp_ => absolute ? fp_ : fp + fp_)\n ]\n :\n fp))\n ).flat()\n else\n if (stats)\n return Promise.all(\n fps.map(fp => fstat(absolute ? fp : fpd + fp))\n )\n else\n return fps\n}\n\n\nexport async function fstat (fp: string): Promise<FStats> {\n if (!path.isAbsolute(fp))\n throw new Error('fp: ' + fp + t(' 必须是绝对路径'))\n \n let stat = await fsp.stat(fp, { bigint: true })\n ;(stat as any).fp = fp\n \n return stat as any\n}\n\n\n/** 删除文件或文件夹 delete files or folders \n - fp: 文件或文件夹的完整路径 The full path to the file or folder\n - options?:\n - print?: `true`\n \n 返回是否实际进行了删除操作 \n Returns whether the delete operation actually took place */\nexport async function fdelete (fp: string, { print = true }: { print?: boolean } = { }) {\n assert(fp.length >= 6, `fp: ${fp} ${t('不能太短,防止误删文件')}`)\n assert(path.isAbsolute(fp), t('fp 必须是绝对路径'))\n \n try {\n await fsp.rm(fp, { recursive: true })\n if (print)\n if (fp.endsWith('/'))\n console.log((t('删除了文件夹: ') + fp).red)\n else\n console.log((t('删除了文件: ') + fp).red)\n return true\n } catch (error) {\n if (error.code === 'ENOENT') {\n if (print)\n if (fp.endsWith('/'))\n console.log(t('文件夹已不存在: ') + fp)\n else\n console.log(t('文件已不存在: ') + fp)\n return false\n }\n \n throw error\n }\n}\n\n\n/** 复制文件或文件夹 copy file or direcotry\n - fp_src: 源 文件/文件夹 完整路径 src file/directory absolute path\n - fp_dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path\n - options?:\n print?: `true`\n overwrite?: `true`\n \n @example\n fcopy('d:/temp/camera/', 'd:/camera/') */\nexport async function fcopy (fp_src: string, fp_dst: string, {\n print = true,\n overwrite = true,\n}: {\n print?: boolean\n overwrite?: boolean\n} = { }) {\n assert(fp_src.endsWith('/') === fp_dst.endsWith('/'), t('fp_src 和 fp_dst 必须同为文件路径或文件夹路径'))\n assert(path.isAbsolute(fp_src) && path.isAbsolute(fp_dst), t('fp_src 和 fp_dst 必须为完整路径'))\n \n if (print)\n console.log(t('复制'), fp_src, '→', fp_dst)\n \n await fse.copy(fp_src, fp_dst, { overwrite, errorOnExist: true })\n}\n\n\n/** 移动文件或文件夹 move file or direcotry\n - src: 源 文件/文件夹 完整路径 src file/directory absolute path\n - dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path\n @example\n fmove('d:/temp/camera/', 'd:/camera/') */\nexport async function fmove (src: string, dst: string, {\n overwrite = false,\n print = true\n}: {\n overwrite?: boolean\n print?: boolean\n} = { }) {\n if (src.endsWith('/') !== dst.endsWith('/'))\n throw new Error(t('src 和 dst 必须同为文件路径或文件夹路径'))\n \n if (!path.isAbsolute(src) || !path.isAbsolute(dst))\n throw new Error(t('src 和 dst 必须为完整路径'))\n \n if (print)\n console.log(t('移动'), src, '→', dst)\n \n await fse.move(src, dst, { overwrite })\n}\n\n\n/** 重命名文件 rename file \n - fp: 当前文件名/路径 current filename/path\n - fp_: 新的文件名/路径 new filename/path\n - options?:\n - fpd?: fp 和 fp_ 在同一文件夹内 fp and fp_ is in same directory\n - print?: `true`\n - overwrite?: `true` 默认覆盖(不检查效率更高) better performance without check */\nexport async function frename (\n fp: string, \n fp_: string,\n {\n fpd,\n print = true,\n overwrite = true\n }: {\n fpd?: string\n print?: boolean\n overwrite?: boolean\n } = { }\n) {\n if (fpd) {\n fp = path.join(fpd, fp)\n fp_ = path.join(fpd, fp_)\n } else if (!path.isAbsolute(fp) || !path.isAbsolute(fp_))\n throw new Error(t('fp 和 fp_ 必须是绝对路径'))\n \n if (print)\n console.log(t('重命名'), fp, '→', fp_)\n \n if (!overwrite && fexists(fp_))\n throw new Error(t('文件已存在:') + fp_)\n \n await fsp.rename(fp, fp_)\n}\n\n\n/**\n 递归创建文件夹,确保 fpd 指向的文件夹存在 Create folders recursively, make sure the folder pointed to by fpd exists \n 返回首个创建的文件夹或 undefined Returns the first created folder or undefined\n \n - fpd: 文件夹完整路径 Folder full path\n - options?:\n - print?: `true`\n - mode?: `'0o777'` */\nexport async function fmkdir (\n fpd: string,\n {\n print = true,\n mode,\n }: {\n print?: boolean\n \n /** `0o777` A file mode. If a string is passed, it is parsed as an octal integer. */\n mode?: string | number\n } = { }\n) {\n assert(path.isAbsolute(fpd), t('fpd 必须是绝对路径: ') + fpd)\n assert(fpd.endsWith('/'), t('fpd 必须以 / 结尾: ') + fpd)\n \n // CallingfsPromises.mkdir() when path is a directory that exists results in a rejection only when recursive is false.\n const fpd_ = (\n await fsp.mkdir(fpd, { recursive: true, mode })\n )?.replaceAll('\\\\', '/')\n \n if (fpd_) {\n if (print)\n console.log(t('已创建文件夹'), fpd)\n } else\n if (print)\n console.log(t('已存在文件夹'), fpd)\n \n return fpd_\n}\n\n\n/** 创建软链接 Create soft links \n - fp_real: 现在真实文件/文件夹的路径 current real file/directory path\n - fp_link: 目标链接文件/文件夹的路径 target file/directory path */\nexport async function flink (\n fp_real: string, \n fp_link: string, \n {\n junction = false,\n print = true \n }: { \n junction?: boolean\n print?: boolean\n} = { }) {\n assert(path.isAbsolute(fp_real) && path.isAbsolute(fp_link), t('fp 必须是绝对路径'))\n \n const is_fpd_real = fp_real.endsWith('/')\n const is_fpd_link = fp_link.endsWith('/')\n \n assert(is_fpd_real === is_fpd_link, t('fp_real 和 fp_link 必须同为文件路径或文件夹路径'))\n \n if (fexists(fp_link))\n throw new Error(t('存在同名') + (is_fpd_link ? t('文件夹') : t('文件')) + ': ' + fp_link + t(',无法创建链接'))\n \n if (print)\n console.log(t('已将源文件 ') + fp_real + t(' 链接到 ') + fp_link)\n \n if (junction)\n fsp.symlink(fp_real, fp_link, 'junction')\n else\n fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file')\n}\n\n\nexport let fwatchers: Record<string, fs.FSWatcher> = { }\n\n/**\n - fp: 文件或文件夹路径 path of file or directory\n - callback: 文件修改时回调 called when modified\n - exec: `true` 首次 watch 时执行 onchange call callback when watch is executed\n \n 创建的 fs.FSWatcher 保存在 watchers 中, 再次调用相同的 fp 会自动关闭已有的 watcher \n save fs.FSWatcher in watchers, subsequent call will auto close existing watcher for the same fp\n \n https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fs_watch_filename_options_listener \n The listener callback gets two arguments (event, fname). \n event is either 'rename' or 'change', and filename is the name of the file which triggered the event.\n On most platforms, 'rename' is emitted whenever a filename appears or disappears in the directory.\n \n The listener callback is attached to the 'change' event fired by fs.FSWatcher, but it is not the same thing as the 'change' value of event. */\nexport async function fwatch (\n fp: string,\n onchange: (event: string, fname: string) => any, \n { exec = true }: { exec?: boolean } = { }\n) {\n if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是完整路径'))\n \n const _watcher = fwatchers[fp]\n if (_watcher)\n _watcher.close()\n \n if (exec)\n await onchange('change', fp.fname)\n \n const start = new Date().getTime()\n \n const debounced_onchange = debounce(\n (event, fname) => {\n if (new Date().getTime() - start < 800)\n return\n console.log(t('文件修改 (') + event + '): ' + fname)\n onchange(event, path.normalize(fname))\n },\n 500,\n { leading: false, trailing: true }\n )\n \n let watcher = fs.watch(fp, debounced_onchange)\n watcher.on('error', error => {\n console.error(error)\n })\n return fwatchers[fp] = watcher\n}\n\n\n/** 打开一个文件并搜索替换某个 pattern open a file and replace certain pattern */\nexport async function freplace (fp: string, pattern: string | RegExp, replacement: string) {\n await fwrite(\n fp,\n (await fread(fp))\n .replaceAll(pattern, replacement)\n )\n}\n\n/** 将文件编码转为 UTF-8 convert file encoding to UTF-8\n - fp: 文件完整路径 file absolute path\n - options?:\n - dryrun?: `true`\n - encoding?: `'auto'` */\nexport async function f2utf8 (fp: string, {\n dryrun = true,\n encoding = 'auto',\n}: {\n dryrun?: boolean\n encoding?: Encoding | 'auto'\n} = { }) {\n const text = await fread(fp, { encoding })\n if (dryrun) {\n console.log(text.slice(0, 10000))\n return\n }\n \n const fp_bak = `${fp.fdir}${fp.fname.replace(/(.*?)(\\.[^.]+)?$/, '$1.bak$2')}`\n if (!fexists(fp_bak))\n await fcopy(fp, fp_bak)\n \n await fwrite(fp, text)\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["file.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n promises as fsp,\n default as fs,\n} from 'fs'\ntype FileHandle = fsp.FileHandle & { fp: string }\n\nimport path from 'upath'\nimport iconv from 'iconv-lite'\nimport fse from 'fs-extra'\nimport archiver from 'archiver'\n\nimport debounce from 'lodash/debounce.js'\n\n\nimport MFS from 'memfs'\ndeclare module 'memfs' {\n interface IFs {\n join: typeof path.join\n is_mfs: true\n }\n}\n\n\nimport { t } from './i18n/instance.js'\nimport { to_json } from './prototype.js'\nimport { assert, WritableMemoryStream } from './utils.js'\n\n\nexport * from './ufs.js'\n\nexport { MFS }\n\nexport type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | 'binary'\n\n\n/** fp 所指向的 文件/ 文件夹 是否存在 \n Does the file/folder pointed to by fp exist? */\nexport function fexists (fp: string, { print = true }: { print?: boolean } = { }) {\n const exists = fs.existsSync(fp)\n \n if (print)\n console.log(exists ? t('已存在') : t('不存在'), fp)\n \n return exists\n}\n\n\n/** 打开文件,返回 FileHandle \n open file, return FileHandle \n Some characters (`< > : \" / \\ | ? *`) are reserved under Windows as documented\n by [Naming Files, Paths, and Namespaces](https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file). Under NTFS, if the filename contains\n a colon, Node.js will open a file system stream, as described by [this MSDN page](https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams).\n \n - flags: `'r'`\n - options?:\n - mode?: `'0o666'` Sets the file mode (permission and sticky bits) if the file is created. */\nexport async function fopen (\n fp: string,\n flags: string | number,\n { mode, print }: { mode?: fs.Mode, print?: boolean } = { }\n) {\n if (print)\n console.log(t('打开文件'), fp)\n \n return Object.assign(\n await fsp.open(fp, flags, mode),\n { fp, flags, mode }\n )\n}\n\n\nexport function create_mfs () {\n let mfs = MFS.createFsFromVolume(\n new MFS.Volume()\n )\n \n mfs.join = path.join.bind(path)\n mfs.is_mfs = true\n \n return mfs\n}\n\n\nexport async function fread (fp: string): Promise<string>\nexport async function fread (fp: string, { dir, encoding, print }?: { dir?: string, encoding: 'binary', print?: boolean }): Promise<Buffer>\nexport async function fread (fp: string, { dir, encoding, print }?: { dir?: string, encoding?: Encoding | 'auto', print?: boolean }): Promise<string>\nexport async function fread (fp: string, {\n dir, \n encoding = 'utf-8', \n print = true\n}: {\n dir?: string\n encoding?: Encoding | 'auto'\n print?: boolean } = { }\n) {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('读取'), fp)\n \n switch (encoding) {\n case 'utf-8':\n return fsp.readFile(fp, { encoding: 'utf-8' })\n \n case 'binary':\n return fsp.readFile(fp)\n \n default: {\n const buffer = await fsp.readFile(fp)\n \n if (encoding === 'auto') {\n const { detect } = await import('chardet')\n encoding = detect(buffer) as any\n if (print)\n console.log(fp + t(' 的编码可能是 ') + encoding.toLowerCase())\n }\n \n return iconv.decode(buffer, encoding)\n }\n }\n}\n\nexport async function fread_lines (fp: string, options: { dir?: string, encoding?: Exclude<Encoding, 'binary'> | 'auto', print?: boolean } = { }) {\n return (await fread(fp, options))\n .split_lines()\n}\n\nexport async function fread_json <T = any> (fp: string, options: { dir?: string, encoding?: Encoding, print?: boolean } = { }): Promise<T> {\n return JSON.parse(await fread(fp, options))\n}\n\n\nexport async function fwrite (fp: string | FileHandle, data: Buffer, options?: { dir?: string, print?: boolean, mkdir?: boolean }): Promise<void>\nexport async function fwrite (fp: string | FileHandle, data: any, options?: { dir?: string, encoding?: Encoding, print?: boolean, mkdir?: boolean }): Promise<void>\nexport async function fwrite (\n fp: string | FileHandle,\n data: any,\n {\n dir,\n encoding = 'utf-8',\n print = true,\n mkdir = false,\n }: {\n dir?: string\n encoding?: Encoding\n print?: boolean\n mkdir?: boolean\n } = { }\n) {\n const is_handle = typeof fp === 'object' && fp && 'fd' in fp\n if (is_handle) {\n if (print)\n console.log(t('写入'), (fp as FileHandle).fp)\n } else {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp as string))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('写入'), fp)\n }\n \n if (encoding === 'gb18030')\n data = iconv.encode(data, encoding)\n \n if (!Buffer.isBuffer(data) && typeof data !== 'string')\n data = to_json(data)\n \n try {\n await fsp.writeFile(fp, data)\n } catch (error) {\n if (!mkdir || error.code !== 'ENOENT' || is_handle)\n throw error\n \n await fmkdir((fp as string).fdir)\n await fsp.writeFile(fp, data)\n }\n}\n\nexport async function fappend (fp: string, data: any, { dir, print = true }: { dir?: string, print?: boolean } = { }) {\n if (dir)\n fp = path.join(dir, fp)\n else if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是绝对路径,或传入 dir 参数: ') + fp)\n \n if (print)\n console.log(t('追加'), fp)\n \n if (!Buffer.isBuffer(data) && typeof data !== 'string')\n throw new Error(t('data 不是 Buffer 或 string'))\n \n await fsp.appendFile(fp, data)\n}\n\n\nexport type FStats = fs.BigIntStats & { fp: string }\n\nexport interface FListOptions {\n filter?: RegExp | ((fp: string) => any)\n deep?: boolean\n absolute?: boolean\n print?: boolean\n stats?: boolean\n}\n\n/**\n - fpd: 文件夹完整路径 absolute path of directory\n - options?:\n - deep?: `false` 递归遍历 recursively\n - absolute?: `false` 返回、打印完整路径而不是相对路径 Return, print full path instead of relative path\n - print?: `true`\n - filter?: `true` RegExp | (fp: string) => any 注意当 deep = true 时被 filter 过滤掉的目录及目录中的文件不会包含在结果中 \n Note that when deep = true, directories and files in directories that are filtered out by the filter will not be included in the results \n - stats?: `false` 启用后返回 FStats 列表, 不能和 deep 一起使用 \n Returns the FStats list when enabled, cannot be used with deep */\nexport async function flist (fpd: string): Promise<string[]>\nexport async function flist (fpd: string, options?: FListOptions & { stats: true }): Promise<FStats[]>\nexport async function flist (fpd: string, options?: FListOptions): Promise<string[]>\nexport async function flist (fpd: string, options: FListOptions = { }): Promise<string[] | FStats[]> {\n const {\n filter,\n deep = false,\n absolute = false,\n print = true,\n stats = false\n } = options\n \n if (!path.isAbsolute(fpd))\n throw new Error(t('参数 fpd: ') + fpd + t(' 必须是绝对路径'))\n \n if (!fpd.endsWith('/'))\n throw new Error(t('参数 fpd: ') + fpd + t(' 必须以 / 结尾'))\n \n // readdir withFileTypes 参数在底层有什么区别,速度上有什么差异\n // 都调用了 uv_fs_scandir, 且调用参数相同,仅仅是 Node.js 侧的回调不同 AfterScanDir / AfterScanDirWithTypes\n // 回调中通过 uv_fs_scandir_next 获取到每个条目的信息,而 uv_fs_scandir_next 中都会读取 type\n // 速度上:都在 0.2 ms 左右就可以完成\n \n const files = await fsp.readdir(fpd, { withFileTypes: true, encoding: 'utf-8' })\n \n const filter_regexp = filter instanceof RegExp\n const filter_fn = Boolean(filter && !filter_regexp)\n \n let fps: string[] = [ ]\n \n for (const file of files) {\n const fp = \n (absolute ? fpd : '') +\n file.name +\n (file.isDirectory() ? '/' : '')\n \n if (filter_regexp && !filter.test(fp))\n continue\n \n if (filter_fn && !(filter as Function)(fp))\n continue\n \n if (print)\n console.log(fp)\n \n fps.push(fp)\n }\n \n if (deep)\n return (\n await Promise.all(\n fps.map(async fp => \n fp.endsWith('/') ?\n [\n fp,\n ... (await flist(\n absolute ? fp : fpd + fp,\n options\n )).map(fp_ => absolute ? fp_ : fp + fp_)\n ]\n :\n fp))\n ).flat()\n else\n if (stats)\n return Promise.all(\n fps.map(fp => fstat(absolute ? fp : fpd + fp))\n )\n else\n return fps\n}\n\n\nexport async function fstat (fp: string): Promise<FStats> {\n if (!path.isAbsolute(fp))\n throw new Error('fp: ' + fp + t(' 必须是绝对路径'))\n \n let stat = await fsp.stat(fp, { bigint: true })\n ;(stat as any).fp = fp\n \n return stat as any\n}\n\n\n/** 删除文件或文件夹 delete files or folders \n - fp: 文件或文件夹的完整路径 The full path to the file or folder\n - options?:\n - print?: `true`\n \n 返回是否实际进行了删除操作 \n Returns whether the delete operation actually took place */\nexport async function fdelete (fp: string, { print = true }: { print?: boolean } = { }) {\n assert(fp.length >= 6, `fp: ${fp} ${t('不能太短,防止误删文件')}`)\n assert(path.isAbsolute(fp), t('fp 必须是绝对路径'))\n \n try {\n await fsp.rm(fp, { recursive: true })\n if (print)\n if (fp.endsWith('/'))\n console.log((t('删除了文件夹: ') + fp).red)\n else\n console.log((t('删除了文件: ') + fp).red)\n return true\n } catch (error) {\n if (error.code === 'ENOENT') {\n if (print)\n if (fp.endsWith('/'))\n console.log(t('文件夹已不存在: ') + fp)\n else\n console.log(t('文件已不存在: ') + fp)\n return false\n }\n \n throw error\n }\n}\n\n\n/** 复制文件或文件夹 copy file or direcotry\n - fp_src: 源 文件/文件夹 完整路径 src file/directory absolute path\n - fp_dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path\n - options?:\n - print?: `true`\n - overwrite?: `true`\n \n @example\n fcopy('d:/temp/camera/', 'd:/camera/') */\nexport async function fcopy (fp_src: string, fp_dst: string, {\n print = true,\n overwrite = true,\n}: {\n print?: boolean\n overwrite?: boolean\n} = { }) {\n assert(fp_src.endsWith('/') === fp_dst.endsWith('/'), t('fp_src 和 fp_dst 必须同为文件路径或文件夹路径'))\n assert(path.isAbsolute(fp_src) && path.isAbsolute(fp_dst), t('fp_src 和 fp_dst 必须为完整路径'))\n \n if (print)\n console.log(t('复制'), fp_src, '→', fp_dst)\n \n await fse.copy(fp_src, fp_dst, { overwrite, errorOnExist: true })\n}\n\n\n/** 移动文件或文件夹 move file or direcotry\n - src: 源 文件/文件夹 完整路径 src file/directory absolute path\n - dst: 目标 文件/文件夹 完整路径 dst file/directory absolute path\n @example\n fmove('d:/temp/camera/', 'd:/camera/') */\nexport async function fmove (src: string, dst: string, {\n overwrite = false,\n print = true\n}: {\n overwrite?: boolean\n print?: boolean\n} = { }) {\n if (src.endsWith('/') !== dst.endsWith('/'))\n throw new Error(t('src 和 dst 必须同为文件路径或文件夹路径'))\n \n if (!path.isAbsolute(src) || !path.isAbsolute(dst))\n throw new Error(t('src 和 dst 必须为完整路径'))\n \n if (print)\n console.log(t('移动'), src, '→', dst)\n \n await fse.move(src, dst, { overwrite })\n}\n\n\n/** 重命名文件 rename file \n - fp: 当前文件名/路径 current filename/path\n - fp_: 新的文件名/路径 new filename/path\n - options?:\n - fpd?: fp 和 fp_ 在同一文件夹内 fp and fp_ is in same directory\n - print?: `true`\n - overwrite?: `true` 默认覆盖(不检查效率更高) better performance without check */\nexport async function frename (\n fp: string, \n fp_: string,\n {\n fpd,\n print = true,\n overwrite = true\n }: {\n fpd?: string\n print?: boolean\n overwrite?: boolean\n } = { }\n) {\n if (fpd) {\n fp = path.join(fpd, fp)\n fp_ = path.join(fpd, fp_)\n } else if (!path.isAbsolute(fp) || !path.isAbsolute(fp_))\n throw new Error(t('fp 和 fp_ 必须是绝对路径'))\n \n if (print)\n console.log(t('重命名'), fp, '→', fp_)\n \n if (!overwrite && fexists(fp_))\n throw new Error(t('文件已存在:') + fp_)\n \n await fsp.rename(fp, fp_)\n}\n\n\n/**\n 递归创建文件夹,确保 fpd 指向的文件夹存在 Create folders recursively, make sure the folder pointed to by fpd exists \n 返回首个创建的文件夹或 undefined Returns the first created folder or undefined\n \n - fpd: 文件夹完整路径 Folder full path\n - options?:\n - print?: `true`\n - mode?: `'0o777'` */\nexport async function fmkdir (\n fpd: string,\n {\n print = true,\n mode,\n }: {\n print?: boolean\n \n /** `0o777` A file mode. If a string is passed, it is parsed as an octal integer. */\n mode?: string | number\n } = { }\n) {\n assert(path.isAbsolute(fpd), t('fpd 必须是绝对路径: ') + fpd)\n assert(fpd.endsWith('/'), t('fpd 必须以 / 结尾: ') + fpd)\n \n // CallingfsPromises.mkdir() when path is a directory that exists results in a rejection only when recursive is false.\n const fpd_ = (\n await fsp.mkdir(fpd, { recursive: true, mode })\n )?.replaceAll('\\\\', '/')\n \n if (fpd_) {\n if (print)\n console.log(t('已创建文件夹'), fpd)\n } else\n if (print)\n console.log(t('已存在文件夹'), fpd)\n \n return fpd_\n}\n\n\n/** 创建软链接 Create soft links \n - fp_real: 现在真实文件/文件夹的路径 current real file/directory path\n - fp_link: 目标链接文件/文件夹的路径 target file/directory path */\nexport async function flink (\n fp_real: string, \n fp_link: string, \n {\n junction = false,\n print = true \n }: { \n junction?: boolean\n print?: boolean\n} = { }) {\n assert(path.isAbsolute(fp_real) && path.isAbsolute(fp_link), t('fp 必须是绝对路径'))\n \n const is_fpd_real = fp_real.endsWith('/')\n const is_fpd_link = fp_link.endsWith('/')\n \n assert(is_fpd_real === is_fpd_link, t('fp_real 和 fp_link 必须同为文件路径或文件夹路径'))\n \n if (fexists(fp_link))\n throw new Error(t('存在同名') + (is_fpd_link ? t('文件夹') : t('文件')) + ': ' + fp_link + t(',无法创建链接'))\n \n if (print)\n console.log(t('已将源文件 ') + fp_real + t(' 链接到 ') + fp_link)\n \n if (junction)\n fsp.symlink(fp_real, fp_link, 'junction')\n else\n fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file')\n}\n\n\nexport interface ZipOptions {\n dirname?: string\n print?: {\n info: boolean\n files: boolean\n }\n}\n\n\n/** 将文件夹压缩为 zip \n - data: \n - 被压缩文件夹路径 (fpd_src: string) 或\n - 文件索引对象 (entries: Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Buffer)>) \n - fp_zip?:\n - 传压缩包完整路径时压缩到文件, 函数返回值为 Promise<zip 路径>\n - 传 undefined 时压缩到内存, 函数返回值为 Promise<zip buffer>\n - options?:\n - dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字,如 'web', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)\n - print?:\n - info?: `true` 开始压缩、压缩完成\n - files?: `true` 打印压缩文件列表 */\nexport async function fzip (entries: Record<string, string | Buffer>, fp_zip?: undefined, options?: ZipOptions): Promise<Buffer>\nexport async function fzip (entries: Record<string, string | Buffer>, fp_zip: string, options?: ZipOptions): Promise<string>\nexport async function fzip (fpd_src: string, fp_zip?: undefined, options?: ZipOptions): Promise<Buffer>\nexport async function fzip (fpd_src: string, fp_zip: string, options?: ZipOptions): Promise<string>\nexport async function fzip (\n data: string | Record<string, string | Buffer>,\n fp_zip?: string,\n {\n dirname,\n print = { files: true, info: true }\n }: ZipOptions = { }\n): Promise<string | Buffer> {\n let entries: Record<string, string | Buffer>\n let fpd_src: string\n \n if (typeof data === 'string') {\n if (!path.isAbsolute(data) || !data.endsWith('/'))\n throw new Error('fpd_src 必须是绝对路径且以 / 结尾')\n \n fpd_src = data\n \n if (dirname === undefined)\n dirname = fpd_src.fname\n \n entries = Object.fromEntries(\n (await flist(fpd_src, { print: false }))\n .map(fp => ([dirname + fp, fpd_src + fp]))\n )\n } else\n entries = data\n \n \n if (print.info)\n console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} → ${fp_zip ? `${fp_zip}/${dirname}` : '内存'}`)\n \n let archive = archiver('zip')\n \n let ostream = fp_zip ? fs.createWriteStream(fp_zip) : new WritableMemoryStream()\n \n const size = await new Promise<number>((resolve, reject) => {\n ostream.once('close', () => {\n resolve(archive.pointer())\n })\n \n archive.once('error', reject)\n \n archive.on('warning', error => {\n console.log(error)\n })\n \n archive.pipe(ostream)\n \n for (const fp in entries) {\n const fdata = entries[fp]\n \n if (fdata instanceof Buffer) {\n if (print.files)\n console.log(`压缩 ${fdata.length.to_fsize_str()} → ${fp}`)\n archive.append(fdata, { name: fp })\n } else {\n assert(fp.endsWith('/') === fdata.endsWith('/'))\n assert(path.isAbsolute(fdata))\n \n if (print.files)\n console.log(`压缩 ${fdata} → ${fp}`)\n \n if (fp.endsWith('/'))\n archive.directory(fdata, fp)\n else\n archive.file(fdata, { name: fp })\n }\n }\n \n archive.finalize()\n })\n \n if (print.info)\n console.log(`压缩完成,总大小 ${size.to_fsize_str()}`)\n \n return fp_zip || (ostream as WritableMemoryStream).pbuffer\n}\n\n\nexport let fwatchers: Record<string, fs.FSWatcher> = { }\n\n/**\n - fp: 文件或文件夹路径 path of file or directory\n - callback: 文件修改时回调 called when modified\n - exec: `true` 首次 watch 时执行 onchange call callback when watch is executed\n \n 创建的 fs.FSWatcher 保存在 watchers 中, 再次调用相同的 fp 会自动关闭已有的 watcher \n save fs.FSWatcher in watchers, subsequent call will auto close existing watcher for the same fp\n \n https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fs_watch_filename_options_listener \n The listener callback gets two arguments (event, fname). \n event is either 'rename' or 'change', and filename is the name of the file which triggered the event.\n On most platforms, 'rename' is emitted whenever a filename appears or disappears in the directory.\n \n The listener callback is attached to the 'change' event fired by fs.FSWatcher, but it is not the same thing as the 'change' value of event. */\nexport async function fwatch (\n fp: string,\n onchange: (event: string, fname: string) => any, \n { exec = true }: { exec?: boolean } = { }\n) {\n if (!path.isAbsolute(fp))\n throw new Error(t('fp 必须是完整路径'))\n \n const _watcher = fwatchers[fp]\n if (_watcher)\n _watcher.close()\n \n if (exec)\n await onchange('change', fp.fname)\n \n const start = new Date().getTime()\n \n const debounced_onchange = debounce(\n (event, fname) => {\n if (new Date().getTime() - start < 800)\n return\n console.log(t('文件修改 (') + event + '): ' + fname)\n onchange(event, path.normalize(fname))\n },\n 500,\n { leading: false, trailing: true }\n )\n \n let watcher = fs.watch(fp, debounced_onchange)\n watcher.on('error', error => {\n console.error(error)\n })\n return fwatchers[fp] = watcher\n}\n\n\n/** 打开一个文件并搜索替换某个 pattern open a file and replace certain pattern */\nexport async function freplace (fp: string, pattern: string | RegExp, replacement: string) {\n await fwrite(\n fp,\n (await fread(fp))\n .replaceAll(pattern, replacement)\n )\n}\n\n/** 将文件编码转为 UTF-8 convert file encoding to UTF-8\n - fp: 文件完整路径 file absolute path\n - options?:\n - dryrun?: `true`\n - encoding?: `'auto'` */\nexport async function f2utf8 (fp: string, {\n dryrun = true,\n encoding = 'auto',\n}: {\n dryrun?: boolean\n encoding?: Encoding | 'auto'\n} = { }) {\n const text = await fread(fp, { encoding })\n if (dryrun) {\n console.log(text.slice(0, 10000))\n return\n }\n \n const fp_bak = `${fp.fdir}${fp.fname.replace(/(.*?)(\\.[^.]+)?$/, '$1.bak$2')}`\n if (!fexists(fp_bak))\n await fcopy(fp, fp_bak)\n \n await fwrite(fp, text)\n}\n\n"]}
|
package/net.browser.d.ts
CHANGED
|
@@ -24,6 +24,20 @@ export interface RequestOptions {
|
|
|
24
24
|
export interface RequestRawOptions extends RequestOptions {
|
|
25
25
|
raw: true;
|
|
26
26
|
}
|
|
27
|
+
export interface RequestError extends Error {
|
|
28
|
+
url: URL;
|
|
29
|
+
options: RequestInit;
|
|
30
|
+
response?: {
|
|
31
|
+
/** 状态码 */
|
|
32
|
+
status: number;
|
|
33
|
+
url: string;
|
|
34
|
+
headers: Headers;
|
|
35
|
+
ok: boolean;
|
|
36
|
+
type: ResponseType;
|
|
37
|
+
text: string;
|
|
38
|
+
redirected: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
27
41
|
/**
|
|
28
42
|
- url: 可以只有 pathname 部分
|
|
29
43
|
- options?:
|
package/net.browser.js
CHANGED
|
@@ -78,9 +78,27 @@ export async function request(url, { method, queries, headers, body, type = 'app
|
|
|
78
78
|
}
|
|
79
79
|
})(),
|
|
80
80
|
};
|
|
81
|
-
let response
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
let response;
|
|
82
|
+
try {
|
|
83
|
+
response = await fetch_retry(url, options, timeout, retries);
|
|
84
|
+
if (!response.ok)
|
|
85
|
+
throw Object.assign(new Error(`状态码 ${response.status}, 非 2xx`), { name: 'StatusCodeError' });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
error.url = url;
|
|
89
|
+
error.options = options;
|
|
90
|
+
if (response)
|
|
91
|
+
error.response = {
|
|
92
|
+
status: response.status,
|
|
93
|
+
url: response.url,
|
|
94
|
+
headers: response.headers,
|
|
95
|
+
ok: response.ok,
|
|
96
|
+
type: response.type,
|
|
97
|
+
text: await response.text(),
|
|
98
|
+
redirected: response.redirected
|
|
99
|
+
};
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
84
102
|
if (raw)
|
|
85
103
|
return response;
|
|
86
104
|
if (!response.body)
|
|
@@ -96,14 +114,43 @@ export async function request(url, { method, queries, headers, body, type = 'app
|
|
|
96
114
|
...body ? { 'content-type': type } : {},
|
|
97
115
|
...headers,
|
|
98
116
|
},
|
|
99
|
-
...body ? {
|
|
117
|
+
...body ? {
|
|
118
|
+
data: typeof body === 'string' ? body : JSON.stringify(body)
|
|
119
|
+
} : {},
|
|
100
120
|
onload(response) {
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
if (200 <= response.status && response.status <= 299)
|
|
122
|
+
resolve(response.responseText);
|
|
123
|
+
else
|
|
124
|
+
reject(Object.assign(new Error(`状态码 ${response.status}, 非 2xx`), {
|
|
125
|
+
name: 'StatusCodeError',
|
|
126
|
+
url,
|
|
127
|
+
options,
|
|
128
|
+
response: {
|
|
129
|
+
stauts: response.status,
|
|
130
|
+
url: url.toString(),
|
|
131
|
+
headers: response.responseHeaders,
|
|
132
|
+
ok: false,
|
|
133
|
+
text: response.responseText
|
|
134
|
+
}
|
|
135
|
+
}));
|
|
136
|
+
},
|
|
137
|
+
onerror(response) {
|
|
138
|
+
reject(Object.assign(new Error(response.error), {
|
|
139
|
+
name: 'TimeoutError',
|
|
140
|
+
url: url,
|
|
141
|
+
options,
|
|
142
|
+
response: {
|
|
143
|
+
stauts: response.status,
|
|
144
|
+
url: url.toString(),
|
|
145
|
+
headers: response.responseHeaders,
|
|
146
|
+
ok: false,
|
|
147
|
+
text: response.responseText
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
},
|
|
151
|
+
ontimeout() {
|
|
152
|
+
reject(Object.assign(new Error('GM_xmlhttpRequest 超时'), { name: 'TimeoutError', url, options }));
|
|
153
|
+
},
|
|
107
154
|
};
|
|
108
155
|
GM_xmlhttpRequest(options);
|
|
109
156
|
});
|
package/net.browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"net.browser.js","sourceRoot":"","sources":["net.browser.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference types='tampermonkey' />\n\nimport { t } from './i18n/instance.js'\nimport './prototype.browser.js' // to_time_str()\nimport { assert, concat, genid, delay } from './utils.browser.js'\n\n\n// ------------------------------------ fetch, request\nexport interface BasicAuth {\n type: 'basic',\n username: string\n password: string\n}\n\nexport interface BearerAuth {\n type: 'bearer',\n token: string\n}\n\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'HEAD' | 'DELETE' | 'PATCH'\n \n queries?: Record<string, any>\n \n headers?: Record<string, string>\n \n body?: string | Record<string, any> | ArrayBufferView | ArrayBuffer | Blob |\n URLSearchParams | FormData\n \n type?: 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data'\n \n retries?: true | number\n \n timeout?: number\n \n auth?: BasicAuth | BearerAuth\n \n cookies?: Record<string, string>\n \n cors?: boolean\n \n by?: 'fetch' | 'GM_xmlhttpRequest'\n}\n\nexport interface RequestRawOptions extends RequestOptions {\n raw: true\n}\n\n\nasync function fetch_retry (url: URL, options: RequestInit, timeout: number, retries = 0, count = 0): Promise<Response> {\n try {\n options.signal = AbortSignal.timeout(timeout)\n return await fetch(url, options)\n } catch (error) {\n if (\n count >= retries ||\n error.name !== 'TimeoutError' && !['ECONNRESET', 'ETIMEDOUT', 'ESOCKETTIMEDOUT'].includes(error.cause?.code)\n )\n throw error\n else {\n const duration = 2 ** count\n console.log(`${t('等待 {{duration}} 秒后重试 fetch ({{_count}}) …', { duration, _count: count })} ${url.toString()}`)\n await delay(1000 * duration)\n return fetch_retry(url, options, timeout, retries, count + 1)\n }\n }\n}\n\n\n/**\n - url: 可以只有 pathname 部分\n - options?:\n - method?: `有 body 时为 POST, 否则为 GET` 'GET' | 'POST' | ···\n - queries?: 添加到 url 上的参数,是 Record<string, any>,true/false 会被转换为 0/1\n - headers?: http 请求头\n - body?: http 请求体,可以是 string, Record<string, any> (会自动 JSON.stringify), ArrayBuffer(View), Blob, \n URLSearchParams (type 为 x-www-form-urlencoded), FormData (type 为 form-data)\n - type?: `'application/json'` 有 body 时设置 http 请求头中的 content-type 头\n - retries?: `false` 可以传入 true (默认 2 次) 或 重试次数\n - timeout?: `5 * 1000`\n - auth?: BasicAuth | BearerAuth\n - raw?: `false` 传入后返回整个 response \n - by: `window.GM_xmlhttpRequest ? 'GM_xmlhttpRequest' : 'fetch'` 发起请求所使用的底层方法 */\nexport async function request (url: string | URL): Promise<string>\nexport async function request (url: string | URL, options: RequestRawOptions): Promise<Response>\nexport async function request (url: string | URL, options: RequestOptions & { encoding: 'binary' }): Promise<ArrayBuffer>\nexport async function request (url: string | URL, options: RequestOptions): Promise<string>\nexport async function request (url: string | URL, {\n method,\n \n queries,\n \n headers,\n \n body,\n \n type = 'application/json',\n \n retries,\n \n timeout = 5 * 1000,\n \n auth,\n \n raw = false,\n \n cors,\n \n by = window.GM_xmlhttpRequest ? 'GM_xmlhttpRequest' : 'fetch',\n}: RequestOptions & { raw?: boolean } = { }) {\n url = new URL(url, location.href)\n \n if (queries)\n for (const key in queries) {\n let value = queries[key]\n if (typeof value === 'boolean')\n value = value ? '1' : '0'\n url.searchParams.append(key, value)\n }\n \n if (body !== undefined && !method)\n method = 'POST'\n \n if (retries === true)\n retries = 2\n \n \n if (by === 'fetch') {\n let options: RequestInit = {\n ... method ? { method } : { },\n \n keepalive: true,\n \n redirect: 'follow',\n \n credentials: 'include',\n \n ... cors ? { mode: 'cors' } : { },\n \n headers: {\n ... body === undefined ? { } : { 'Content-Type': type },\n ... auth ?\n { Authorization: auth.type === 'basic' ? `Basic ${`${auth.username}:${auth.password}`.to_base64()}` : `Bearer ${auth.token}` }\n :\n { },\n ... headers ? \n Object.fromEntries(\n Object.entries(headers)\n .filter(([key, value]) => !key.startsWith(':'))\n ) : { }\n },\n \n // --- body\n body: (() => {\n if (body === undefined)\n return\n \n switch (type) {\n case 'application/json':\n return typeof body === 'string' || \n ArrayBuffer.isView(body) || \n body instanceof ArrayBuffer ||\n body instanceof Blob ?\n body as (string | NodeJS.ArrayBufferView | ArrayBuffer | Blob)\n :\n JSON.stringify(body)\n \n case 'application/x-www-form-urlencoded':\n return body instanceof URLSearchParams ? body : new URLSearchParams(body as Record<string, any>)\n \n case 'multipart/form-data':\n if (body instanceof FormData)\n return body\n else {\n let form = new FormData()\n for (const key in body as Record<string, any>) {\n let value = body[key]\n form.set(key, value)\n }\n return form\n }\n }\n })(),\n }\n \n \n let response = await fetch_retry(url, options, timeout, retries)\n \n if (!response.ok)\n throw Object.assign(\n new Error(t('状态码 {{status}} 非 2xx', { status: response.status })),\n { name: 'StatusCodeError', url, options, response }\n )\n \n if (raw)\n return response\n \n if (!response.body)\n return response.body\n \n return response.text()\n } else\n return new Promise((resolve, reject) => {\n const options: Tampermonkey.Request<any> = {\n ... method ? { method: method as 'GET' | 'POST' | 'HEAD' } : { },\n \n url: url.toString(),\n \n headers: {\n ... body ? { 'content-type': type } : { },\n ... headers,\n },\n \n ... body ? { data: body as string } : { },\n \n onload (response) {\n if (!(200 <= response.status && response.status <= 299)) {\n reject(\n Object.assign(\n new Error(t('状态码 {{status}} 非 2xx', { status: response.status })),\n { name: 'StatusCodeError', url, options, response }\n )\n )\n \n return\n }\n \n resolve(response.responseText)\n }\n }\n \n GM_xmlhttpRequest(options)\n })\n}\n\n\n/** 发起 http 请求并将响应体作为 json 解析 */\nexport async function request_json <T = any> (url: string, options?: RequestOptions): Promise<T> {\n const resp = await request(url, options)\n if (!resp)\n return\n try {\n return JSON.parse(resp)\n } catch (error) {\n console.error(resp)\n throw error\n }\n}\n\n\n\nlet decoder = new TextDecoder()\n\nlet encoder = new TextEncoder()\n\n\nexport class WebSocketConnectionError extends Error {\n override name = 'WebSocketConnectionError'\n \n websocket: WebSocket\n \n constructor (websocket: WebSocket) {\n super(`${websocket.url} ${t('连接出错了')}`)\n this.websocket = websocket\n }\n}\n\n\n/** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket \n 遇到 error 时会创建 WebSocketConnectionError, 并作为参数调用 on_error,同时 reject 掉返回的 promise (若此时未 settle) \n - url\n - options:\n - protocols?\n - on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string\n https://datatracker.ietf.org/doc/html/rfc6455#section-5.2\n - on_close?: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes\n - on_error? */\nexport async function connect_websocket (\n url: string | URL,\n {\n protocols,\n on_close,\n on_error,\n on_message\n }: {\n protocols?: string | string[]\n on_close? (event: { code: number, reason: string }, websocket: WebSocket): any\n on_error? (error: WebSocketConnectionError, websocket: WebSocket): any\n on_message (data: ArrayBuffer | string, websocket: WebSocket): any\n }\n) {\n let websocket = new WebSocket(url, protocols)\n \n // https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543\n websocket.binaryType = 'arraybuffer'\n \n return new Promise<WebSocket>((resolve, reject) => {\n let settled = false\n \n websocket.addEventListener('open', async event => {\n console.log(\n websocket.url +\n (protocols ? \n ' ' + (\n typeof protocols === 'string' ? protocols : protocols.join(', ').bracket('square')\n ).bracket()\n :\n '') +\n t(' 已连接')\n )\n \n settled = true\n resolve(websocket)\n })\n \n websocket.addEventListener('close', event => {\n if (event.code === 1000)\n console.log(websocket.url + t(' 已正常关闭'))\n else\n console.log(`${websocket.url} ${t('被关闭')}, code: ${event.code}${ event.reason ? `, ${t('原因')}: ${event.reason}` : '' }`)\n on_close?.(event, websocket)\n })\n \n websocket.addEventListener('error', event => {\n const error = new WebSocketConnectionError(websocket)\n \n try {\n on_error?.(error, websocket)\n } catch (error) {\n if (settled)\n throw error\n else {\n settled = true\n reject(error)\n }\n }\n \n if (settled)\n throw error\n else {\n settled = true\n reject(error)\n }\n })\n \n websocket.addEventListener('message', event => {\n on_message(event.data, websocket)\n })\n })\n}\n\n\n/** 接收到消息后的处理函数 \n 返回值可以是:\n - 数组: 会自动被封装为 { id: 相同, data: 返回值, done: true } 这样的消息并调用 websocket.send 将其发送\n - void: 什么都不做\n - 以上的 promise */\nexport type MessageHandler = (message: Message, websocket?: WebSocket) => void | any[] | Promise<void | any[]>\n\n\n/** 二进制消息格式 \n - json.length (小端序): 4 字节\n - json 数据\n - binary 数据\n*/\nexport interface Message <TData extends any[] = any[]> {\n /** rpc id: 在 rpc 系统中认为是唯一的。用来在单个 websocket 连接上复用多个 rpc 请求。多个相同 id 的 message 组成一个请求流 */\n id?: number\n \n /** 只在 rpc 发起时指定被调用的 function name,发起时 rpc 时必传 */\n func?: string\n \n /** 通过这个 flag 主动表明这是发往对方的最后一个 message, 对方可以销毁 handler 了 \n 并非强制,可以不说明,由双方的函数自己约定\n */\n done?: boolean\n \n /** 通知对方这里产生的错误,本质上类似 data 也是一种数据,并不代表 rpc 的结束,后续可能继续有 rpc message 交换 */\n error?: Error\n \n /** data 是一个数组, 作为:\n - rpc 发起方调用 func 的参数,或者请求流 message 携带的数据\n - 结果或者响应流的数据,传给请求发起方\n \n 里面是可序列化为 json 的 js 变量,或者是 Uint8Array \n Uint8Array 的参数处理后被替换为 Uint8Array.byteLength, 并将下标记录在 bins 中\n \n 注意: 数组中如果有 undefined 值,传输到对面会变成 null 值\n */\n data?: TData\n \n /** bins: data 中哪些下标对应的原始值是 Uint8Array 类型的,如: [0, 3] */\n bins?: number[]\n}\n\n/** 通过创建 remote 对象对 websocket rpc 进行抽象 \n 调用方使用 remote.call 进行调用 \n 被调方在创建 remote 对象时传入 funcs 注册处理函数,并使用 remote.handle 方法处理 websocket message \n 未连接时自动连接,断开后自动重连 */\nexport class Remote {\n url: string\n \n /** 主动发起 websocket 连接的客户端 (构造函数传 url) 有这个属性 */\n websocket?: WebSocket\n \n /** 通过 rpc message.func 被调用的 rpc 函数 */\n funcs: Record<string, MessageHandler>\n \n /** map<id, message handler>: 通过 rpc message.id 找到对应的 handler, unary rpc 接收方不需要设置 handlers, 发送方需要 */\n handlers = new Map<number, MessageHandler>()\n \n \n print = false\n \n pconnect: Promise<any>\n \n \n get connected () {\n return this.websocket?.readyState === WebSocket.OPEN\n }\n \n \n static parse <TData extends any[] = any[]> (array_buffer: ArrayBuffer) {\n const buf = new Uint8Array(array_buffer as ArrayBuffer)\n const dv = new DataView(array_buffer)\n \n const len_json = dv.getUint32(0, true)\n \n let offset = 4 + len_json\n \n let message: Message<TData> = JSON.parse(decoder.decode(buf.subarray(4, offset)))\n \n if (message.bins) {\n const { bins } = message\n let { data } = message\n \n for (const ibin of bins) {\n const len_buf = data[ibin]\n data[ibin] = buf.subarray(offset, offset + len_buf)\n offset += len_buf\n }\n }\n \n if (message.error)\n message.error = Object.assign(new Error(), message.error)\n \n return message\n }\n \n \n static pack ({ id, func, data = [ ], done, error }: Message) {\n let data_ = new Array(data.length)\n let bins: number[] = [ ]\n let bufs: Uint8Array[] = [ ]\n \n for (let i = 0; i < data.length; i++) {\n const item = data[i]\n if (item instanceof Uint8Array) {\n bins.push(i)\n bufs.push(item)\n data_[i] = item.length\n } else\n data_[i] = item\n }\n \n const data_json = {\n id,\n ... func ? { func } : { },\n ... done ? { done } : { },\n ... error ? { error } : { },\n ... data_.length ? { data: data_ } : { },\n ... bins.length ? { bins } : { },\n }\n \n const str_json = encoder.encode(JSON.stringify(data_json))\n \n let dv = new DataView(new ArrayBuffer(4))\n \n dv.setUint32(0, str_json.length, true)\n \n return concat([dv, str_json, ... bufs])\n }\n \n \n constructor ({\n url, funcs = { }, websocket\n }: {\n url?: string, funcs?: Remote['funcs'], websocket?: WebSocket\n } = { }) {\n this.url = url\n this.funcs = funcs\n this.websocket = websocket\n }\n \n \n /** 幂等,保证 websocket 已连接,否则抛出异常,不需要手动调用,在其它方法中已默认自动重连 */\n async connect () {\n if (this.connected)\n return\n \n const ptail = this.pconnect\n \n let resolve: () => void\n this.pconnect = new Promise<void>((_resolve, _reject) => {\n resolve = _resolve\n })\n \n await ptail\n \n try {\n if (!this.connected)\n // 保存的 rpc 状态在 this.handlers, 与 websocket 无关,因此即使断开重连也不影响 rpc 的运行,即\n // 底层连接断开后自动重连对上层应该是无感知的,除非再次连接时失败\n this.websocket = await connect_websocket(this.url, { on_message: this.handle.bind(this) })\n } finally {\n resolve()\n }\n }\n \n \n disconnect () {\n this.websocket?.close()\n }\n \n \n /** 接收 websocket 连接的 remote 端必传 websocket 参数;发起端选传,如果传了必须等于 this.websocket \n 发送或连接出错时自动清理 message.id 对应的 handler */\n async send (message: Message, websocket?: WebSocket) {\n try {\n if (this.url) {\n assert(!websocket || websocket === this.websocket)\n await this.connect()\n websocket = this.websocket\n } else {\n assert(websocket)\n if (websocket.readyState !== WebSocket.OPEN)\n throw new Error(t('remote.send(): websocket client 已断开'))\n }\n \n if (!message.id)\n message.id = genid()\n \n websocket.send(Remote.pack(message))\n } catch (error) {\n if (message.id)\n this.handlers.delete(message.id)\n throw error\n }\n }\n \n \n /** 处理接收到的 websocket message 并解析, 根据 id dispatch 到对应的 handler 进行处理 \n 如果 message.done == true 则清理 handler \n 如果 handler 返回了值,则包装为 message 发送 */\n async handle (data: ArrayBuffer, websocket: WebSocket) {\n const message = Remote.parse(data)\n \n const { id, func, done } = message\n \n if (this.print)\n console.log(message)\n \n let handler: MessageHandler\n \n if (func)\n handler = this.funcs[func]\n else {\n handler = this.handlers.get(id)\n if (done)\n this.handlers.delete(id)\n }\n \n try {\n if (handler) {\n const data = await handler(message, websocket)\n if (data)\n await this.send({ id, data }, websocket)\n } else if (message.error)\n throw message.error\n else\n throw new Error(`${t('找不到 rpc handler')}: ${func ? `func: ${func.quote()}` : `id: ${id}`}`)\n } catch (error) {\n // handle 出错并不意味着 rpc 一定会结束,可能 error 是运行中的正常数据,所以不能清理 handler\n \n if (\n websocket.readyState === WebSocket.OPEN &&\n !message.error // 防止无限循环往对方发送 error, 只有在对方无错误时才可以发送\n )\n try { await this.send({ id, error, /* 不能设置 done 清理对面 handler, 理由同上 */ }, websocket) } catch { }\n \n // 再往上层抛出错误没有意义了,上层调用栈是 websocket.on('message') 之类的\n console.log(error)\n }\n }\n \n \n /** 调用 remote 中的 func, 只适用于最简单的一元 rpc (请求, 响应) */\n async call <TReturn extends any[] = any[]> (func: string, args?: any[]) {\n return new Promise<TReturn>(async (resolve, reject) => {\n const id = genid()\n \n this.handlers.set(id, (message: Message<TReturn>) => {\n const { error, data } = message\n if (error)\n reject(error)\n else\n resolve(data)\n this.handlers.delete(id)\n })\n \n try {\n await this.send({ id, func, data: args }) // 不需要 done: true, 因为对面的 remote.handlers 中不会有这个 id 的 handler\n } catch (error) {\n reject(error)\n }\n })\n }\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"net.browser.js","sourceRoot":"","sources":["net.browser.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference types='tampermonkey' />\n\nimport { t } from './i18n/instance.js'\nimport './prototype.browser.js' // to_time_str()\nimport { assert, concat, genid, delay } from './utils.browser.js'\n\n\n// ------------------------------------ fetch, request\nexport interface BasicAuth {\n type: 'basic',\n username: string\n password: string\n}\n\nexport interface BearerAuth {\n type: 'bearer',\n token: string\n}\n\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'HEAD' | 'DELETE' | 'PATCH'\n \n queries?: Record<string, any>\n \n headers?: Record<string, string>\n \n body?: string | Record<string, any> | ArrayBufferView | ArrayBuffer | Blob |\n URLSearchParams | FormData\n \n type?: 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data'\n \n retries?: true | number\n \n timeout?: number\n \n auth?: BasicAuth | BearerAuth\n \n cookies?: Record<string, string>\n \n cors?: boolean\n \n by?: 'fetch' | 'GM_xmlhttpRequest'\n}\n\nexport interface RequestRawOptions extends RequestOptions {\n raw: true\n}\n\n\nasync function fetch_retry (url: URL, options: RequestInit, timeout: number, retries = 0, count = 0): Promise<Response> {\n try {\n options.signal = AbortSignal.timeout(timeout)\n return await fetch(url, options)\n } catch (error) {\n if (\n count >= retries ||\n error.name !== 'TimeoutError' && !['ECONNRESET', 'ETIMEDOUT', 'ESOCKETTIMEDOUT'].includes(error.cause?.code)\n )\n throw error\n else {\n const duration = 2 ** count\n console.log(`${t('等待 {{duration}} 秒后重试 fetch ({{_count}}) …', { duration, _count: count })} ${url.toString()}`)\n await delay(1000 * duration)\n return fetch_retry(url, options, timeout, retries, count + 1)\n }\n }\n}\n\n\nexport interface RequestError extends Error {\n url: URL\n \n options: RequestInit\n \n response?: {\n /** 状态码 */\n status: number\n \n url: string\n \n headers: Headers\n \n ok: boolean\n \n type: ResponseType\n \n text: string\n \n redirected: boolean\n }\n}\n\n\n/**\n - url: 可以只有 pathname 部分\n - options?:\n - method?: `有 body 时为 POST, 否则为 GET` 'GET' | 'POST' | ···\n - queries?: 添加到 url 上的参数,是 Record<string, any>,true/false 会被转换为 0/1\n - headers?: http 请求头\n - body?: http 请求体,可以是 string, Record<string, any> (会自动 JSON.stringify), ArrayBuffer(View), Blob, \n URLSearchParams (type 为 x-www-form-urlencoded), FormData (type 为 form-data)\n - type?: `'application/json'` 有 body 时设置 http 请求头中的 content-type 头\n - retries?: `false` 可以传入 true (默认 2 次) 或 重试次数\n - timeout?: `5 * 1000`\n - auth?: BasicAuth | BearerAuth\n - raw?: `false` 传入后返回整个 response \n - by: `window.GM_xmlhttpRequest ? 'GM_xmlhttpRequest' : 'fetch'` 发起请求所使用的底层方法 */\nexport async function request (url: string | URL): Promise<string>\nexport async function request (url: string | URL, options: RequestRawOptions): Promise<Response>\nexport async function request (url: string | URL, options: RequestOptions & { encoding: 'binary' }): Promise<ArrayBuffer>\nexport async function request (url: string | URL, options: RequestOptions): Promise<string>\nexport async function request (url: string | URL, {\n method,\n \n queries,\n \n headers,\n \n body,\n \n type = 'application/json',\n \n retries,\n \n timeout = 5 * 1000,\n \n auth,\n \n raw = false,\n \n cors,\n \n by = window.GM_xmlhttpRequest ? 'GM_xmlhttpRequest' : 'fetch',\n}: RequestOptions & { raw?: boolean } = { }) {\n url = new URL(url, location.href)\n \n if (queries)\n for (const key in queries) {\n let value = queries[key]\n if (typeof value === 'boolean')\n value = value ? '1' : '0'\n url.searchParams.append(key, value)\n }\n \n if (body !== undefined && !method)\n method = 'POST'\n \n if (retries === true)\n retries = 2\n \n \n if (by === 'fetch') {\n let options: RequestInit = {\n ... method ? { method } : { },\n \n keepalive: true,\n \n redirect: 'follow',\n \n credentials: 'include',\n \n ... cors ? { mode: 'cors' } : { },\n \n headers: {\n ... body === undefined ? { } : { 'Content-Type': type },\n ... auth ?\n { Authorization: auth.type === 'basic' ? `Basic ${`${auth.username}:${auth.password}`.to_base64()}` : `Bearer ${auth.token}` }\n :\n { },\n ... headers ? \n Object.fromEntries(\n Object.entries(headers)\n .filter(([key, value]) => !key.startsWith(':'))\n ) : { }\n },\n \n // --- body\n body: (() => {\n if (body === undefined)\n return\n \n switch (type) {\n case 'application/json':\n return typeof body === 'string' || \n ArrayBuffer.isView(body) || \n body instanceof ArrayBuffer ||\n body instanceof Blob ?\n body as (string | NodeJS.ArrayBufferView | ArrayBuffer | Blob)\n :\n JSON.stringify(body)\n \n case 'application/x-www-form-urlencoded':\n return body instanceof URLSearchParams ? body : new URLSearchParams(body as Record<string, any>)\n \n case 'multipart/form-data':\n if (body instanceof FormData)\n return body\n else {\n let form = new FormData()\n for (const key in body as Record<string, any>) {\n let value = body[key]\n form.set(key, value)\n }\n return form\n }\n }\n })(),\n }\n \n \n let response: Response\n \n try {\n response = await fetch_retry(url, options, timeout, retries)\n \n if (!response.ok)\n throw Object.assign(\n new Error(`状态码 ${response.status}, 非 2xx`),\n { name: 'StatusCodeError' }\n )\n } catch (error) {\n error.url = url\n error.options = options\n \n if (response)\n error.response = {\n status: response.status,\n url: response.url,\n headers: response.headers,\n ok: response.ok,\n type: response.type,\n text: await response.text(),\n redirected: response.redirected\n }\n \n throw error\n }\n \n if (raw)\n return response\n \n if (!response.body)\n return response.body\n \n return response.text()\n } else\n return new Promise((resolve, reject) => {\n const options: Tampermonkey.Request<any> = {\n ... method ? { method: method as 'GET' | 'POST' | 'HEAD' } : { },\n \n url: url.toString(),\n \n headers: {\n ... body ? { 'content-type': type } : { },\n ... headers,\n },\n \n ... body ? {\n data: typeof body === 'string' ? body : JSON.stringify(body)\n } : { },\n \n onload (response) {\n if (200 <= response.status && response.status <= 299)\n resolve(response.responseText)\n else\n reject(\n Object.assign(\n new Error(`状态码 ${response.status}, 非 2xx`), \n {\n name: 'StatusCodeError',\n url,\n options,\n response: {\n stauts: response.status,\n url: url.toString(),\n headers: response.responseHeaders,\n ok: false,\n text: response.responseText\n }\n }\n )\n )\n },\n \n onerror (response) {\n reject(\n Object.assign(\n new Error(response.error),\n {\n name: 'TimeoutError',\n url: url as URL,\n options,\n response: {\n stauts: response.status,\n url: url.toString(),\n headers: response.responseHeaders,\n ok: false,\n text: response.responseText\n }\n }\n )\n )\n },\n \n ontimeout () {\n reject(\n Object.assign(\n new Error('GM_xmlhttpRequest 超时'),\n { name: 'TimeoutError', url, options }\n )\n )\n },\n }\n \n GM_xmlhttpRequest(options)\n })\n}\n\n\n/** 发起 http 请求并将响应体作为 json 解析 */\nexport async function request_json <T = any> (url: string, options?: RequestOptions): Promise<T> {\n const resp = await request(url, options)\n if (!resp)\n return\n try {\n return JSON.parse(resp)\n } catch (error) {\n console.error(resp)\n throw error\n }\n}\n\n\n\nlet decoder = new TextDecoder()\n\nlet encoder = new TextEncoder()\n\n\nexport class WebSocketConnectionError extends Error {\n override name = 'WebSocketConnectionError'\n \n websocket: WebSocket\n \n constructor (websocket: WebSocket) {\n super(`${websocket.url} ${t('连接出错了')}`)\n this.websocket = websocket\n }\n}\n\n\n/** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket \n 遇到 error 时会创建 WebSocketConnectionError, 并作为参数调用 on_error,同时 reject 掉返回的 promise (若此时未 settle) \n - url\n - options:\n - protocols?\n - on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string\n https://datatracker.ietf.org/doc/html/rfc6455#section-5.2\n - on_close?: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes\n - on_error? */\nexport async function connect_websocket (\n url: string | URL,\n {\n protocols,\n on_close,\n on_error,\n on_message\n }: {\n protocols?: string | string[]\n on_close? (event: { code: number, reason: string }, websocket: WebSocket): any\n on_error? (error: WebSocketConnectionError, websocket: WebSocket): any\n on_message (data: ArrayBuffer | string, websocket: WebSocket): any\n }\n) {\n let websocket = new WebSocket(url, protocols)\n \n // https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543\n websocket.binaryType = 'arraybuffer'\n \n return new Promise<WebSocket>((resolve, reject) => {\n let settled = false\n \n websocket.addEventListener('open', async event => {\n console.log(\n websocket.url +\n (protocols ? \n ' ' + (\n typeof protocols === 'string' ? protocols : protocols.join(', ').bracket('square')\n ).bracket()\n :\n '') +\n t(' 已连接')\n )\n \n settled = true\n resolve(websocket)\n })\n \n websocket.addEventListener('close', event => {\n if (event.code === 1000)\n console.log(websocket.url + t(' 已正常关闭'))\n else\n console.log(`${websocket.url} ${t('被关闭')}, code: ${event.code}${ event.reason ? `, ${t('原因')}: ${event.reason}` : '' }`)\n on_close?.(event, websocket)\n })\n \n websocket.addEventListener('error', event => {\n const error = new WebSocketConnectionError(websocket)\n \n try {\n on_error?.(error, websocket)\n } catch (error) {\n if (settled)\n throw error\n else {\n settled = true\n reject(error)\n }\n }\n \n if (settled)\n throw error\n else {\n settled = true\n reject(error)\n }\n })\n \n websocket.addEventListener('message', event => {\n on_message(event.data, websocket)\n })\n })\n}\n\n\n/** 接收到消息后的处理函数 \n 返回值可以是:\n - 数组: 会自动被封装为 { id: 相同, data: 返回值, done: true } 这样的消息并调用 websocket.send 将其发送\n - void: 什么都不做\n - 以上的 promise */\nexport type MessageHandler = (message: Message, websocket?: WebSocket) => void | any[] | Promise<void | any[]>\n\n\n/** 二进制消息格式 \n - json.length (小端序): 4 字节\n - json 数据\n - binary 数据\n*/\nexport interface Message <TData extends any[] = any[]> {\n /** rpc id: 在 rpc 系统中认为是唯一的。用来在单个 websocket 连接上复用多个 rpc 请求。多个相同 id 的 message 组成一个请求流 */\n id?: number\n \n /** 只在 rpc 发起时指定被调用的 function name,发起时 rpc 时必传 */\n func?: string\n \n /** 通过这个 flag 主动表明这是发往对方的最后一个 message, 对方可以销毁 handler 了 \n 并非强制,可以不说明,由双方的函数自己约定\n */\n done?: boolean\n \n /** 通知对方这里产生的错误,本质上类似 data 也是一种数据,并不代表 rpc 的结束,后续可能继续有 rpc message 交换 */\n error?: Error\n \n /** data 是一个数组, 作为:\n - rpc 发起方调用 func 的参数,或者请求流 message 携带的数据\n - 结果或者响应流的数据,传给请求发起方\n \n 里面是可序列化为 json 的 js 变量,或者是 Uint8Array \n Uint8Array 的参数处理后被替换为 Uint8Array.byteLength, 并将下标记录在 bins 中\n \n 注意: 数组中如果有 undefined 值,传输到对面会变成 null 值\n */\n data?: TData\n \n /** bins: data 中哪些下标对应的原始值是 Uint8Array 类型的,如: [0, 3] */\n bins?: number[]\n}\n\n/** 通过创建 remote 对象对 websocket rpc 进行抽象 \n 调用方使用 remote.call 进行调用 \n 被调方在创建 remote 对象时传入 funcs 注册处理函数,并使用 remote.handle 方法处理 websocket message \n 未连接时自动连接,断开后自动重连 */\nexport class Remote {\n url: string\n \n /** 主动发起 websocket 连接的客户端 (构造函数传 url) 有这个属性 */\n websocket?: WebSocket\n \n /** 通过 rpc message.func 被调用的 rpc 函数 */\n funcs: Record<string, MessageHandler>\n \n /** map<id, message handler>: 通过 rpc message.id 找到对应的 handler, unary rpc 接收方不需要设置 handlers, 发送方需要 */\n handlers = new Map<number, MessageHandler>()\n \n \n print = false\n \n pconnect: Promise<any>\n \n \n get connected () {\n return this.websocket?.readyState === WebSocket.OPEN\n }\n \n \n static parse <TData extends any[] = any[]> (array_buffer: ArrayBuffer) {\n const buf = new Uint8Array(array_buffer as ArrayBuffer)\n const dv = new DataView(array_buffer)\n \n const len_json = dv.getUint32(0, true)\n \n let offset = 4 + len_json\n \n let message: Message<TData> = JSON.parse(decoder.decode(buf.subarray(4, offset)))\n \n if (message.bins) {\n const { bins } = message\n let { data } = message\n \n for (const ibin of bins) {\n const len_buf = data[ibin]\n data[ibin] = buf.subarray(offset, offset + len_buf)\n offset += len_buf\n }\n }\n \n if (message.error)\n message.error = Object.assign(new Error(), message.error)\n \n return message\n }\n \n \n static pack ({ id, func, data = [ ], done, error }: Message) {\n let data_ = new Array(data.length)\n let bins: number[] = [ ]\n let bufs: Uint8Array[] = [ ]\n \n for (let i = 0; i < data.length; i++) {\n const item = data[i]\n if (item instanceof Uint8Array) {\n bins.push(i)\n bufs.push(item)\n data_[i] = item.length\n } else\n data_[i] = item\n }\n \n const data_json = {\n id,\n ... func ? { func } : { },\n ... done ? { done } : { },\n ... error ? { error } : { },\n ... data_.length ? { data: data_ } : { },\n ... bins.length ? { bins } : { },\n }\n \n const str_json = encoder.encode(JSON.stringify(data_json))\n \n let dv = new DataView(new ArrayBuffer(4))\n \n dv.setUint32(0, str_json.length, true)\n \n return concat([dv, str_json, ... bufs])\n }\n \n \n constructor ({\n url, funcs = { }, websocket\n }: {\n url?: string, funcs?: Remote['funcs'], websocket?: WebSocket\n } = { }) {\n this.url = url\n this.funcs = funcs\n this.websocket = websocket\n }\n \n \n /** 幂等,保证 websocket 已连接,否则抛出异常,不需要手动调用,在其它方法中已默认自动重连 */\n async connect () {\n if (this.connected)\n return\n \n const ptail = this.pconnect\n \n let resolve: () => void\n this.pconnect = new Promise<void>((_resolve, _reject) => {\n resolve = _resolve\n })\n \n await ptail\n \n try {\n if (!this.connected)\n // 保存的 rpc 状态在 this.handlers, 与 websocket 无关,因此即使断开重连也不影响 rpc 的运行,即\n // 底层连接断开后自动重连对上层应该是无感知的,除非再次连接时失败\n this.websocket = await connect_websocket(this.url, { on_message: this.handle.bind(this) })\n } finally {\n resolve()\n }\n }\n \n \n disconnect () {\n this.websocket?.close()\n }\n \n \n /** 接收 websocket 连接的 remote 端必传 websocket 参数;发起端选传,如果传了必须等于 this.websocket \n 发送或连接出错时自动清理 message.id 对应的 handler */\n async send (message: Message, websocket?: WebSocket) {\n try {\n if (this.url) {\n assert(!websocket || websocket === this.websocket)\n await this.connect()\n websocket = this.websocket\n } else {\n assert(websocket)\n if (websocket.readyState !== WebSocket.OPEN)\n throw new Error(t('remote.send(): websocket client 已断开'))\n }\n \n if (!message.id)\n message.id = genid()\n \n websocket.send(Remote.pack(message))\n } catch (error) {\n if (message.id)\n this.handlers.delete(message.id)\n throw error\n }\n }\n \n \n /** 处理接收到的 websocket message 并解析, 根据 id dispatch 到对应的 handler 进行处理 \n 如果 message.done == true 则清理 handler \n 如果 handler 返回了值,则包装为 message 发送 */\n async handle (data: ArrayBuffer, websocket: WebSocket) {\n const message = Remote.parse(data)\n \n const { id, func, done } = message\n \n if (this.print)\n console.log(message)\n \n let handler: MessageHandler\n \n if (func)\n handler = this.funcs[func]\n else {\n handler = this.handlers.get(id)\n if (done)\n this.handlers.delete(id)\n }\n \n try {\n if (handler) {\n const data = await handler(message, websocket)\n if (data)\n await this.send({ id, data }, websocket)\n } else if (message.error)\n throw message.error\n else\n throw new Error(`${t('找不到 rpc handler')}: ${func ? `func: ${func.quote()}` : `id: ${id}`}`)\n } catch (error) {\n // handle 出错并不意味着 rpc 一定会结束,可能 error 是运行中的正常数据,所以不能清理 handler\n \n if (\n websocket.readyState === WebSocket.OPEN &&\n !message.error // 防止无限循环往对方发送 error, 只有在对方无错误时才可以发送\n )\n try { await this.send({ id, error, /* 不能设置 done 清理对面 handler, 理由同上 */ }, websocket) } catch { }\n \n // 再往上层抛出错误没有意义了,上层调用栈是 websocket.on('message') 之类的\n console.log(error)\n }\n }\n \n \n /** 调用 remote 中的 func, 只适用于最简单的一元 rpc (请求, 响应) */\n async call <TReturn extends any[] = any[]> (func: string, args?: any[]) {\n return new Promise<TReturn>(async (resolve, reject) => {\n const id = genid()\n \n this.handlers.set(id, (message: Message<TReturn>) => {\n const { error, data } = message\n if (error)\n reject(error)\n else\n resolve(data)\n this.handlers.delete(id)\n })\n \n try {\n await this.send({ id, func, data: args }) // 不需要 done: true, 因为对面的 remote.handlers 中不会有这个 id 的 handler\n } catch (error) {\n reject(error)\n }\n })\n }\n}\n\n"]}
|
package/net.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="cheerio" />
|
|
3
|
-
import { FormData, type Response } from 'undici';
|
|
3
|
+
import { FormData, type Response, type RequestInit } from 'undici';
|
|
4
4
|
import { WebSocket } from 'ws';
|
|
5
5
|
import { Cookie, CookieJar, MemoryCookieStore } from 'tough-cookie';
|
|
6
6
|
declare module 'tough-cookie' {
|
|
@@ -10,6 +10,7 @@ declare module 'tough-cookie' {
|
|
|
10
10
|
}
|
|
11
11
|
import './prototype.js';
|
|
12
12
|
import type { Encoding } from './file.js';
|
|
13
|
+
import { inspect } from './utils.js';
|
|
13
14
|
export declare enum MyProxy {
|
|
14
15
|
socks5 = "http://localhost:10080",
|
|
15
16
|
whistle = "http://localhost:8899"
|
|
@@ -17,7 +18,7 @@ export declare enum MyProxy {
|
|
|
17
18
|
export declare const cookies: {
|
|
18
19
|
store: MemoryCookieStore;
|
|
19
20
|
jar: CookieJar;
|
|
20
|
-
get(domain_or_url: string, str?: boolean):
|
|
21
|
+
get(domain_or_url: string, str?: boolean): Promise<string> | Cookie[] | Promise<Cookie[]>;
|
|
21
22
|
};
|
|
22
23
|
export { Cookie };
|
|
23
24
|
export interface BasicAuth {
|
|
@@ -45,6 +46,21 @@ export interface RequestOptions {
|
|
|
45
46
|
export interface RequestRawOptions extends RequestOptions {
|
|
46
47
|
raw: true;
|
|
47
48
|
}
|
|
49
|
+
export interface RequestError extends Error {
|
|
50
|
+
url: URL;
|
|
51
|
+
options: RequestInit;
|
|
52
|
+
response?: {
|
|
53
|
+
/** 状态码 */
|
|
54
|
+
status: number;
|
|
55
|
+
url: string;
|
|
56
|
+
headers: Headers;
|
|
57
|
+
ok: boolean;
|
|
58
|
+
type: ResponseType;
|
|
59
|
+
text: string;
|
|
60
|
+
redirected: boolean;
|
|
61
|
+
};
|
|
62
|
+
[inspect.custom]: Function;
|
|
63
|
+
}
|
|
48
64
|
/**
|
|
49
65
|
- url: 必须是完整 url
|
|
50
66
|
- options?:
|