xshell 1.0.14 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/file.d.ts +12 -20
- package/file.js +33 -47
- package/file.js.map +1 -1
- package/i18n/dict.json +21 -0
- package/net.browser.d.ts +17 -10
- package/net.browser.js +41 -24
- package/net.browser.js.map +1 -1
- package/net.d.ts +27 -20
- package/net.js +60 -39
- package/net.js.map +1 -1
- package/package.json +4 -5
- package/process.d.ts +1 -1
- package/process.js +3 -4
- package/process.js.map +1 -1
- package/server.js.map +1 -1
- package/utils.d.ts +10 -1
- package/utils.js +24 -1
- package/utils.js.map +1 -1
- package/myfont.woff2 +0 -0
- package/myfontb.woff2 +0 -0
package/file.d.ts
CHANGED
|
@@ -15,7 +15,8 @@ declare module 'memfs' {
|
|
|
15
15
|
}
|
|
16
16
|
export * from './ufs.js';
|
|
17
17
|
export { MFS };
|
|
18
|
-
export type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | '
|
|
18
|
+
export type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | 'utf-16le';
|
|
19
|
+
export declare const encodings: readonly ["utf-8", "gb18030", "shift-jis", "utf-16le"];
|
|
19
20
|
/** fp 所指向的 文件/ 文件夹 是否存在
|
|
20
21
|
Does the file/folder pointed to by fp exist? */
|
|
21
22
|
export declare function fexists(fp: string, { print }?: {
|
|
@@ -47,12 +48,12 @@ export declare function fread(fp: string, { dir, encoding, print }?: {
|
|
|
47
48
|
}): Promise<Buffer>;
|
|
48
49
|
export declare function fread(fp: string, { dir, encoding, print }?: {
|
|
49
50
|
dir?: string;
|
|
50
|
-
encoding?: Encoding
|
|
51
|
+
encoding?: Encoding;
|
|
51
52
|
print?: boolean;
|
|
52
53
|
}): Promise<string>;
|
|
53
54
|
export declare function fread_lines(fp: string, options?: {
|
|
54
55
|
dir?: string;
|
|
55
|
-
encoding?:
|
|
56
|
+
encoding?: Encoding;
|
|
56
57
|
print?: boolean;
|
|
57
58
|
}): Promise<string[]>;
|
|
58
59
|
export declare function fread_json<T = any>(fp: string, options?: {
|
|
@@ -60,18 +61,18 @@ export declare function fread_json<T = any>(fp: string, options?: {
|
|
|
60
61
|
encoding?: Encoding;
|
|
61
62
|
print?: boolean;
|
|
62
63
|
}): Promise<T>;
|
|
63
|
-
|
|
64
|
+
/** 写入 data 到 fp 路径所指的文件
|
|
65
|
+
- fp: 目标文件完整路径
|
|
66
|
+
- data: 支持下面几种类型
|
|
67
|
+
- string: 写入文本
|
|
68
|
+
- Uint8Array, Buffer: 写入二进制 buffer
|
|
69
|
+
- any: 通过 JSON.stringify 转为文本后写入文件 */
|
|
70
|
+
export declare function fwrite(fp: string | FileHandle, data: string | Uint8Array | any, { dir, print, mkdir, }?: {
|
|
64
71
|
dir?: string;
|
|
65
72
|
print?: boolean;
|
|
66
73
|
mkdir?: boolean;
|
|
67
74
|
}): Promise<void>;
|
|
68
|
-
export declare function
|
|
69
|
-
dir?: string;
|
|
70
|
-
encoding?: Encoding;
|
|
71
|
-
print?: boolean;
|
|
72
|
-
mkdir?: boolean;
|
|
73
|
-
}): Promise<void>;
|
|
74
|
-
export declare function fappend(fp: string, data: any, { dir, print }?: {
|
|
75
|
+
export declare function fappend(fp: string, data: string | Uint8Array, { dir, print }?: {
|
|
75
76
|
dir?: string;
|
|
76
77
|
print?: boolean;
|
|
77
78
|
}): Promise<void>;
|
|
@@ -208,12 +209,3 @@ export declare function fwatch(fp: string, onchange: (event: string, fname: stri
|
|
|
208
209
|
}): Promise<fs.FSWatcher>;
|
|
209
210
|
/** 打开一个文件并搜索替换某个 pattern open a file and replace certain pattern */
|
|
210
211
|
export declare function freplace(fp: string, pattern: string | RegExp, replacement: string): Promise<void>;
|
|
211
|
-
/** 将文件编码转为 UTF-8 convert file encoding to UTF-8
|
|
212
|
-
- fp: 文件完整路径 file absolute path
|
|
213
|
-
- options?:
|
|
214
|
-
- dryrun?: `true`
|
|
215
|
-
- encoding?: `'auto'` */
|
|
216
|
-
export declare function f2utf8(fp: string, { dryrun, encoding, }?: {
|
|
217
|
-
dryrun?: boolean;
|
|
218
|
-
encoding?: Encoding | 'auto';
|
|
219
|
-
}): Promise<void>;
|
package/file.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { promises as fsp, default as fs, } from 'fs';
|
|
2
|
+
import { isUint8Array } from 'util/types';
|
|
2
3
|
import path from 'upath';
|
|
3
|
-
import iconv from 'iconv-lite';
|
|
4
4
|
import fse from 'fs-extra';
|
|
5
|
-
import archiver from 'archiver';
|
|
6
5
|
import debounce from 'lodash/debounce.js';
|
|
7
6
|
import MFS from 'memfs';
|
|
8
7
|
import { t } from './i18n/instance.js';
|
|
@@ -10,6 +9,7 @@ import { to_json } from './prototype.js';
|
|
|
10
9
|
import { assert, WritableMemoryStream } from './utils.js';
|
|
11
10
|
export * from './ufs.js';
|
|
12
11
|
export { MFS };
|
|
12
|
+
export const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'];
|
|
13
13
|
/** fp 所指向的 文件/ 文件夹 是否存在
|
|
14
14
|
Does the file/folder pointed to by fp exist? */
|
|
15
15
|
export function fexists(fp, { print = true } = {}) {
|
|
@@ -39,10 +39,13 @@ export function create_mfs() {
|
|
|
39
39
|
return mfs;
|
|
40
40
|
}
|
|
41
41
|
export async function fread(fp, { dir, encoding = 'utf-8', print = true } = {}) {
|
|
42
|
-
if (dir)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
if (dir) {
|
|
43
|
+
assert(dir.endsWith('/'), t('dir 必须以 / 结尾'));
|
|
44
|
+
fp = dir + fp;
|
|
45
|
+
}
|
|
46
|
+
assert(!fp.endsWith('/'), t('fp 必须是文件,不能以 / 结尾'));
|
|
47
|
+
assert(path.isAbsolute(fp), `${t('fp 必须是绝对路径:')} ${fp}`);
|
|
48
|
+
assert(encoding !== 'auto');
|
|
46
49
|
if (print)
|
|
47
50
|
console.log(t('读取'), fp);
|
|
48
51
|
switch (encoding) {
|
|
@@ -50,16 +53,9 @@ export async function fread(fp, { dir, encoding = 'utf-8', print = true } = {})
|
|
|
50
53
|
return fsp.readFile(fp, { encoding: 'utf-8' });
|
|
51
54
|
case 'binary':
|
|
52
55
|
return fsp.readFile(fp);
|
|
53
|
-
default:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const { detect } = await import('chardet');
|
|
57
|
-
encoding = detect(buffer);
|
|
58
|
-
if (print)
|
|
59
|
-
console.log(fp + t(' 的编码可能是 ') + encoding.toLowerCase());
|
|
60
|
-
}
|
|
61
|
-
return iconv.decode(buffer, encoding);
|
|
62
|
-
}
|
|
56
|
+
default:
|
|
57
|
+
return new TextDecoder(encoding)
|
|
58
|
+
.decode(await fsp.readFile(fp));
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
export async function fread_lines(fp, options = {}) {
|
|
@@ -69,23 +65,28 @@ export async function fread_lines(fp, options = {}) {
|
|
|
69
65
|
export async function fread_json(fp, options = {}) {
|
|
70
66
|
return JSON.parse(await fread(fp, options));
|
|
71
67
|
}
|
|
72
|
-
|
|
68
|
+
/** 写入 data 到 fp 路径所指的文件
|
|
69
|
+
- fp: 目标文件完整路径
|
|
70
|
+
- data: 支持下面几种类型
|
|
71
|
+
- string: 写入文本
|
|
72
|
+
- Uint8Array, Buffer: 写入二进制 buffer
|
|
73
|
+
- any: 通过 JSON.stringify 转为文本后写入文件 */
|
|
74
|
+
export async function fwrite(fp, data, { dir, print = true, mkdir = false, } = {}) {
|
|
73
75
|
const is_handle = typeof fp === 'object' && fp && 'fd' in fp;
|
|
74
76
|
if (is_handle) {
|
|
75
77
|
if (print)
|
|
76
78
|
console.log(t('写入'), fp.fp);
|
|
77
79
|
}
|
|
78
80
|
else {
|
|
79
|
-
if (dir)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
if (dir) {
|
|
82
|
+
assert(dir.endsWith('/'), t('dir 必须以 / 结尾'));
|
|
83
|
+
fp = dir + fp;
|
|
84
|
+
}
|
|
85
|
+
assert(path.isAbsolute(fp), `${t('fp 必须是绝对路径,当前为:')} ${fp}`);
|
|
83
86
|
if (print)
|
|
84
87
|
console.log(t('写入'), fp);
|
|
85
88
|
}
|
|
86
|
-
if (
|
|
87
|
-
data = iconv.encode(data, encoding);
|
|
88
|
-
if (!Buffer.isBuffer(data) && typeof data !== 'string')
|
|
89
|
+
if (!isUint8Array(data) && typeof data !== 'string')
|
|
89
90
|
data = to_json(data);
|
|
90
91
|
try {
|
|
91
92
|
await fsp.writeFile(fp, data);
|
|
@@ -98,14 +99,14 @@ export async function fwrite(fp, data, { dir, encoding = 'utf-8', print = true,
|
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
export async function fappend(fp, data, { dir, print = true } = {}) {
|
|
101
|
-
if (dir)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
if (dir) {
|
|
103
|
+
assert(dir.endsWith('/'), t('dir 必须以 / 结尾'));
|
|
104
|
+
fp = dir + fp;
|
|
105
|
+
}
|
|
106
|
+
assert(path.isAbsolute(fp), `${t('fp 必须是绝对路径,当前为:')} ${fp}`);
|
|
105
107
|
if (print)
|
|
106
108
|
console.log(t('追加'), fp);
|
|
107
|
-
|
|
108
|
-
throw new Error(t('data 不是 Buffer 或 string'));
|
|
109
|
+
assert(isUint8Array(data) || typeof data === 'string');
|
|
109
110
|
await fsp.appendFile(fp, data);
|
|
110
111
|
}
|
|
111
112
|
export async function flist(fpd, options = {}) {
|
|
@@ -291,7 +292,8 @@ export async function fzip(data, fp_zip, { dirname, print = { files: true, info:
|
|
|
291
292
|
entries = data;
|
|
292
293
|
if (print.info)
|
|
293
294
|
console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} → ${fp_zip ? `${fp_zip}/${dirname}` : '内存'}`);
|
|
294
|
-
|
|
295
|
+
const { default: archiver } = await import('archiver');
|
|
296
|
+
let archive = archiver('zip', { zlib: { chunkSize: 16 * 2 ** 20 /* 16 MB */ } });
|
|
295
297
|
let ostream = fp_zip ? fs.createWriteStream(fp_zip) : new WritableMemoryStream();
|
|
296
298
|
const size = await new Promise((resolve, reject) => {
|
|
297
299
|
ostream.once('close', () => {
|
|
@@ -367,20 +369,4 @@ export async function freplace(fp, pattern, replacement) {
|
|
|
367
369
|
await fwrite(fp, (await fread(fp))
|
|
368
370
|
.replaceAll(pattern, replacement));
|
|
369
371
|
}
|
|
370
|
-
/** 将文件编码转为 UTF-8 convert file encoding to UTF-8
|
|
371
|
-
- fp: 文件完整路径 file absolute path
|
|
372
|
-
- options?:
|
|
373
|
-
- dryrun?: `true`
|
|
374
|
-
- encoding?: `'auto'` */
|
|
375
|
-
export async function f2utf8(fp, { dryrun = true, encoding = 'auto', } = {}) {
|
|
376
|
-
const text = await fread(fp, { encoding });
|
|
377
|
-
if (dryrun) {
|
|
378
|
-
console.log(text.slice(0, 10000));
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
const fp_bak = `${fp.fdir}${fp.fname.replace(/(.*?)(\.[^.]+)?$/, '$1.bak$2')}`;
|
|
382
|
-
if (!fexists(fp_bak))
|
|
383
|
-
await fcopy(fp, fp_bak);
|
|
384
|
-
await fwrite(fp, text);
|
|
385
|
-
}
|
|
386
372
|
//# sourceMappingURL=file.js.map
|
package/file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 if (!dirname.endsWith('/'))\n throw new Error('dirname 需要以 / 结尾')\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"]}
|
|
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 { isUint8Array } from 'util/types'\n\n\nimport path from 'upath'\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, WritableMemoryStream } from './utils.js'\n\n\nexport * from './ufs.js'\n\nexport { MFS }\n\nexport type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | 'utf-16le'\n\nexport const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'] as const\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, 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 | 'binary'\n print?: boolean } = { }\n) {\n if (dir) {\n assert(dir.endsWith('/'), t('dir 必须以 / 结尾'))\n fp = dir + fp\n }\n \n assert(!fp.endsWith('/'), t('fp 必须是文件,不能以 / 结尾'))\n assert(path.isAbsolute(fp), `${t('fp 必须是绝对路径:')} ${fp}`)\n assert((encoding as string) !== 'auto')\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 return new TextDecoder(encoding)\n .decode(await fsp.readFile(fp))\n }\n}\n\nexport async function fread_lines (fp: string, options: { dir?: string, encoding?: Encoding, 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\n/** 写入 data 到 fp 路径所指的文件 \n - fp: 目标文件完整路径\n - data: 支持下面几种类型\n - string: 写入文本\n - Uint8Array, Buffer: 写入二进制 buffer\n - any: 通过 JSON.stringify 转为文本后写入文件 */\nexport async function fwrite (\n fp: string | FileHandle,\n data: string | Uint8Array | any,\n {\n dir,\n print = true,\n mkdir = false,\n }: {\n dir?: string\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 assert(dir.endsWith('/'), t('dir 必须以 / 结尾'))\n fp = dir + fp\n }\n \n assert(path.isAbsolute(fp as string), `${t('fp 必须是绝对路径,当前为:')} ${fp}`)\n \n if (print)\n console.log(t('写入'), fp)\n }\n \n if (!isUint8Array(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: string | Uint8Array, { dir, print = true }: { dir?: string, print?: boolean } = { }) {\n if (dir) {\n assert(dir.endsWith('/'), t('dir 必须以 / 结尾'))\n fp = dir + fp\n }\n \n assert(path.isAbsolute(fp), `${t('fp 必须是绝对路径,当前为:')} ${fp}`)\n \n if (print)\n console.log(t('追加'), fp)\n \n assert(isUint8Array(data) || typeof data === '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) {\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 FStats\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 if (!dirname.endsWith('/'))\n throw new Error('dirname 需要以 / 结尾')\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 const { default: archiver } = await import('archiver')\n \n let archive = archiver('zip', { zlib: { chunkSize: 16 * 2**20 /* 16 MB */ } })\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"]}
|
package/i18n/dict.json
CHANGED
|
@@ -271,5 +271,26 @@
|
|
|
271
271
|
},
|
|
272
272
|
"传入 request 的 headers 参数中 key 应该都是小写的,实际为 {{key}}": {
|
|
273
273
|
"en": "The key in the headers parameter of the incoming request should be all lowercase, and it is actually {{key}}"
|
|
274
|
+
},
|
|
275
|
+
"dir 必须以 / 结尾": {
|
|
276
|
+
"en": "dir must end with /"
|
|
277
|
+
},
|
|
278
|
+
"fp 必须是文件,不能以 / 结尾": {
|
|
279
|
+
"en": "fp must be a file and cannot end with /"
|
|
280
|
+
},
|
|
281
|
+
"fp 必须是绝对路径:": {
|
|
282
|
+
"en": "fp must be an absolute path:"
|
|
283
|
+
},
|
|
284
|
+
"fp 必须是绝对路径,当前为:": {
|
|
285
|
+
"en": "fp must be an absolute path, currently:"
|
|
286
|
+
},
|
|
287
|
+
"已正常关闭": {
|
|
288
|
+
"en": "closed normally"
|
|
289
|
+
},
|
|
290
|
+
"websocket close 事件时应该已经 settled": {
|
|
291
|
+
"en": "Promise should have been settled in websocket close event"
|
|
292
|
+
},
|
|
293
|
+
"连接被关闭": {
|
|
294
|
+
"en": "connection closed"
|
|
274
295
|
}
|
|
275
296
|
}
|
package/net.browser.d.ts
CHANGED
|
@@ -63,25 +63,32 @@ export declare function request_json<T = any>(url: string, options?: RequestOpti
|
|
|
63
63
|
export declare class WebSocketConnectionError extends Error {
|
|
64
64
|
name: string;
|
|
65
65
|
websocket: WebSocket;
|
|
66
|
-
|
|
66
|
+
event: WebSocketEventMap['close' | 'error'];
|
|
67
|
+
type: 'close' | 'error';
|
|
68
|
+
code?: number;
|
|
69
|
+
reason?: string;
|
|
70
|
+
constructor(websocket: WebSocket, event: WebSocketConnectionError['event'], message?: string);
|
|
67
71
|
}
|
|
68
72
|
/** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket
|
|
69
|
-
遇到 error 时会创建 WebSocketConnectionError
|
|
73
|
+
遇到 error 时会创建 WebSocketConnectionError:
|
|
74
|
+
- reject 掉返回的 promise (若此时未 settle)
|
|
75
|
+
- 作为参数调用 on_error (已 settle 且有 on_error 回调)
|
|
76
|
+
可以用 WebSocket.bufferedAmount 来显示大消息的发送进度
|
|
77
|
+
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount
|
|
70
78
|
- url
|
|
71
79
|
- options:
|
|
72
80
|
- protocols?
|
|
73
81
|
- on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string
|
|
74
82
|
https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
- on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
|
|
84
|
+
type 为 'close' 时有 code 和 reason 属性
|
|
85
|
+
- on_close?: 和 websocket 的 'close' 事件不相同,只在正常关闭 (close code 为 1000) 时才调用,否则都会调用 on_error
|
|
86
|
+
https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes */
|
|
87
|
+
export declare function connect_websocket(url: string | URL, { protocols, on_message, on_error, on_close, }: {
|
|
78
88
|
protocols?: string | string[];
|
|
79
|
-
on_close?(event: {
|
|
80
|
-
code: number;
|
|
81
|
-
reason: string;
|
|
82
|
-
}, websocket: WebSocket): any;
|
|
83
|
-
on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
|
|
84
89
|
on_message(data: ArrayBuffer | string, websocket: WebSocket): any;
|
|
90
|
+
on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
|
|
91
|
+
on_close?(event: CloseEvent, websocket: WebSocket): any;
|
|
85
92
|
}): Promise<WebSocket>;
|
|
86
93
|
/** 接收到消息后的处理函数
|
|
87
94
|
返回值可以是:
|
package/net.browser.js
CHANGED
|
@@ -181,27 +181,43 @@ let encoder = new TextEncoder();
|
|
|
181
181
|
export class WebSocketConnectionError extends Error {
|
|
182
182
|
name = 'WebSocketConnectionError';
|
|
183
183
|
websocket;
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
event;
|
|
185
|
+
type;
|
|
186
|
+
code;
|
|
187
|
+
reason;
|
|
188
|
+
constructor(websocket, event, message) {
|
|
189
|
+
super(`${websocket.url} ${t('连接出错了')}. ${message || ''}`);
|
|
186
190
|
this.websocket = websocket;
|
|
191
|
+
this.event = event;
|
|
192
|
+
this.type = event.type;
|
|
193
|
+
if (this.type === 'close') {
|
|
194
|
+
this.code = event.code;
|
|
195
|
+
this.reason = event.reason;
|
|
196
|
+
}
|
|
187
197
|
}
|
|
188
198
|
}
|
|
189
199
|
/** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket
|
|
190
|
-
遇到 error 时会创建 WebSocketConnectionError
|
|
200
|
+
遇到 error 时会创建 WebSocketConnectionError:
|
|
201
|
+
- reject 掉返回的 promise (若此时未 settle)
|
|
202
|
+
- 作为参数调用 on_error (已 settle 且有 on_error 回调)
|
|
203
|
+
可以用 WebSocket.bufferedAmount 来显示大消息的发送进度
|
|
204
|
+
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount
|
|
191
205
|
- url
|
|
192
206
|
- options:
|
|
193
207
|
- protocols?
|
|
194
208
|
- on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string
|
|
195
209
|
https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
|
|
196
|
-
-
|
|
197
|
-
|
|
198
|
-
|
|
210
|
+
- on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
|
|
211
|
+
type 为 'close' 时有 code 和 reason 属性
|
|
212
|
+
- on_close?: 和 websocket 的 'close' 事件不相同,只在正常关闭 (close code 为 1000) 时才调用,否则都会调用 on_error
|
|
213
|
+
https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes */
|
|
214
|
+
export async function connect_websocket(url, { protocols, on_message, on_error, on_close, }) {
|
|
199
215
|
let websocket = new WebSocket(url, protocols);
|
|
200
216
|
// https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543
|
|
201
217
|
websocket.binaryType = 'arraybuffer';
|
|
202
218
|
return new Promise((resolve, reject) => {
|
|
203
219
|
let settled = false;
|
|
204
|
-
websocket.addEventListener('open',
|
|
220
|
+
websocket.addEventListener('open', event => {
|
|
205
221
|
console.log(websocket.url +
|
|
206
222
|
(protocols ?
|
|
207
223
|
' ' + (typeof protocols === 'string' ? protocols : protocols.join(', ').bracket('square')).bracket()
|
|
@@ -212,27 +228,28 @@ export async function connect_websocket(url, { protocols, on_close, on_error, on
|
|
|
212
228
|
resolve(websocket);
|
|
213
229
|
});
|
|
214
230
|
websocket.addEventListener('close', event => {
|
|
215
|
-
if (event.code === 1000)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
231
|
+
if (event.code === 1000) // 正常关闭
|
|
232
|
+
if (on_close)
|
|
233
|
+
on_close(event, websocket);
|
|
234
|
+
else
|
|
235
|
+
console.log(`${websocket.url} ${t('已正常关闭')}`);
|
|
236
|
+
else { // 异常关闭,认为发生了错误,进行错误处理
|
|
237
|
+
assert(settled, t('websocket close 事件时应该已经 settled'));
|
|
238
|
+
const error = new WebSocketConnectionError(websocket, event, `${t('连接被关闭')}, code: ${event.code}${event.reason ? `, ${t('原因')}: ${event.reason}` : ''}`);
|
|
239
|
+
if (on_error)
|
|
240
|
+
on_error(error, websocket);
|
|
241
|
+
else // 既然用户不传 on_error, 就当 unhandled error 抛出来
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
220
244
|
});
|
|
221
245
|
websocket.addEventListener('error', event => {
|
|
222
|
-
const error = new WebSocketConnectionError(websocket);
|
|
223
|
-
|
|
224
|
-
on_error
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (settled)
|
|
246
|
+
const error = new WebSocketConnectionError(websocket, event);
|
|
247
|
+
if (settled) {
|
|
248
|
+
if (on_error)
|
|
249
|
+
on_error(error, websocket);
|
|
250
|
+
else // 既然用户不传 on_error, 就当 unhandled error 抛出来
|
|
228
251
|
throw error;
|
|
229
|
-
else {
|
|
230
|
-
settled = true;
|
|
231
|
-
reject(error);
|
|
232
|
-
}
|
|
233
252
|
}
|
|
234
|
-
if (settled)
|
|
235
|
-
throw error;
|
|
236
253
|
else {
|
|
237
254
|
settled = true;
|
|
238
255
|
reject(error);
|