xshell 1.2.30 → 1.2.31
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/fflate.d.ts +359 -0
- package/fflate.js +1175 -0
- package/file.d.ts +41 -0
- package/file.js +220 -3
- package/net.d.ts +1 -1
- package/package.json +7 -7
- package/path.d.ts +2 -2
package/file.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { promises as fsp, default as fs } from 'fs';
|
|
2
|
+
import type { UnzipFileFilter } from './fflate.ts';
|
|
2
3
|
export { fsp };
|
|
3
4
|
export type Encoding = 'utf-8' | 'gb18030' | 'shift-jis' | 'utf-16le';
|
|
4
5
|
export type FileHandle = fsp.FileHandle & {
|
|
@@ -220,6 +221,46 @@ export declare function fzip(data: string | Record<string, string | Uint8Array>,
|
|
|
220
221
|
- info?: `true` 开始压缩、压缩完成
|
|
221
222
|
- files?: `true` 打印压缩文件列表 */
|
|
222
223
|
export declare function zip(data: string | Record<string, string | Uint8Array>, options?: ZipOptions): Promise<Buffer>;
|
|
224
|
+
export interface UnzipOptions {
|
|
225
|
+
encoding?: Encoding;
|
|
226
|
+
dryrun?: boolean;
|
|
227
|
+
print?: {
|
|
228
|
+
info: boolean;
|
|
229
|
+
files: boolean;
|
|
230
|
+
};
|
|
231
|
+
strip?: boolean;
|
|
232
|
+
clean?: boolean;
|
|
233
|
+
filter?: UnzipFileFilter;
|
|
234
|
+
}
|
|
235
|
+
/** 解压 zip 包至文件夹,返回 fpd_out
|
|
236
|
+
- zip:
|
|
237
|
+
- 包路径 (string) 或
|
|
238
|
+
- 包数据 (Uint8Array | ArrayBuffer)
|
|
239
|
+
- fpd_out: 解压到文件夹的完整路径 (string)
|
|
240
|
+
- options?:
|
|
241
|
+
- encoding?: `utf-8` 压缩包文件名编码
|
|
242
|
+
- dryrun?: 只是打印一下文件名列表,看看编码是否正确,不实际解压
|
|
243
|
+
- print?:
|
|
244
|
+
- info?: `true` 开始解压、解压完成
|
|
245
|
+
- files?: `true` 打印解压缩的文件列表
|
|
246
|
+
- strip?: `true` 压缩包内只有一个顶层文件夹时自动去除该层级
|
|
247
|
+
- clean?: `true` 忽略解压 ftrashes 这些垃圾文件
|
|
248
|
+
- filter?: 用于过滤要解压的文件, 返回 falsy 值时忽略这个文件,要注意 file.name 为完整的相对路径(没有 strip) */
|
|
249
|
+
export declare function funzip(zip: string | Uint8Array | ArrayBuffer, fpd_out: string, options?: UnzipOptions): Promise<string>;
|
|
250
|
+
/** 解压 zip 包至内存,返回解压后的数据 (Record<文件或文件夹 (以 / 结尾) 的相对路径, Uint8Array>)
|
|
251
|
+
- zip:
|
|
252
|
+
- 压缩文件路径 (string) 或
|
|
253
|
+
- 压缩文件内容 (buffer)
|
|
254
|
+
- options?:
|
|
255
|
+
- encoding?: `utf-8` 压缩包文件名编码
|
|
256
|
+
- dryrun?: 只是打印一下文件名列表,看看编码是否正确,不实际解压
|
|
257
|
+
- print?:
|
|
258
|
+
- info?: `true` 开始解压、解压完成
|
|
259
|
+
- files?: `true` 打印解压缩的文件列表
|
|
260
|
+
- strip?: `true` 压缩包内只有一个顶层文件夹时自动去除该层级
|
|
261
|
+
- clean?: `true` 忽略解压 ftrashes 这些垃圾文件
|
|
262
|
+
- filter?: 用于过滤要解压的文件, 返回 falsy 值时忽略这个文件,要注意 file.name 为完整的相对路径(没有 strip) */
|
|
263
|
+
export declare function unzip(zip: string | Uint8Array | ArrayBuffer, options?: UnzipOptions): Promise<Record<string, Uint8Array>>;
|
|
223
264
|
export declare let fwatchers: Record<string, fs.FSWatcher>;
|
|
224
265
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
225
266
|
export declare function ftail(fp: string, handler: (lines: string[]) => void | Promise<void>, { print }?: {
|
package/file.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { promises as fsp, default as fs } from 'fs';
|
|
2
|
-
import { isUint8Array } from 'util/types';
|
|
2
|
+
import { isArrayBuffer, isUint8Array } from 'util/types';
|
|
3
3
|
import { t } from "./i18n/instance.js";
|
|
4
|
-
import { to_json } from "./prototype.js";
|
|
4
|
+
import { noop, to_json } from "./prototype.js";
|
|
5
5
|
import { pack, parse } from "./io.js";
|
|
6
6
|
import { path } from "./path.js";
|
|
7
|
-
import { check, Lock, WritableMemoryStream, url_width, throttle } from "./utils.js";
|
|
7
|
+
import { check, Lock, WritableMemoryStream, url_width, throttle, decode } from "./utils.js";
|
|
8
8
|
import { noprint } from "./process.js";
|
|
9
9
|
export { fsp };
|
|
10
10
|
export const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'];
|
|
@@ -545,6 +545,223 @@ async function _zip(data, fp_zip, { dirname, print = { files: true, info: true }
|
|
|
545
545
|
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
546
546
|
return fp_zip || ostream.pbuffer;
|
|
547
547
|
}
|
|
548
|
+
/** 解压 zip 包至文件夹,返回 fpd_out
|
|
549
|
+
- zip:
|
|
550
|
+
- 包路径 (string) 或
|
|
551
|
+
- 包数据 (Uint8Array | ArrayBuffer)
|
|
552
|
+
- fpd_out: 解压到文件夹的完整路径 (string)
|
|
553
|
+
- options?:
|
|
554
|
+
- encoding?: `utf-8` 压缩包文件名编码
|
|
555
|
+
- dryrun?: 只是打印一下文件名列表,看看编码是否正确,不实际解压
|
|
556
|
+
- print?:
|
|
557
|
+
- info?: `true` 开始解压、解压完成
|
|
558
|
+
- files?: `true` 打印解压缩的文件列表
|
|
559
|
+
- strip?: `true` 压缩包内只有一个顶层文件夹时自动去除该层级
|
|
560
|
+
- clean?: `true` 忽略解压 ftrashes 这些垃圾文件
|
|
561
|
+
- filter?: 用于过滤要解压的文件, 返回 falsy 值时忽略这个文件,要注意 file.name 为完整的相对路径(没有 strip) */
|
|
562
|
+
export async function funzip(zip, fpd_out, options) {
|
|
563
|
+
await _unzip(zip, fpd_out, options);
|
|
564
|
+
return fpd_out;
|
|
565
|
+
}
|
|
566
|
+
/** 解压 zip 包至内存,返回解压后的数据 (Record<文件或文件夹 (以 / 结尾) 的相对路径, Uint8Array>)
|
|
567
|
+
- zip:
|
|
568
|
+
- 压缩文件路径 (string) 或
|
|
569
|
+
- 压缩文件内容 (buffer)
|
|
570
|
+
- options?:
|
|
571
|
+
- encoding?: `utf-8` 压缩包文件名编码
|
|
572
|
+
- dryrun?: 只是打印一下文件名列表,看看编码是否正确,不实际解压
|
|
573
|
+
- print?:
|
|
574
|
+
- info?: `true` 开始解压、解压完成
|
|
575
|
+
- files?: `true` 打印解压缩的文件列表
|
|
576
|
+
- strip?: `true` 压缩包内只有一个顶层文件夹时自动去除该层级
|
|
577
|
+
- clean?: `true` 忽略解压 ftrashes 这些垃圾文件
|
|
578
|
+
- filter?: 用于过滤要解压的文件, 返回 falsy 值时忽略这个文件,要注意 file.name 为完整的相对路径(没有 strip) */
|
|
579
|
+
export async function unzip(zip, options) {
|
|
580
|
+
return _unzip(zip, undefined, options);
|
|
581
|
+
}
|
|
582
|
+
async function _unzip(zip, fpd_out, { encoding = 'utf-8', dryrun = false, print = {
|
|
583
|
+
files: true,
|
|
584
|
+
info: true
|
|
585
|
+
}, strip = true, clean = true, filter: _filter } = {}) {
|
|
586
|
+
const str_out = typeof fpd_out === 'string' ? fpd_out : '内存';
|
|
587
|
+
let fp_zip = 'buffer';
|
|
588
|
+
let nfiles = 0;
|
|
589
|
+
let size_uncompressed = 0;
|
|
590
|
+
if (isArrayBuffer(zip))
|
|
591
|
+
zip = new Uint8Array(zip);
|
|
592
|
+
else if (typeof zip === 'string') {
|
|
593
|
+
check(['zip', 'apk', 'crx', 'vsix'].includes(zip.fext), 'fp_src 应该以 zip 等后缀结尾');
|
|
594
|
+
fp_zip = zip;
|
|
595
|
+
zip = await fread(zip, { encoding: 'binary', print: false });
|
|
596
|
+
}
|
|
597
|
+
if (print.info)
|
|
598
|
+
log_action(`开始${dryrun ? '测试' : ''}解压`, `${fp_zip} (${zip.length.to_fsize_str()})`, str_out);
|
|
599
|
+
if (!dryrun && fpd_out)
|
|
600
|
+
await fmkdir(fpd_out, { print: print.info });
|
|
601
|
+
let dryrun_unzipped = {};
|
|
602
|
+
const { unzipSync } = await import("./fflate.js");
|
|
603
|
+
let unzipped = unzipSync(zip, {
|
|
604
|
+
decoder: encoding === 'utf-8'
|
|
605
|
+
? decode
|
|
606
|
+
: (() => {
|
|
607
|
+
let text_decoder = new TextDecoder(encoding);
|
|
608
|
+
return buf => text_decoder.decode(buf);
|
|
609
|
+
})(),
|
|
610
|
+
filter(file) {
|
|
611
|
+
const { name, originalSize } = file;
|
|
612
|
+
// 需要递归的清理 LICENSE, .husky/, .husky/pre-commit 等文件
|
|
613
|
+
if (clean) {
|
|
614
|
+
const lname = name.toLowerCase();
|
|
615
|
+
let to_clean = false;
|
|
616
|
+
// xxx/xxx/xxx/a.txt
|
|
617
|
+
// xxx/xxx/
|
|
618
|
+
// a.txt
|
|
619
|
+
// xxx/
|
|
620
|
+
// 处理每个文件夹部分
|
|
621
|
+
let ileft = 0, iright = 0;
|
|
622
|
+
for (; (iright = lname.indexOf('/', ileft) + 1) !== 0; ileft = iright)
|
|
623
|
+
if (ftrashes.has(lname.slice(ileft, iright))) {
|
|
624
|
+
to_clean = true;
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
// 处理最后剩下的文件名
|
|
628
|
+
if (!to_clean && ileft < lname.length && ftrashes.has(lname.slice(ileft)))
|
|
629
|
+
to_clean = true;
|
|
630
|
+
if (to_clean) {
|
|
631
|
+
if (print.files)
|
|
632
|
+
console.log(`清理了 ${name}`);
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (!clean && name.startsWith('__MACOSX/') ||
|
|
637
|
+
_filter && !_filter(file))
|
|
638
|
+
return false;
|
|
639
|
+
else {
|
|
640
|
+
nfiles++;
|
|
641
|
+
size_uncompressed += originalSize;
|
|
642
|
+
if (dryrun) {
|
|
643
|
+
dryrun_unzipped[name] = null;
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
else
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
if (dryrun)
|
|
652
|
+
unzipped = dryrun_unzipped;
|
|
653
|
+
if (strip) {
|
|
654
|
+
let top_common_dir = '';
|
|
655
|
+
for (const key in unzipped) {
|
|
656
|
+
const islash = key.indexOf('/');
|
|
657
|
+
if (islash === -1) { // 顶层有文件
|
|
658
|
+
top_common_dir = '';
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
const top_dir = key.slice(0, islash + 1);
|
|
663
|
+
if (top_common_dir) {
|
|
664
|
+
if (top_common_dir !== top_dir) {
|
|
665
|
+
top_common_dir = '';
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
else
|
|
670
|
+
top_common_dir = top_dir;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (top_common_dir) {
|
|
674
|
+
let unzipped_ = {};
|
|
675
|
+
for (const key in unzipped) {
|
|
676
|
+
const key_ = key.slice(top_common_dir.length);
|
|
677
|
+
if (key_)
|
|
678
|
+
unzipped_[key_] = unzipped[key];
|
|
679
|
+
}
|
|
680
|
+
unzipped = unzipped_;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
let pwrites = [];
|
|
684
|
+
for (const key in unzipped) {
|
|
685
|
+
const value = unzipped[key];
|
|
686
|
+
if (fpd_out && !dryrun) {
|
|
687
|
+
const fp = fpd_out + key;
|
|
688
|
+
if (fp.isdir)
|
|
689
|
+
await fmkdir(fp, noprint);
|
|
690
|
+
else {
|
|
691
|
+
let pwrite = fwrite(fp, value, noprint);
|
|
692
|
+
pwrite.catch(noop); // suppress PromiseRejectionHandledWarning: Promise rejection was handled asynchronously
|
|
693
|
+
pwrites.push(pwrite);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
if (print.files)
|
|
697
|
+
console.log(`解压出 ${key}`);
|
|
698
|
+
}
|
|
699
|
+
if (fpd_out && !dryrun)
|
|
700
|
+
await Promise.all(pwrites);
|
|
701
|
+
if (print.info)
|
|
702
|
+
console.log(`解压了 ${nfiles} 个文件,解压后文件总大小为 ${size_uncompressed.to_fsize_str()}`);
|
|
703
|
+
if (!fpd_out || dryrun)
|
|
704
|
+
return unzipped;
|
|
705
|
+
}
|
|
706
|
+
const ftrashes = new Set([
|
|
707
|
+
'__MACOSX/',
|
|
708
|
+
'.babelrc.js',
|
|
709
|
+
'.babelrc',
|
|
710
|
+
'.ci',
|
|
711
|
+
'.circleci',
|
|
712
|
+
'.dockerignore',
|
|
713
|
+
'.DS_Store',
|
|
714
|
+
'.editorconfig',
|
|
715
|
+
'.eslintignore',
|
|
716
|
+
'.eslintrc.js',
|
|
717
|
+
'.eslintrc.json',
|
|
718
|
+
'.eslintrc.yaml',
|
|
719
|
+
'.eslintrc.yml',
|
|
720
|
+
'.eslintrc',
|
|
721
|
+
'.gitattributes',
|
|
722
|
+
'.github',
|
|
723
|
+
'.gitignore',
|
|
724
|
+
'.husky/',
|
|
725
|
+
'.jsbeautifyrc',
|
|
726
|
+
'.jshintrc',
|
|
727
|
+
'.mailmap',
|
|
728
|
+
'.markdownlint.js',
|
|
729
|
+
'.node-version',
|
|
730
|
+
'.npmignore',
|
|
731
|
+
'.prettierignore',
|
|
732
|
+
'.prettierrc.js',
|
|
733
|
+
'.prettierrc.json',
|
|
734
|
+
'.prettierrc.yaml',
|
|
735
|
+
'.prettierrc',
|
|
736
|
+
'.project',
|
|
737
|
+
'.releaserc.json',
|
|
738
|
+
'.stylelintrc.json',
|
|
739
|
+
'.travis.yml',
|
|
740
|
+
'.vscode/',
|
|
741
|
+
'AUTHORS.txt',
|
|
742
|
+
'AUTHORS',
|
|
743
|
+
'bower',
|
|
744
|
+
'CODE_OF_CONDUCT.md',
|
|
745
|
+
'codecov.yml',
|
|
746
|
+
'commitlint.config.js',
|
|
747
|
+
'CONTRIBUTING.md',
|
|
748
|
+
'COPING.md',
|
|
749
|
+
'husky.config.js',
|
|
750
|
+
'LICENCE.md',
|
|
751
|
+
'LICENCE.txt',
|
|
752
|
+
'LICENCE',
|
|
753
|
+
'LICENSE.md',
|
|
754
|
+
'LICENSE.txt',
|
|
755
|
+
'LICENSE',
|
|
756
|
+
'lint-staged.config.js',
|
|
757
|
+
'open-bot.yaml',
|
|
758
|
+
'package-lock.json',
|
|
759
|
+
'pnpm-lock.yaml',
|
|
760
|
+
'prettier.config.js',
|
|
761
|
+
'stylelint.config.js',
|
|
762
|
+
'tslint.json',
|
|
763
|
+
'yarn.lock',
|
|
764
|
+
].map(f => f.toLowerCase()));
|
|
548
765
|
export let fwatchers = {};
|
|
549
766
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
550
767
|
export async function ftail(fp, handler, { print = true } = {}) {
|
package/net.d.ts
CHANGED
|
@@ -285,5 +285,5 @@ export declare class RemoteClient {
|
|
|
285
285
|
[inspect.custom](): {
|
|
286
286
|
remote: string;
|
|
287
287
|
websocket: string;
|
|
288
|
-
} & Omit<this, "
|
|
288
|
+
} & Omit<this, "websocket" | typeof import("util").inspect.custom | "call" | "remote" | "send">;
|
|
289
289
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xshell",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -67,14 +67,14 @@
|
|
|
67
67
|
"commander": "^13.1.0",
|
|
68
68
|
"css-loader": "^7.1.2",
|
|
69
69
|
"emoji-regex": "^10.4.0",
|
|
70
|
-
"eslint": "^9.
|
|
70
|
+
"eslint": "^9.24.0",
|
|
71
71
|
"eslint-plugin-import": "^2.31.0",
|
|
72
|
-
"eslint-plugin-react": "^7.37.
|
|
72
|
+
"eslint-plugin-react": "^7.37.5",
|
|
73
73
|
"gulp-sort": "^2.0.0",
|
|
74
74
|
"https-proxy-agent": "^7.0.6",
|
|
75
75
|
"i18next": "^24.2.3",
|
|
76
76
|
"i18next-scanner": "^4.6.0",
|
|
77
|
-
"koa": "^2.16.
|
|
77
|
+
"koa": "^2.16.1",
|
|
78
78
|
"koa-compress": "^5.1.1",
|
|
79
79
|
"license-webpack-plugin": "^4.0.2",
|
|
80
80
|
"map-stream": "^0.0.7",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"react-i18next": "^15.4.1",
|
|
85
85
|
"react-object-model": "^1.2.23",
|
|
86
86
|
"resolve-path": "^1.4.0",
|
|
87
|
-
"sass": "^1.86.
|
|
87
|
+
"sass": "^1.86.3",
|
|
88
88
|
"sass-loader": "^16.0.5",
|
|
89
89
|
"source-map-loader": "^5.0.0",
|
|
90
90
|
"strip-ansi": "^7.1.0",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"tough-cookie": "^5.1.2",
|
|
94
94
|
"ts-loader": "^9.5.2",
|
|
95
95
|
"tslib": "^2.8.1",
|
|
96
|
-
"typescript": "^5.8.
|
|
96
|
+
"typescript": "^5.8.3",
|
|
97
97
|
"ua-parser-js": "^2.0.3",
|
|
98
98
|
"undici": "^7.7.0",
|
|
99
99
|
"vinyl": "^3.0.0",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"@types/tough-cookie": "^4.0.5",
|
|
119
119
|
"@types/ua-parser-js": "^0.7.39",
|
|
120
120
|
"@types/vinyl-fs": "^3.0.5",
|
|
121
|
-
"@types/vscode": "^1.
|
|
121
|
+
"@types/vscode": "^1.99.0",
|
|
122
122
|
"@types/webpack-bundle-analyzer": "^4.7.0"
|
|
123
123
|
},
|
|
124
124
|
"pnpm": {
|
package/path.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare function extname(path: string): string;
|
|
|
54
54
|
/** `/` */
|
|
55
55
|
export declare const sep = "/";
|
|
56
56
|
/** The platform-specific file delimiter. ';' or ':'. */
|
|
57
|
-
export declare const delimiter: "
|
|
57
|
+
export declare const delimiter: ":" | ";";
|
|
58
58
|
/** Returns an object from a path string - the opposite of format().
|
|
59
59
|
@param path path to evaluate.
|
|
60
60
|
@throws {TypeError} if `path` is not a string. */
|
|
@@ -81,7 +81,7 @@ export declare let path: {
|
|
|
81
81
|
basename: typeof basename;
|
|
82
82
|
extname: typeof extname;
|
|
83
83
|
sep: string;
|
|
84
|
-
delimiter: "
|
|
84
|
+
delimiter: ":" | ";";
|
|
85
85
|
parse: typeof parse;
|
|
86
86
|
format: typeof format;
|
|
87
87
|
toNamespacedPath: typeof toNamespacedPath;
|