@lengmoxxl/sdk 0.1.5 → 0.1.6
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/README.md +8 -5
- package/dist/agent.d.ts +2 -1
- package/dist/channel.d.ts +2 -3
- package/dist/index.cjs +19 -4
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
| `ui.publish(topic, data)` | 后端向本插件 UI 发事件,对应前端 `ui.subscribe` |
|
|
14
14
|
| `ui.subscribe<T>(topic, callback)` | 前端订阅本插件后端事件,返回取消订阅的函数 |
|
|
15
15
|
| `ui.request<T>(method, params?)` | 前端调用本插件后端方法,返回 `Promise<T>` |
|
|
16
|
-
| `connect(machine, signal?)` | 后端借用机器连接:`{ host
|
|
16
|
+
| `connect(machine, signal?)` | 后端借用机器连接:`{ host?, env? }`,可带 `AbortSignal` |
|
|
17
17
|
| `host.dataDirectory` / `host.config` | 插件私有数据目录 / 本插件设置 |
|
|
18
18
|
| `host.tabs(options)` / `host.open(url)` | 前端开侧栏标签页 / 用系统浏览器打开 http、https |
|
|
19
19
|
| `host.preview` | `{ url, message }`,HTML 预览 frame 的地址与握手消息 |
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
`ui.handle` 注册的方法名不能含 `:`;`ui.publish` 与 `ui.subscribe` 的主题由宿主加插件 id 前缀,
|
|
24
24
|
`global` 用原始主题,自定义主题要自己加命名空间(如 `directory-demo:opened`)。
|
|
25
25
|
|
|
26
|
-
`connect({})` 连接本机,`connect({ host })` 连接 SSH
|
|
26
|
+
`connect({})` 连接本机,`connect({ host })` 连接 SSH;`env` 是那台机器上节点启动时的环境。
|
|
27
27
|
|
|
28
28
|
宿主为相同机器复用连接并计数,每次取得连接对应一次 `disconnect()`。
|
|
29
29
|
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
放入 init.ts `workspaces` 的插件用 `ui.handle` 提供:`workspaces()`(`WorkspaceRow[]`,
|
|
66
66
|
按显示顺序)、`workspace-menu()`(`WorkspaceMenuItem[]`)、`workspace-create({ key })`
|
|
67
67
|
(返回 `{ id }`)、`workspace-select({ id })`、`workspace-close({ id })`、
|
|
68
|
+
`workspace-rename({ id, name })`(名字为空表示交回 provider 自己跟随的名字)、
|
|
68
69
|
`workspace-move({ id, before? })`(`before` 是目标工作区 id,不是索引;省略为末尾,且只
|
|
69
70
|
允许同一 provider 内拖动)。
|
|
70
71
|
|
|
@@ -146,7 +147,9 @@ connection.disconnect();
|
|
|
146
147
|
|
|
147
148
|
`openMachine` 返回 `Promise<MachineConnection>`。`type` 为 `'local'` 或 `'ssh'`;local 可给
|
|
148
149
|
`binary`,ssh 必须给 `host`(系统 ssh 目标或别名)与可选 `agent`(`InstallAgent`),两者
|
|
149
|
-
都可给 `
|
|
150
|
+
都可给 `env`(节点启动时带上的环境,值里的 `$NAME` 用运行节点那台机器的环境展开)与 `signal`。
|
|
151
|
+
不传 `agent` 时 SDK 不下载二进制;连接用 BatchMode SSH。
|
|
150
152
|
|
|
151
|
-
`agentCommand(command)` 返回拼接后的 shell 命令:在 PATH 前加入远端 `$HOME/.local/bin`,
|
|
152
|
-
|
|
153
|
+
`agentCommand(command, env)` 返回拼接后的 shell 命令:在 PATH 前加入远端 `$HOME/.local/bin`,
|
|
154
|
+
再带上当前进程的 WANGCAI_HOME 与配置要求的环境;值里的 `$NAME` 留给远端 shell 展开。命令本身
|
|
155
|
+
不转义,只传可信内容。
|
package/dist/agent.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function exportableEnvironment(env?: Record<string, string>): Record<string, string>;
|
|
2
|
+
export declare function agentCommand(command: string, env?: Record<string, string>): string;
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MachineConnection } from './connection';
|
|
2
|
+
import type { Machine } from './types';
|
|
2
3
|
export type Dispose = () => void | Promise<void>;
|
|
3
4
|
/** A sidebar tab the window opens for a plugin: what it is called, and what it draws. */
|
|
4
5
|
export interface TabOptions {
|
|
@@ -31,9 +32,7 @@ export interface MainContext {
|
|
|
31
32
|
handle<T = unknown>(method: string, handler: (params: T) => unknown): Dispose;
|
|
32
33
|
publish(topic: string, data: unknown): void;
|
|
33
34
|
};
|
|
34
|
-
connect(machine:
|
|
35
|
-
host?: string;
|
|
36
|
-
}, signal?: AbortSignal): Promise<MachineConnection>;
|
|
35
|
+
connect(machine: Pick<Machine, 'host' | 'env'>, signal?: AbortSignal): Promise<MachineConnection>;
|
|
37
36
|
host: {
|
|
38
37
|
dataDirectory: string;
|
|
39
38
|
config: any;
|
package/dist/index.cjs
CHANGED
|
@@ -174,14 +174,25 @@ var Pty = class {
|
|
|
174
174
|
};
|
|
175
175
|
|
|
176
176
|
// agent.ts
|
|
177
|
-
|
|
177
|
+
var quoted = (value) => value.replace(/[\\`"]/g, "\\$&");
|
|
178
|
+
function exportableEnvironment(env = {}) {
|
|
179
|
+
return Object.fromEntries(Object.entries(env).filter(([name]) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)));
|
|
180
|
+
}
|
|
181
|
+
function agentCommand(command, env = {}) {
|
|
178
182
|
const home = process.env.WANGCAI_HOME;
|
|
179
183
|
const exportHome = home ? `export WANGCAI_HOME='${home.replace(/'/g, String.raw`'\''`)}'; ` : "";
|
|
180
|
-
|
|
184
|
+
const exports2 = Object.entries(exportableEnvironment(env)).map(([name, value]) => `export ${name}="${quoted(value)}"; `).join("");
|
|
185
|
+
return `${exportHome}export PATH="$HOME/.local/bin:$PATH"; ${exports2}${command}`;
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
// connection.ts
|
|
184
189
|
var exec = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
190
|
+
function expandedEnvironment(env) {
|
|
191
|
+
return Object.fromEntries(Object.entries(env).map(([name, value]) => [
|
|
192
|
+
name,
|
|
193
|
+
value.replace(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g, (_, variable) => process.env[variable] ?? "")
|
|
194
|
+
]));
|
|
195
|
+
}
|
|
185
196
|
var MachineConnection = class {
|
|
186
197
|
constructor(options) {
|
|
187
198
|
this.options = options;
|
|
@@ -340,8 +351,12 @@ var MachineConnection = class {
|
|
|
340
351
|
try {
|
|
341
352
|
let info;
|
|
342
353
|
let port;
|
|
354
|
+
const env = exportableEnvironment(this.options.env);
|
|
343
355
|
if (this.options.type === "local") {
|
|
344
|
-
const { stdout } = await exec(this.options.binary ?? "wangcai", ["server", "start", "--json"], {
|
|
356
|
+
const { stdout } = await exec(this.options.binary ?? "wangcai", ["server", "start", "--json"], {
|
|
357
|
+
timeout: 15e3,
|
|
358
|
+
env: { ...process.env, ...expandedEnvironment(env) }
|
|
359
|
+
});
|
|
345
360
|
info = JSON.parse(stdout);
|
|
346
361
|
port = info.port;
|
|
347
362
|
} else {
|
|
@@ -353,7 +368,7 @@ var MachineConnection = class {
|
|
|
353
368
|
"-o",
|
|
354
369
|
"ConnectTimeout=8",
|
|
355
370
|
this.options.host,
|
|
356
|
-
agentCommand("wangcai server start --json")
|
|
371
|
+
agentCommand("wangcai server start --json", env)
|
|
357
372
|
], { timeout: 15e3, maxBuffer: 64 * 1024 });
|
|
358
373
|
info = JSON.parse(stdout);
|
|
359
374
|
if (!Number.isInteger(info.port) || info.port < 1 || info.port > 65535) throw new Error("Node returned an invalid port.");
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type InstallAgent = (host: string, signal?: AbortSignal) => Promise<void>
|
|
|
10
10
|
* workspace-create({ key }) -> { id: string } the id of the workspace it made
|
|
11
11
|
* workspace-select({ id })
|
|
12
12
|
* workspace-close({ id })
|
|
13
|
+
* workspace-rename({ id, name }) an empty name gives the workspace back to the name it followed
|
|
13
14
|
* workspace-move({ id, before? })
|
|
14
15
|
*
|
|
15
16
|
* Every view that follows the workspace in front shares these channel topics, whatever the provider
|
|
@@ -35,6 +36,7 @@ export interface Machine {
|
|
|
35
36
|
id: string;
|
|
36
37
|
name: string;
|
|
37
38
|
host?: string;
|
|
39
|
+
env?: Record<string, string>;
|
|
38
40
|
}
|
|
39
41
|
export interface WorkspaceActive {
|
|
40
42
|
machine: Machine;
|
|
@@ -52,11 +54,13 @@ export interface FileClick {
|
|
|
52
54
|
export type ConnectionOptions = {
|
|
53
55
|
type: 'local';
|
|
54
56
|
binary?: string;
|
|
57
|
+
env?: Record<string, string>;
|
|
55
58
|
signal?: AbortSignal;
|
|
56
59
|
} | {
|
|
57
60
|
type: 'ssh';
|
|
58
61
|
host: string;
|
|
59
62
|
agent?: InstallAgent;
|
|
63
|
+
env?: Record<string, string>;
|
|
60
64
|
signal?: AbortSignal;
|
|
61
65
|
};
|
|
62
66
|
export interface Size {
|