@solarisdk/core 0.4.3 → 0.4.4
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/dist/desktop.d.ts +5 -0
- package/dist/desktop.js +18 -1
- package/dist/handle.d.ts +14 -3
- package/dist/handle.js +20 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/dist/desktop.d.ts
CHANGED
|
@@ -41,6 +41,11 @@ export declare class Desktop extends SessionHandle {
|
|
|
41
41
|
doubleClick: (x: number, y: number, opts?: ClickOptions) => Promise<void>;
|
|
42
42
|
down: (x: number, y: number, button?: MouseButton) => Promise<void>;
|
|
43
43
|
up: (x: number, y: number, button?: MouseButton) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Scroll the wheel with the pointer at (x, y). `direction` defaults to "down", `amount` (wheel clicks, 1-50)
|
|
46
|
+
* to 3. The guest takes the wheel delta in the `y` field and does not move the pointer, so the pointer is moved
|
|
47
|
+
* first and (x, y) is never passed as the delta (it used to be: scroll(x, 500) fired 500 clicks, 20-30 s).
|
|
48
|
+
*/
|
|
44
49
|
scroll: (x: number, y: number, opts?: ScrollOptions) => Promise<void>;
|
|
45
50
|
drag: (from: {
|
|
46
51
|
x: number;
|
package/dist/desktop.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SessionHandle } from "./handle.js";
|
|
2
|
+
import { SolariError } from "./errors.js";
|
|
2
3
|
import { base64ToBytes } from "./transport.js";
|
|
3
4
|
function buttonToCode(button) {
|
|
4
5
|
if (button === undefined)
|
|
@@ -79,7 +80,23 @@ export class Desktop extends SessionHandle {
|
|
|
79
80
|
}).then(() => undefined),
|
|
80
81
|
down: (x, y, button = "left") => this.mouseCall(x, y, "down", button),
|
|
81
82
|
up: (x, y, button = "left") => this.mouseCall(x, y, "up", button),
|
|
82
|
-
scroll: (x, y, opts = {}) =>
|
|
83
|
+
scroll: async (x, y, opts = {}) => {
|
|
84
|
+
const amount = opts.amount ?? 3;
|
|
85
|
+
if (!Number.isInteger(amount) || amount < 1 || amount > 50) {
|
|
86
|
+
throw new SolariError("scroll amount must be a whole number of wheel clicks from 1 to 50");
|
|
87
|
+
}
|
|
88
|
+
const direction = opts.direction ?? "down";
|
|
89
|
+
if (direction !== "up" && direction !== "down") {
|
|
90
|
+
throw new SolariError('scroll direction must be "up" or "down"');
|
|
91
|
+
}
|
|
92
|
+
await this.mouseCall(x, y, "move", undefined, opts.humanize);
|
|
93
|
+
await this.guiCall("input.mouse", {
|
|
94
|
+
x,
|
|
95
|
+
y: direction === "up" ? amount : -amount,
|
|
96
|
+
action: "scroll",
|
|
97
|
+
button: buttonToCode(opts.button),
|
|
98
|
+
});
|
|
99
|
+
},
|
|
83
100
|
drag: (from, to, button = "left") => this.guiCall("input.drag", { from, to, button: buttonToCode(button) }).then(() => undefined),
|
|
84
101
|
};
|
|
85
102
|
mouseCall(x, y, action, button, humanize) {
|
package/dist/handle.d.ts
CHANGED
|
@@ -56,6 +56,16 @@ export interface SessionConfig extends ControlChannelConfig {
|
|
|
56
56
|
}
|
|
57
57
|
/** The longest `timeoutMs` the gateway accepts for a command (600 000 ms), and the default for `commands.run`. */
|
|
58
58
|
export declare const DEFAULT_COMMAND_TIMEOUT_MS = 600000;
|
|
59
|
+
/**
|
|
60
|
+
* The session `id` is no longer running (killed or paused, through any handle or by id), so the exit reminder must not
|
|
61
|
+
* name it. Tracking is by id, not by handle: two handles to one session, or a `client.kill(id)` with no handle at all,
|
|
62
|
+
* all clear the same entry.
|
|
63
|
+
*/
|
|
64
|
+
export declare function markSessionReleased(id: string): void;
|
|
65
|
+
/** The lines the exit reminder prints: one per distinct session id, however many handles track it. */
|
|
66
|
+
export declare function exitReminderMessages(): string[];
|
|
67
|
+
/** Ids the exit reminder would name right now (for tests). */
|
|
68
|
+
export declare function unreleasedSessionIds(): string[];
|
|
59
69
|
/** Cap on PTY output held before the first onData() subscriber (bytes, total). */
|
|
60
70
|
export declare const PTY_EARLY_BUFFER_MAX: number;
|
|
61
71
|
export interface SessionHandle {
|
|
@@ -172,10 +182,11 @@ export declare class SessionHandle {
|
|
|
172
182
|
}>;
|
|
173
183
|
readonly volumes: {
|
|
174
184
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
185
|
+
* Not available at runtime. A volume is mounted when the sandbox is created (or resumed): the guest cannot fetch the
|
|
186
|
+
* storage credentials itself, and the gateway has no runtime-mount route, so the old pass-through to the guest
|
|
187
|
+
* `volume.mount` RPC always failed with "bucket is required". Pass `volumes: [{ volumeId, path }]` at create.
|
|
177
188
|
*/
|
|
178
|
-
mount: (
|
|
189
|
+
mount: (_volId: string, _path: string) => Promise<void>;
|
|
179
190
|
};
|
|
180
191
|
readonly git: {
|
|
181
192
|
/** Clone `url` into `opts.path` (or git's default dir) under `opts.cwd`. */
|
package/dist/handle.js
CHANGED
|
@@ -6,6 +6,18 @@ export const DEFAULT_COMMAND_TIMEOUT_MS = 600_000;
|
|
|
6
6
|
const unreleased = new Map();
|
|
7
7
|
const MAX_TRACKED_UNRELEASED = 1000;
|
|
8
8
|
let exitHookInstalled = false;
|
|
9
|
+
export function markSessionReleased(id) {
|
|
10
|
+
for (const [token, tracked] of unreleased)
|
|
11
|
+
if (tracked === id)
|
|
12
|
+
unreleased.delete(token);
|
|
13
|
+
}
|
|
14
|
+
export function exitReminderMessages() {
|
|
15
|
+
return [...new Set(unreleased.values())].map((id) => `[solari] this process is exiting but session ${shortId(id)} is still running and will bill until its ` +
|
|
16
|
+
`idle timeout. Call kill() to release it (or declare it with \`await using\`).`);
|
|
17
|
+
}
|
|
18
|
+
export function unreleasedSessionIds() {
|
|
19
|
+
return [...unreleased.values()];
|
|
20
|
+
}
|
|
9
21
|
function trackUnreleased(token, id) {
|
|
10
22
|
unreleased.set(token, id);
|
|
11
23
|
if (unreleased.size > MAX_TRACKED_UNRELEASED)
|
|
@@ -14,10 +26,8 @@ function trackUnreleased(token, id) {
|
|
|
14
26
|
return;
|
|
15
27
|
exitHookInstalled = true;
|
|
16
28
|
process.on("exit", () => {
|
|
17
|
-
for (const
|
|
18
|
-
console.warn(
|
|
19
|
-
`idle timeout. Call kill() to release it (or declare it with \`await using\`).`);
|
|
20
|
-
}
|
|
29
|
+
for (const line of exitReminderMessages())
|
|
30
|
+
console.warn(line);
|
|
21
31
|
unreleased.clear();
|
|
22
32
|
});
|
|
23
33
|
}
|
|
@@ -70,7 +80,8 @@ export class SessionHandle {
|
|
|
70
80
|
return this.channel.reconnect();
|
|
71
81
|
}
|
|
72
82
|
close(opts = {}) {
|
|
73
|
-
|
|
83
|
+
if (!opts.quiet)
|
|
84
|
+
unreleased.delete(this.releaseToken);
|
|
74
85
|
if (!this.killed && !opts.quiet && typeof console !== "undefined") {
|
|
75
86
|
console.warn(`[solari] close() on session ${shortId(this.id)} closed the local channel only — ` +
|
|
76
87
|
`the remote machine is still running and will bill until its idle ` +
|
|
@@ -399,9 +410,7 @@ export class SessionHandle {
|
|
|
399
410
|
return this.hooks.uploadUrl(this.id, path);
|
|
400
411
|
}
|
|
401
412
|
volumes = {
|
|
402
|
-
mount: (
|
|
403
|
-
.call("volume.mount", { volumeId: volId, path })
|
|
404
|
-
.then(() => undefined),
|
|
413
|
+
mount: (_volId, _path) => Promise.reject(new SolariError("volumes.mount() is not supported on a running sandbox: pass volumes: [{ volumeId, path }] when you create it")),
|
|
405
414
|
};
|
|
406
415
|
git = {
|
|
407
416
|
clone: (url, opts = {}) => this.gitClone(url, opts),
|
|
@@ -624,6 +633,7 @@ export class SessionHandle {
|
|
|
624
633
|
throw new Error("pause requires a client-created handle");
|
|
625
634
|
}
|
|
626
635
|
await this.hooks.pause(this.id);
|
|
636
|
+
markSessionReleased(this.id);
|
|
627
637
|
this.close({ quiet: true });
|
|
628
638
|
}
|
|
629
639
|
async resume() {
|
|
@@ -631,6 +641,7 @@ export class SessionHandle {
|
|
|
631
641
|
throw new Error("resume requires a client-created handle");
|
|
632
642
|
}
|
|
633
643
|
const r = await this.hooks.resume(this.id);
|
|
644
|
+
trackUnreleased(this.releaseToken, this.id);
|
|
634
645
|
this.channel.setControlUrl(r.controlUrl);
|
|
635
646
|
await this.channel.reconnect();
|
|
636
647
|
}
|
|
@@ -673,6 +684,7 @@ export class SessionHandle {
|
|
|
673
684
|
if (this.hooks.kill)
|
|
674
685
|
await this.hooks.kill(this.id);
|
|
675
686
|
this.killed = true;
|
|
687
|
+
markSessionReleased(this.id);
|
|
676
688
|
this.close();
|
|
677
689
|
}
|
|
678
690
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_COMMAND_TIMEOUT_MS, SessionHandle } from "./handle.js";
|
|
1
|
+
export { DEFAULT_COMMAND_TIMEOUT_MS, SessionHandle, markSessionReleased, unreleasedSessionIds, exitReminderMessages } from "./handle.js";
|
|
2
2
|
export { shortId } from "./ids.js";
|
|
3
3
|
export { formatIdlePolicy } from "./idle-policy.js";
|
|
4
4
|
export type { SessionConfig, SessionHooks } from "./handle.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_COMMAND_TIMEOUT_MS, SessionHandle } from "./handle.js";
|
|
1
|
+
export { DEFAULT_COMMAND_TIMEOUT_MS, SessionHandle, markSessionReleased, unreleasedSessionIds, exitReminderMessages } from "./handle.js";
|
|
2
2
|
export { shortId } from "./ids.js";
|
|
3
3
|
export { formatIdlePolicy } from "./idle-policy.js";
|
|
4
4
|
export { Desktop } from "./desktop.js";
|
package/dist/types.d.ts
CHANGED
|
@@ -632,6 +632,10 @@ export interface MouseResult {
|
|
|
632
632
|
export interface ScrollOptions {
|
|
633
633
|
button?: MouseButton;
|
|
634
634
|
humanize?: boolean;
|
|
635
|
+
/** Which way the wheel turns. Default "down". */
|
|
636
|
+
direction?: "up" | "down";
|
|
637
|
+
/** Wheel clicks, a whole number from 1 to 50. Default 3. */
|
|
638
|
+
amount?: number;
|
|
635
639
|
}
|
|
636
640
|
export interface ClickOptions {
|
|
637
641
|
button?: MouseButton;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solarisdk/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Shared runtime for the Solari SDK \u2014 transport, session handles, images, templates, and types used by @solarisdk/desktop and @solarisdk/sandbox.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|