xshell 1.0.66 → 1.0.67
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/apps.d.ts +54 -0
- package/apps.js +93 -0
- package/file.d.ts +24 -0
- package/file.js +59 -1
- package/package.json +5 -1
- package/process.d.ts +3 -2
- package/process.js +5 -4
- package/utils.browser.d.ts +1 -1
- package/utils.d.ts +1 -1
package/apps.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type { Readable } from 'stream';
|
|
3
|
+
import type OSS from 'ali-oss';
|
|
4
|
+
import { type CallOptions } from './process.js';
|
|
5
|
+
export declare let npm: {
|
|
6
|
+
bin: string;
|
|
7
|
+
call(cwd: string, bin: string, args: string[], options?: CallOptions): Promise<import("./process.js").CallResult<string>>;
|
|
8
|
+
/** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
|
|
9
|
+
- cwd?: `fpd_root`
|
|
10
|
+
- pkgs?: `[ ]` */
|
|
11
|
+
install(cwd?: string, pkgs?: string[], { save_dev, save_peer, legacy, force, term, inspect, break: _break, }?: {
|
|
12
|
+
save_dev?: boolean;
|
|
13
|
+
save_peer?: boolean;
|
|
14
|
+
legacy?: boolean;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
term?: boolean;
|
|
17
|
+
inspect?: boolean;
|
|
18
|
+
break?: boolean;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
/** 使用 tsc 编译项目
|
|
22
|
+
- fpd: 项目目录
|
|
23
|
+
- options?:
|
|
24
|
+
- tsconfig?: `'<dir>/tsconfig.json'`
|
|
25
|
+
- typecheck?: `false` 是否只进行 typecheck, (使用 call_node 执行而非 term) */
|
|
26
|
+
export declare function tsc(fpd: string, { tsconfig, typecheck, }?: {
|
|
27
|
+
tsconfig?: string;
|
|
28
|
+
typecheck?: boolean;
|
|
29
|
+
}): Promise<import("./process.js").CallResult<string>>;
|
|
30
|
+
export declare let oss: {
|
|
31
|
+
client: OSS;
|
|
32
|
+
bucket: string;
|
|
33
|
+
region: string;
|
|
34
|
+
root: string;
|
|
35
|
+
init({ bucket, region, root, access_id, access_key }: {
|
|
36
|
+
bucket: string;
|
|
37
|
+
region: string;
|
|
38
|
+
root: string;
|
|
39
|
+
access_id: string;
|
|
40
|
+
access_key: string;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/** 上传文件到 OSS,返回文件 URL
|
|
43
|
+
- fp: 上传到 OSS 的路径, 如 assets/web.latest.zip
|
|
44
|
+
- data: 文件 (Uint8Array) | 本地文件完整路径 (string) | ReadableStream
|
|
45
|
+
- options?:
|
|
46
|
+
- private?: `false` 设置为私有,需要通过 URL 签名参数访问
|
|
47
|
+
- print?: `true` 打印消息 */
|
|
48
|
+
upload(fp: string, data: Uint8Array | string | Readable, { private: _private, print, }?: {
|
|
49
|
+
private?: boolean;
|
|
50
|
+
print?: boolean;
|
|
51
|
+
}): Promise<string>;
|
|
52
|
+
/** 获取经过签名后可访问的 url */
|
|
53
|
+
get_url(fp: string): Promise<string>;
|
|
54
|
+
};
|
package/apps.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import util from 'util';
|
|
2
|
+
import { call_nodejs, exe_nodejs, platform } from './process.js';
|
|
3
|
+
import { assert } from './utils.js';
|
|
4
|
+
import { path } from './path.js';
|
|
5
|
+
export let npm = {
|
|
6
|
+
bin: `${platform === 'win32' ? exe_nodejs.fdir : '/usr/lib/'}node_modules/corepack/dist/pnpm.js`,
|
|
7
|
+
async call(cwd, bin, args, options) {
|
|
8
|
+
return call_nodejs(bin, args, { cwd, ...options });
|
|
9
|
+
},
|
|
10
|
+
/** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
|
|
11
|
+
- cwd?: `fpd_root`
|
|
12
|
+
- pkgs?: `[ ]` */
|
|
13
|
+
async install(cwd, pkgs = [], { save_dev = false, save_peer = false, legacy = false, force = false, term = false, inspect = false, break: _break = false, } = {}) {
|
|
14
|
+
const args = [
|
|
15
|
+
'install',
|
|
16
|
+
...util.inspect.defaultOptions.colors ? ['--color'] : [],
|
|
17
|
+
...legacy ? ['--legacy-peer-deps'] : [],
|
|
18
|
+
...force ? ['--force'] : [],
|
|
19
|
+
...save_dev ? ['--save-dev'] : [],
|
|
20
|
+
...save_peer ? ['--save-peer'] : [],
|
|
21
|
+
...pkgs || []
|
|
22
|
+
];
|
|
23
|
+
await this.call(cwd, this.bin, args);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
/** 使用 tsc 编译项目
|
|
27
|
+
- fpd: 项目目录
|
|
28
|
+
- options?:
|
|
29
|
+
- tsconfig?: `'<dir>/tsconfig.json'`
|
|
30
|
+
- typecheck?: `false` 是否只进行 typecheck, (使用 call_node 执行而非 term) */
|
|
31
|
+
export async function tsc(fpd, { tsconfig = './tsconfig.json', typecheck = false, } = {}) {
|
|
32
|
+
return call_nodejs(`${fpd}/node_modules/typescript/bin/tsc`, [
|
|
33
|
+
'--project', tsconfig,
|
|
34
|
+
...typecheck ? ['--noEmit'] : []
|
|
35
|
+
], {
|
|
36
|
+
cwd: fpd,
|
|
37
|
+
print: { command: false, code: false, stdout: true, stderr: true }
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export let oss = {
|
|
41
|
+
client: null,
|
|
42
|
+
bucket: null,
|
|
43
|
+
region: null,
|
|
44
|
+
root: null,
|
|
45
|
+
async init({ bucket, region, root, access_id, access_key }) {
|
|
46
|
+
if (this.client)
|
|
47
|
+
return;
|
|
48
|
+
const OSS = (await import('ali-oss')).default;
|
|
49
|
+
this.bucket = bucket;
|
|
50
|
+
this.region = region;
|
|
51
|
+
this.root = root;
|
|
52
|
+
this.client = new OSS({
|
|
53
|
+
accessKeyId: access_id,
|
|
54
|
+
accessKeySecret: access_key,
|
|
55
|
+
region: this.region,
|
|
56
|
+
bucket: this.bucket,
|
|
57
|
+
secure: true
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
/** 上传文件到 OSS,返回文件 URL
|
|
61
|
+
- fp: 上传到 OSS 的路径, 如 assets/web.latest.zip
|
|
62
|
+
- data: 文件 (Uint8Array) | 本地文件完整路径 (string) | ReadableStream
|
|
63
|
+
- options?:
|
|
64
|
+
- private?: `false` 设置为私有,需要通过 URL 签名参数访问
|
|
65
|
+
- print?: `true` 打印消息 */
|
|
66
|
+
async upload(fp, data, { private: _private = false, print = true, } = {}) {
|
|
67
|
+
assert(this.client, 'OSS 应该已经初始化了');
|
|
68
|
+
assert(!fp.isdir, '不能使用 oss.upload 上传文件夹,请使用 oss.upload_dir');
|
|
69
|
+
if (typeof data === 'string')
|
|
70
|
+
assert(data[1] === ':' && path.isAbsolute(data), 'oss.upload 传入 data 参数类型为 string 时,必须为本地文件完整路径');
|
|
71
|
+
if (data instanceof Uint8Array && !Buffer.isBuffer(data))
|
|
72
|
+
data = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
73
|
+
await this.client.put(fp, data);
|
|
74
|
+
let url;
|
|
75
|
+
if (_private) {
|
|
76
|
+
await this.client.putACL(fp, 'private');
|
|
77
|
+
url = await this.get_url(fp);
|
|
78
|
+
}
|
|
79
|
+
else
|
|
80
|
+
url = new URL(this.root + fp).toString();
|
|
81
|
+
if (print)
|
|
82
|
+
console.log(`已上传到 OSS${_private ? ' (私有)' : ''}:`, url);
|
|
83
|
+
return url;
|
|
84
|
+
},
|
|
85
|
+
/** 获取经过签名后可访问的 url */
|
|
86
|
+
async get_url(fp) {
|
|
87
|
+
assert(this.client, 'OSS 应该已经初始化了');
|
|
88
|
+
const url = new URL(this.client.signatureUrl(fp, { expires: /* 十年 */ 3600 * 24 * 365 * 10 }));
|
|
89
|
+
const url_ = `${this.root}${url.pathname.slice(1)}${url.search}`;
|
|
90
|
+
return url_;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=apps.js.map
|
package/file.d.ts
CHANGED
|
@@ -171,6 +171,30 @@ export declare function flink(fp_real: string, fp_link: string, { junction, prin
|
|
|
171
171
|
junction?: boolean;
|
|
172
172
|
print?: boolean;
|
|
173
173
|
}): Promise<void>;
|
|
174
|
+
export interface ZipOptions {
|
|
175
|
+
dirname?: string;
|
|
176
|
+
print?: {
|
|
177
|
+
info: boolean;
|
|
178
|
+
files: boolean;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/** 将文件夹压缩为 zip
|
|
182
|
+
返回 fp_zip 或压缩包数据
|
|
183
|
+
- data:
|
|
184
|
+
- 被压缩文件夹路径 (fpd_src: string) 或
|
|
185
|
+
- 文件索引对象 (entries: Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
186
|
+
- fp_zip?:
|
|
187
|
+
- 传压缩包完整路径时压缩到文件, 函数返回值为 Promise<zip 路径>
|
|
188
|
+
- 传 undefined 时压缩到内存, 函数返回值为 Promise<zip Uint8Array>
|
|
189
|
+
- options?:
|
|
190
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
191
|
+
- print?:
|
|
192
|
+
- info?: `true` 开始压缩、压缩完成
|
|
193
|
+
- files?: `true` 打印压缩文件列表 */
|
|
194
|
+
export declare function fzip(entries: Record<string, string | Uint8Array>, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
|
|
195
|
+
export declare function fzip(entries: Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
196
|
+
export declare function fzip(fpd_src: string, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
|
|
197
|
+
export declare function fzip(fpd_src: string, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
174
198
|
export declare let fwatchers: Record<string, fs.FSWatcher>;
|
|
175
199
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
176
200
|
export declare function ftail(fp: string, handler: (lines: string[]) => void | Promise<void>, { print }?: {
|
package/file.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isUint8Array } from 'util/types';
|
|
|
3
3
|
import { path } from './path.js';
|
|
4
4
|
import { t } from './i18n/instance.js';
|
|
5
5
|
import { to_json } from './prototype.js';
|
|
6
|
-
import { assert, Lock } from './utils.js';
|
|
6
|
+
import { assert, Lock, WritableMemoryStream } from './utils.js';
|
|
7
7
|
export { fsp };
|
|
8
8
|
export const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'];
|
|
9
9
|
/** fp 所指向的 文件/ 文件夹 是否存在
|
|
@@ -367,6 +367,64 @@ export async function flink(fp_real, fp_link, { junction = false, print = true }
|
|
|
367
367
|
else
|
|
368
368
|
fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file');
|
|
369
369
|
}
|
|
370
|
+
export async function fzip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
371
|
+
let entries;
|
|
372
|
+
let fpd_src;
|
|
373
|
+
if (typeof data === 'string') {
|
|
374
|
+
if (!path.isAbsolute(data) || !data.isdir)
|
|
375
|
+
throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
|
|
376
|
+
fpd_src = data;
|
|
377
|
+
if (dirname === undefined)
|
|
378
|
+
dirname = fpd_src.fname;
|
|
379
|
+
if (!dirname.isdir)
|
|
380
|
+
throw new Error('dirname 需要以 / 结尾');
|
|
381
|
+
entries = Object.fromEntries((await flist(fpd_src, { print: false }))
|
|
382
|
+
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
383
|
+
}
|
|
384
|
+
else
|
|
385
|
+
entries = data;
|
|
386
|
+
if (print.info)
|
|
387
|
+
console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} -> ${fp_zip ? `${fp_zip}/${dirname}` : '内存'}`);
|
|
388
|
+
const { default: archiver } = await import('archiver');
|
|
389
|
+
let archive = archiver('zip', { zlib: { chunkSize: 16 * 2 ** 20 /* 16 MB */ } });
|
|
390
|
+
let ostream = fp_zip ?
|
|
391
|
+
fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
|
|
392
|
+
:
|
|
393
|
+
new WritableMemoryStream();
|
|
394
|
+
const size = await new Promise(async (resolve, reject) => {
|
|
395
|
+
ostream.once('close', () => {
|
|
396
|
+
resolve(archive.pointer());
|
|
397
|
+
});
|
|
398
|
+
ostream.once('error', reject);
|
|
399
|
+
archive.once('error', reject);
|
|
400
|
+
archive.on('warning', error => {
|
|
401
|
+
console.log(error);
|
|
402
|
+
});
|
|
403
|
+
archive.pipe(ostream);
|
|
404
|
+
for (const fp in entries) {
|
|
405
|
+
const fdata = entries[fp];
|
|
406
|
+
if (fdata instanceof Uint8Array) {
|
|
407
|
+
if (print.files)
|
|
408
|
+
console.log(`压缩 ${fdata.length.to_fsize_str()} -> ${fp}`);
|
|
409
|
+
archive.append(Buffer.isBuffer(fdata) ? fdata : Buffer.from(fdata.buffer), { name: fp });
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
assert(fp.isdir === fdata.isdir);
|
|
413
|
+
assert(path.isAbsolute(fdata));
|
|
414
|
+
if (print.files)
|
|
415
|
+
console.log(`压缩 ${fdata} -> ${fp}`);
|
|
416
|
+
if (fp.isdir)
|
|
417
|
+
archive.directory(fdata, fp);
|
|
418
|
+
else
|
|
419
|
+
archive.file(fdata, { name: fp });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
await archive.finalize();
|
|
423
|
+
});
|
|
424
|
+
if (print.info)
|
|
425
|
+
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
426
|
+
return fp_zip || ostream.pbuffer;
|
|
427
|
+
}
|
|
370
428
|
export let fwatchers = {};
|
|
371
429
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
372
430
|
export async function ftail(fp, handler, { print = true } = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xshell",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"@babel/traverse": "^7.23.5",
|
|
51
51
|
"@koa/cors": "^4.0.0",
|
|
52
52
|
"@types/ws": "^8.5.10",
|
|
53
|
+
"ali-oss": "^6.18.1",
|
|
54
|
+
"archiver": "^6.0.1",
|
|
53
55
|
"byte-size": "^8.1.1",
|
|
54
56
|
"chalk": "^5.3.0",
|
|
55
57
|
"chardet": "^2.0.0",
|
|
@@ -91,6 +93,8 @@
|
|
|
91
93
|
},
|
|
92
94
|
"devDependencies": {
|
|
93
95
|
"@babel/types": "^7.23.5",
|
|
96
|
+
"@types/ali-oss": "^6.16.11",
|
|
97
|
+
"@types/archiver": "^6.0.2",
|
|
94
98
|
"@types/babel__traverse": "^7.20.4",
|
|
95
99
|
"@types/byte-size": "^8.1.2",
|
|
96
100
|
"@types/chardet": "^0.8.3",
|
package/process.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import './prototype.js';
|
|
|
6
6
|
import { Encoding } from './file.js';
|
|
7
7
|
import { inspect } from './utils.js';
|
|
8
8
|
export declare const exe_nodejs: string;
|
|
9
|
+
export declare const platform: NodeJS.Platform;
|
|
10
|
+
export declare const username: string;
|
|
9
11
|
interface StartOptions {
|
|
10
12
|
/** `继承当前工作目录 process.cwd()` 子进程的工作目录 `inherit the cwd` cwd of the child process. */
|
|
11
13
|
cwd?: string;
|
|
@@ -108,8 +110,7 @@ export declare const exe_winterm: string;
|
|
|
108
110
|
/** 新建 terminal 窗口执行进程 New Terminal window execution process
|
|
109
111
|
- exe: exe 文件路径 exe file path
|
|
110
112
|
- args: 调用参数 call parameter
|
|
111
|
-
- options?: WinTermOptions
|
|
112
|
-
*/
|
|
113
|
+
- options?: WinTermOptions */
|
|
113
114
|
export declare function term(exe: string, args?: string[], { cwd, print, title, }?: TermOptions): Promise<ChildProcess>;
|
|
114
115
|
export interface TermNodeOptions extends TermOptions {
|
|
115
116
|
/** nodejs debugger port */
|
package/process.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
|
-
import
|
|
2
|
+
import os from 'os';
|
|
3
3
|
import { t } from './i18n/instance.js';
|
|
4
4
|
import './prototype.js';
|
|
5
5
|
import { inspect, DecoderStream } from './utils.js';
|
|
6
6
|
export const exe_nodejs = process.execPath.fp;
|
|
7
|
+
export const platform = os.platform();
|
|
8
|
+
export const username = os.userInfo().username;
|
|
7
9
|
/** start process
|
|
8
10
|
- exe: .exe 路径或文件名 (建议使用完整路径,跳过 path 搜索,性能更高) path or filename (full path is recommanded to skip path searching for better perf)
|
|
9
11
|
- args: `[]` 参数列表 arguments list
|
|
@@ -184,12 +186,11 @@ export async function call_nodejs(js, args = [], { inspect, break: _break, ...op
|
|
|
184
186
|
...args
|
|
185
187
|
], options);
|
|
186
188
|
}
|
|
187
|
-
export const exe_winterm = `C:/Users/${
|
|
189
|
+
export const exe_winterm = `C:/Users/${username}/AppData/Local/Microsoft/WindowsApps/wt.exe`;
|
|
188
190
|
/** 新建 terminal 窗口执行进程 New Terminal window execution process
|
|
189
191
|
- exe: exe 文件路径 exe file path
|
|
190
192
|
- args: 调用参数 call parameter
|
|
191
|
-
- options?: WinTermOptions
|
|
192
|
-
*/
|
|
193
|
+
- options?: WinTermOptions */
|
|
193
194
|
export async function term(exe, args = [], { cwd = process.cwd().fpd, print = true, title,
|
|
194
195
|
// env
|
|
195
196
|
} = {}) {
|
package/utils.browser.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare class Lock<TResource = void> {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function pause(milliseconds?: number): Promise<void>;
|
|
53
53
|
/** 字符串字典序比较 */
|
|
54
|
-
export declare function strcmp(l: string, r: string):
|
|
54
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
55
55
|
/** 比较 1.10.02 这种版本号 */
|
|
56
56
|
export declare function vercmp(l: string, r: string): number;
|
|
57
57
|
export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
|
package/utils.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare function unique<T>(iterable: T[] | Iterable<T>, selector?: string
|
|
|
22
22
|
/** 排序对象中 key 的顺序,返回新的对象 */
|
|
23
23
|
export declare function sort_keys<T>(obj: T): T;
|
|
24
24
|
/** 字符串字典序比较 */
|
|
25
|
-
export declare function strcmp(l: string, r: string):
|
|
25
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
26
26
|
/** 比较 1.10.02 这种版本号 */
|
|
27
27
|
export declare function vercmp(l: string, r: string): number;
|
|
28
28
|
export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
|