@phreshos/cli 0.1.65 → 0.1.66
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/commands/access.js +2 -0
- package/dist/commands/execution.js +13 -2
- package/dist/commands/options.js +4 -4
- package/dist/commands/projection.js +12 -9
- package/dist/commands/schemas.js +62 -10
- package/dist/commands/service.js +133 -0
- package/dist/commands/window.js +93 -14
- package/dist/template/package.json +1 -1
- package/package.json +3 -3
package/dist/commands/access.js
CHANGED
|
@@ -5,6 +5,7 @@ import { connectSystem } from "./connection.js";
|
|
|
5
5
|
import windowCommands from "./window.js";
|
|
6
6
|
import executeCommand from "./execute.js";
|
|
7
7
|
import operationCommands from "./operation.js";
|
|
8
|
+
import serviceCommands from "./service.js";
|
|
8
9
|
/** Expose the shared System domains through explicit Node SDK executors. */
|
|
9
10
|
export default function accessCommands(program, connect = connectSystem) {
|
|
10
11
|
executeCommand(program, connect);
|
|
@@ -12,5 +13,6 @@ export default function accessCommands(program, connect = connectSystem) {
|
|
|
12
13
|
programCommands(program, connect);
|
|
13
14
|
processCommands(program, connect);
|
|
14
15
|
endpointCommands(program, connect);
|
|
16
|
+
serviceCommands(program, connect);
|
|
15
17
|
windowCommands(program, connect);
|
|
16
18
|
}
|
|
@@ -24,14 +24,25 @@ export const executeCommandPaths = Object.freeze({
|
|
|
24
24
|
"endpoint.publish": ["endpoint", "publish"],
|
|
25
25
|
"endpoint.wait": ["endpoint", "wait"],
|
|
26
26
|
"endpoint.waitLifecycle": ["endpoint", "waitLifecycle"],
|
|
27
|
+
"service.list": ["service", "list"],
|
|
28
|
+
"service.search": ["service", "search"],
|
|
29
|
+
"service.inspect": ["service", "inspect"],
|
|
30
|
+
"service.waitReady": ["service", "waitReady"],
|
|
31
|
+
"service.ask": ["service", "ask"],
|
|
32
|
+
"service.publish": ["service", "publish"],
|
|
33
|
+
"service.wait": ["service", "wait"],
|
|
34
|
+
"service.waitLifecycle": ["service", "waitLifecycle"],
|
|
35
|
+
"service.waitDiscovery": ["service", "waitDiscovery"],
|
|
27
36
|
"window.inspect": ["window", "inspect"],
|
|
28
37
|
"window.move": ["window", "move"],
|
|
29
38
|
"window.resize": ["window", "resize"],
|
|
30
39
|
"window.setGeometry": ["window", "setGeometry"],
|
|
31
40
|
"window.minimize": ["window", "minimize"],
|
|
32
41
|
"window.maximize": ["window", "maximize"],
|
|
33
|
-
"window.
|
|
34
|
-
"window.
|
|
42
|
+
"window.setTitle": ["window", "setTitle"],
|
|
43
|
+
"window.setHeader": ["window", "setHeader"],
|
|
44
|
+
"window.setFrame": ["window", "setFrame"],
|
|
45
|
+
"window.setTransaction": ["window", "setTransaction"],
|
|
35
46
|
"window.raise": ["window", "raise"],
|
|
36
47
|
"window.wait": ["window", "wait"]
|
|
37
48
|
});
|
package/dist/commands/options.js
CHANGED
|
@@ -10,8 +10,8 @@ export const endpointOptions = Object.freeze([
|
|
|
10
10
|
option("--endpoint <endpoint>", "Endpoint kind", { mandatory: true, choices: ["server", "client"] })
|
|
11
11
|
]);
|
|
12
12
|
export const clientOverrideOptions = Object.freeze([
|
|
13
|
-
option("--client-service", "
|
|
14
|
-
option("--no-client-service", "
|
|
13
|
+
option("--client-service", "make this Client execution context available through Service discovery"),
|
|
14
|
+
option("--no-client-service", "keep this Client execution context out of Service discovery"),
|
|
15
15
|
option("--client-title <title>", "initial Window title"),
|
|
16
16
|
option("--client-width <value>", "initial Window width"),
|
|
17
17
|
option("--client-height <value>", "initial Window height"),
|
|
@@ -22,8 +22,8 @@ export const clientOverrideOptions = Object.freeze([
|
|
|
22
22
|
option("--client-maximized", "open the Window maximized")
|
|
23
23
|
]);
|
|
24
24
|
export const serverOverrideOptions = Object.freeze([
|
|
25
|
-
option("--server-service", "
|
|
26
|
-
option("--no-server-service", "
|
|
25
|
+
option("--server-service", "make this Server execution context available through Service discovery"),
|
|
26
|
+
option("--no-server-service", "keep this Server execution context out of Service discovery")
|
|
27
27
|
]);
|
|
28
28
|
export const launchOptions = Object.freeze([
|
|
29
29
|
...serverOverrideOptions,
|
|
@@ -18,19 +18,22 @@ export async function programView(program) {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
export async function processView(process) {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const program = process.program();
|
|
22
|
+
const [server, client] = await Promise.all([
|
|
23
|
+
program.server === null
|
|
24
|
+
? Promise.resolve({ running: false, service: false })
|
|
25
|
+
: Promise.all([process.server.running(), process.server.isService()]).then(([running, service]) => ({ running, service })),
|
|
26
|
+
program.client === null
|
|
27
|
+
? Promise.resolve({ running: false, service: false })
|
|
28
|
+
: Promise.all([process.client.running(), process.client.isService()]).then(([running, service]) => ({ running, service }))
|
|
26
29
|
]);
|
|
27
30
|
return {
|
|
28
31
|
identity: process.identity,
|
|
29
32
|
name: process.name,
|
|
30
|
-
program:
|
|
33
|
+
program: program.identity,
|
|
31
34
|
startedAt: process.startedAt.toISOString(),
|
|
32
|
-
server: { declared:
|
|
33
|
-
client: { declared:
|
|
35
|
+
server: { declared: program.server !== null, ...server },
|
|
36
|
+
client: { declared: program.client !== null, ...client }
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
39
|
export async function endpointView(process, name) {
|
|
@@ -40,7 +43,7 @@ export async function endpointView(process, name) {
|
|
|
40
43
|
program: program.identity,
|
|
41
44
|
endpoint: name,
|
|
42
45
|
declared: name === "server" ? program.server !== null : program.client !== null,
|
|
43
|
-
running: await endpoint(process, name).
|
|
46
|
+
running: await endpoint(process, name).running(),
|
|
44
47
|
service: await endpoint(process, name).isService()
|
|
45
48
|
};
|
|
46
49
|
}
|
package/dist/commands/schemas.js
CHANGED
|
@@ -3,25 +3,60 @@ import { value } from "../contract/schema.js";
|
|
|
3
3
|
const metric = {
|
|
4
4
|
anyOf: [value.number("pixels"), value.string("workspace-relative expression")]
|
|
5
5
|
};
|
|
6
|
+
const transaction = {
|
|
7
|
+
anyOf: [
|
|
8
|
+
value.boolean("default or disabled transaction"),
|
|
9
|
+
value.number("duration in milliseconds"),
|
|
10
|
+
value.object({
|
|
11
|
+
duration: value.number("duration in milliseconds"),
|
|
12
|
+
easing: value.any("CSS easing name or cubic Bézier tuple")
|
|
13
|
+
}, ["duration", "easing"], "appearance transaction")
|
|
14
|
+
]
|
|
15
|
+
};
|
|
16
|
+
const frame = {
|
|
17
|
+
anyOf: [
|
|
18
|
+
value.boolean("default or absent frame"),
|
|
19
|
+
value.object({
|
|
20
|
+
radius: { anyOf: [value.number("radius in pixels"), value.literal("full", "fully rounded radius")] },
|
|
21
|
+
color: value.string("Appearance color role or CSS color"),
|
|
22
|
+
material: {
|
|
23
|
+
anyOf: [
|
|
24
|
+
value.literal(false, "disabled Material"),
|
|
25
|
+
value.object({
|
|
26
|
+
grain: value.number("grain frequency"),
|
|
27
|
+
grainAmount: value.number("grain intensity"),
|
|
28
|
+
backdrop: value.number("backdrop blur"),
|
|
29
|
+
opacity: value.number("Material opacity"),
|
|
30
|
+
distortion: value.number("backdrop distortion"),
|
|
31
|
+
saturation: value.number("backdrop saturation")
|
|
32
|
+
}, [], "partial Appearance Material")
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}, [], "Window frame customization")
|
|
36
|
+
]
|
|
37
|
+
};
|
|
6
38
|
const endpointDeclaration = value.nullable(value.object({
|
|
7
39
|
start: value.boolean("whether a default Process starts this Endpoint"),
|
|
8
|
-
service: value.boolean("default Service role for new
|
|
40
|
+
service: value.boolean("default Service role for new execution contexts")
|
|
9
41
|
}, ["start", "service"], "resolved Server Endpoint declaration"));
|
|
10
42
|
const clientDeclaration = value.nullable(value.object({
|
|
11
43
|
start: value.boolean("whether a default Process starts this Endpoint"),
|
|
12
|
-
service: value.boolean("default Service role for new
|
|
44
|
+
service: value.boolean("default Service role for new execution contexts"),
|
|
13
45
|
title: value.nullable(value.string("default Window title")),
|
|
46
|
+
header: value.nullable(value.boolean("default Window header visibility")),
|
|
47
|
+
frame: value.nullable(frame),
|
|
48
|
+
transaction: value.nullable(transaction),
|
|
14
49
|
size: value.nullable(value.object({ width: metric, height: metric }, ["width", "height"], "default Window size")),
|
|
15
50
|
position: value.nullable(value.object({ x: metric, y: metric }, ["x", "y"], "default Window position")),
|
|
16
51
|
layer: value.nullable(value.enumeration(layers, "default Window layer")),
|
|
17
52
|
minimize: value.nullable(value.boolean("default minimized state")),
|
|
18
53
|
maximize: value.nullable(value.boolean("default maximized state"))
|
|
19
|
-
}, ["start", "service", "title", "size", "position", "layer", "minimize", "maximize"], "resolved Client Endpoint declaration"));
|
|
54
|
+
}, ["start", "service", "title", "header", "frame", "transaction", "size", "position", "layer", "minimize", "maximize"], "resolved Client Endpoint declaration"));
|
|
20
55
|
export const programOutput = value.object({
|
|
21
56
|
identity: value.string("stable Program identity"),
|
|
22
57
|
assetId: value.string("public Program asset identity"),
|
|
23
58
|
name: value.string("human-readable Program name"),
|
|
24
|
-
version: value.
|
|
59
|
+
version: value.string("Resolved Program version"),
|
|
25
60
|
description: value.nullable(value.string("Program description")),
|
|
26
61
|
installed: value.boolean("whether production files are installed"),
|
|
27
62
|
hasAgent: value.boolean("whether the Program provides agent documentation"),
|
|
@@ -41,19 +76,28 @@ export const endpointOutput = value.object({
|
|
|
41
76
|
program: value.string("owning Program identity"),
|
|
42
77
|
endpoint: value.enumeration(["server", "client"], "Endpoint kind"),
|
|
43
78
|
declared: value.boolean("whether the Program declares this Endpoint"),
|
|
44
|
-
running: value.boolean("whether the Endpoint currently
|
|
45
|
-
service: value.boolean("whether this Endpoint
|
|
79
|
+
running: value.boolean("whether the Endpoint currently has a running execution context"),
|
|
80
|
+
service: value.boolean("whether this Endpoint execution context is addressable as a Service")
|
|
46
81
|
}, ["process", "program", "endpoint", "declared", "running", "service"], "Endpoint state");
|
|
82
|
+
export const serviceOutput = value.object({
|
|
83
|
+
program: value.string("owning Program identity"),
|
|
84
|
+
process: value.string("Process and Service name"),
|
|
85
|
+
endpoint: value.enumeration(["server", "client"], "Endpoint kind"),
|
|
86
|
+
available: value.boolean("whether a ready Endpoint is currently available at this address")
|
|
87
|
+
}, ["program", "process", "endpoint", "available"], "Service state");
|
|
47
88
|
export const windowOutput = value.object({
|
|
48
89
|
process: value.string("owning Process identity"),
|
|
49
90
|
title: value.string("Window title"),
|
|
91
|
+
header: value.boolean("whether the Desktop-owned Window header is shown"),
|
|
92
|
+
frame,
|
|
93
|
+
transaction,
|
|
50
94
|
position: value.object({ x: metric, y: metric }, ["x", "y"], "Window position"),
|
|
51
95
|
size: value.object({ width: metric, height: metric }, ["width", "height"], "Window size"),
|
|
52
96
|
minimized: value.boolean("whether the Window is minimized"),
|
|
53
97
|
maximized: value.boolean("whether the Window is maximized"),
|
|
54
98
|
front: value.boolean("whether the Window is at the front of its layer"),
|
|
55
99
|
layer: value.enumeration(layers, "Window layer")
|
|
56
|
-
}, ["process", "title", "position", "size", "minimized", "maximized", "front", "layer"], "Window state");
|
|
100
|
+
}, ["process", "title", "header", "frame", "transaction", "position", "size", "minimized", "maximized", "front", "layer"], "Window state");
|
|
57
101
|
export const programPresentation = fields(["Identity", "identity"], ["Asset", "assetId"], ["Name", "name"], ["Version", "version"], ["Description", "description"], ["Installed", "installed"], ["Agent", "hasAgent"], ["Server", "server"], ["Client", "client"]);
|
|
58
102
|
export const programListPresentation = list("data", "Program", "Programs", "No matching Programs", [
|
|
59
103
|
{ label: "Name", path: "name" },
|
|
@@ -73,7 +117,13 @@ export const processListPresentation = list("data", "Process", "Processes", "No
|
|
|
73
117
|
]);
|
|
74
118
|
export const endpointPresentation = fields(["Process", "process"], ["Program", "program"], ["Endpoint", "endpoint"], ["Declared", "declared"], ["Running", "running"], ["Service", "service"]);
|
|
75
119
|
export const endpointActionPresentation = fields(["Process", "process"], ["Endpoint", "endpoint"], ["Running", "running"], ["Service", "service"]);
|
|
76
|
-
export const
|
|
120
|
+
export const servicePresentation = fields(["Program", "program"], ["Service", "process"], ["Endpoint", "endpoint"], ["Available", "available"]);
|
|
121
|
+
export const serviceListPresentation = list("data", "Service", "Services", "No matching Services", [
|
|
122
|
+
{ label: "Service", path: "process" },
|
|
123
|
+
{ label: "Program", path: "program" },
|
|
124
|
+
{ label: "Endpoint", path: "endpoint" }
|
|
125
|
+
]);
|
|
126
|
+
export const windowPresentation = fields(["Process", "process"], ["Title", "title"], ["Header", "header"], ["Frame", "frame"], ["Transaction", "transaction"], ["Position", "position"], ["Size", "size"], ["Minimized", "minimized"], ["Maximized", "maximized"], ["Front", "front"], ["Layer", "layer"]);
|
|
77
127
|
export const windowPositionPresentation = fields(["Process", "process"], ["Position", "position"]);
|
|
78
128
|
export const windowSizePresentation = fields(["Process", "process"], ["Size", "size"]);
|
|
79
129
|
export const windowGeometryPresentation = fields(["Process", "process"], ["Position", "position"], ["Size", "size"]);
|
|
@@ -81,6 +131,8 @@ export const windowMinimizePresentation = fields(["Process", "process"], ["Minim
|
|
|
81
131
|
export const windowMaximizePresentation = fields(["Process", "process"], ["Maximized", "maximized"]);
|
|
82
132
|
export const windowTitlePresentation = fields(["Process", "process"], ["Title", "title"]);
|
|
83
133
|
export const windowHeaderPresentation = fields(["Process", "process"], ["Header", "header"]);
|
|
134
|
+
export const windowFramePresentation = fields(["Process", "process"], ["Frame", "frame"]);
|
|
135
|
+
export const windowTransactionPresentation = fields(["Process", "process"], ["Transaction", "transaction"]);
|
|
84
136
|
export const windowRaisePresentation = fields(["Process", "process"], ["Front", "front"]);
|
|
85
137
|
export const eventPresentation = fields(["Scope", "scope"], ["Event", "event"], ["Payload", "payload"]);
|
|
86
138
|
export const lifecyclePresentation = fields(["Scope", "scope"], ["Event", "event"]);
|
|
@@ -109,8 +161,8 @@ export function textOutput(description) {
|
|
|
109
161
|
function endpointState(description) {
|
|
110
162
|
return value.object({
|
|
111
163
|
declared: value.boolean("whether the Program declares this Endpoint"),
|
|
112
|
-
running: value.boolean("whether the Endpoint currently
|
|
113
|
-
service: value.boolean("whether this Endpoint
|
|
164
|
+
running: value.boolean("whether the Endpoint currently has a running execution context"),
|
|
165
|
+
service: value.boolean("whether this Endpoint execution context is a Service")
|
|
114
166
|
}, ["declared", "running", "service"], description);
|
|
115
167
|
}
|
|
116
168
|
function fields(...values) {
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { parseExecuteRequest } from "@phreshos/core";
|
|
2
|
+
import { defineCommand } from "../contract/command.js";
|
|
3
|
+
import { value } from "../contract/schema.js";
|
|
4
|
+
import { dataOutput, eventOutput, eventPresentation, lifecyclePresentation, serviceListPresentation, serviceOutput, servicePresentation, valuePresentation } from "./schemas.js";
|
|
5
|
+
import { connected } from "./connection.js";
|
|
6
|
+
import { bounded, payload } from "./input.js";
|
|
7
|
+
import { executeDescription } from "./execution.js";
|
|
8
|
+
import { option, timeoutOption, withJson } from "./options.js";
|
|
9
|
+
const addressOptions = [
|
|
10
|
+
option("--program <identity>", "owning Program identity", { mandatory: true }),
|
|
11
|
+
option("--process <name>", "Process and Service name", { mandatory: true }),
|
|
12
|
+
option("--endpoint <endpoint>", "Endpoint kind", { mandatory: true, choices: ["server", "client"] })
|
|
13
|
+
];
|
|
14
|
+
const availabilityEvents = ["available", "unavailable"];
|
|
15
|
+
export default function serviceCommands(root, connect) {
|
|
16
|
+
const services = defineCommand(root, {
|
|
17
|
+
name: "service",
|
|
18
|
+
description: "discover and communicate with named Endpoint Services",
|
|
19
|
+
guidance: ["Discovery returns ready Services; exact addresses remain stable while their providers are unavailable."]
|
|
20
|
+
});
|
|
21
|
+
defineCommand(services, {
|
|
22
|
+
name: "list",
|
|
23
|
+
description: executeDescription("service", "list"),
|
|
24
|
+
requiresSystem: true,
|
|
25
|
+
options: withJson(),
|
|
26
|
+
output: dataOutput(value.array(serviceOutput, "ready Services"), "Visible Services", serviceListPresentation),
|
|
27
|
+
examples: ["phresh service list"]
|
|
28
|
+
}, async () => executeService(connect, { $operation: "list" }));
|
|
29
|
+
defineCommand(services, {
|
|
30
|
+
name: "search",
|
|
31
|
+
description: executeDescription("service", "search"),
|
|
32
|
+
requiresSystem: true,
|
|
33
|
+
options: withJson(option("--name <name>", "Process and Service name", { mandatory: true })),
|
|
34
|
+
output: dataOutput(value.array(serviceOutput, "matching ready Services"), "Matching Services", serviceListPresentation),
|
|
35
|
+
examples: ["phresh service search --name ssh"]
|
|
36
|
+
}, async ({ options }) => executeService(connect, { $operation: "search", name: options.name }));
|
|
37
|
+
defineCommand(services, {
|
|
38
|
+
name: "inspect",
|
|
39
|
+
description: executeDescription("service", "inspect"),
|
|
40
|
+
requiresSystem: true,
|
|
41
|
+
options: withJson(...addressOptions),
|
|
42
|
+
output: dataOutput(serviceOutput, "The selected Service", servicePresentation),
|
|
43
|
+
examples: ["phresh service inspect --program terminal --process ssh --endpoint server"]
|
|
44
|
+
}, async ({ options }) => executeAddressedService(connect, options, { $operation: "inspect" }));
|
|
45
|
+
defineCommand(services, {
|
|
46
|
+
name: "waitReady",
|
|
47
|
+
aliases: ["wait-ready"],
|
|
48
|
+
description: executeDescription("service", "waitReady"),
|
|
49
|
+
requiresSystem: true,
|
|
50
|
+
options: withJson(...addressOptions, timeoutOption),
|
|
51
|
+
output: dataOutput(serviceOutput, "The ready Service", servicePresentation),
|
|
52
|
+
examples: ["phresh service wait-ready --program terminal --process ssh --endpoint server"]
|
|
53
|
+
}, async ({ options }) => executeAddressedService(connect, options, {
|
|
54
|
+
$operation: "waitReady",
|
|
55
|
+
...(options.timeout === undefined ? {} : { timeout: timeout(options.timeout) })
|
|
56
|
+
}));
|
|
57
|
+
defineCommand(services, {
|
|
58
|
+
name: "ask",
|
|
59
|
+
description: executeDescription("service", "ask"),
|
|
60
|
+
requiresSystem: true,
|
|
61
|
+
options: withJson(option("--program <identity>", "owning Program identity", { mandatory: true }), option("--process <name>", "Process and Service name", { mandatory: true }), option("--endpoint <endpoint>", "Endpoint kind", { mandatory: true, choices: ["server"] }), option("--event <event>", "event name", { mandatory: true }), option("--payload <json>", "arbitrary event payload as JSON"), timeoutOption),
|
|
62
|
+
output: dataOutput(value.any("answer returned by the Server Service contract"), "The Service answer", valuePresentation),
|
|
63
|
+
examples: ["phresh service ask --program tilo --process board --endpoint server --event board.list --json"]
|
|
64
|
+
}, async ({ options }) => executeAddressedService(connect, options, {
|
|
65
|
+
$operation: "ask",
|
|
66
|
+
event: options.event,
|
|
67
|
+
...(options.payload === undefined ? {} : { input: payload(options.payload) }),
|
|
68
|
+
...(options.timeout === undefined ? {} : { timeout: timeout(options.timeout) })
|
|
69
|
+
}));
|
|
70
|
+
defineCommand(services, {
|
|
71
|
+
name: "publish",
|
|
72
|
+
description: executeDescription("service", "publish"),
|
|
73
|
+
requiresSystem: true,
|
|
74
|
+
options: withJson(...addressOptions, option("--event <event>", "event name", { mandatory: true }), option("--payload <json>", "arbitrary event payload as JSON")),
|
|
75
|
+
output: dataOutput(serviceOutput, "The addressed Service", servicePresentation),
|
|
76
|
+
examples: ["phresh service publish --program tilo --process board --endpoint client --event changed"]
|
|
77
|
+
}, async ({ options }) => executeAddressedService(connect, options, {
|
|
78
|
+
$operation: "publish",
|
|
79
|
+
event: options.event,
|
|
80
|
+
...(options.payload === undefined ? {} : { input: payload(options.payload) })
|
|
81
|
+
}));
|
|
82
|
+
defineCommand(services, {
|
|
83
|
+
name: "wait",
|
|
84
|
+
description: executeDescription("service", "wait"),
|
|
85
|
+
requiresSystem: true,
|
|
86
|
+
options: withJson(...addressOptions, option("--event <event>", "event name", { mandatory: true }), timeoutOption),
|
|
87
|
+
output: dataOutput(eventOutput("The observed Service event"), "One Service event", eventPresentation),
|
|
88
|
+
examples: ["phresh service wait --program tilo --process board --endpoint client --event changed"]
|
|
89
|
+
}, async ({ options }) => executeAddressedService(connect, options, {
|
|
90
|
+
$operation: "wait",
|
|
91
|
+
event: options.event,
|
|
92
|
+
...(options.timeout === undefined ? {} : { timeout: timeout(options.timeout) })
|
|
93
|
+
}));
|
|
94
|
+
defineCommand(services, {
|
|
95
|
+
name: "waitLifecycle",
|
|
96
|
+
aliases: ["wait-lifecycle"],
|
|
97
|
+
description: executeDescription("service", "waitLifecycle"),
|
|
98
|
+
requiresSystem: true,
|
|
99
|
+
options: withJson(...addressOptions, option("--event <event>", "availability event", { mandatory: true, choices: availabilityEvents }), timeoutOption),
|
|
100
|
+
output: dataOutput(eventOutput("The observed Service availability event"), "One Service lifecycle event", lifecyclePresentation),
|
|
101
|
+
examples: ["phresh service wait-lifecycle --program tilo --process board --endpoint server --event available"]
|
|
102
|
+
}, async ({ options }) => executeAddressedService(connect, options, {
|
|
103
|
+
$operation: "waitLifecycle",
|
|
104
|
+
event: options.event,
|
|
105
|
+
...(options.timeout === undefined ? {} : { timeout: timeout(options.timeout) })
|
|
106
|
+
}));
|
|
107
|
+
defineCommand(services, {
|
|
108
|
+
name: "waitDiscovery",
|
|
109
|
+
aliases: ["wait-discovery"],
|
|
110
|
+
description: executeDescription("service", "waitDiscovery"),
|
|
111
|
+
requiresSystem: true,
|
|
112
|
+
options: withJson(option("--event <event>", "discovery event", { mandatory: true, choices: availabilityEvents }), timeoutOption),
|
|
113
|
+
output: dataOutput(eventOutput("The observed Service discovery event"), "One Service discovery event", lifecyclePresentation),
|
|
114
|
+
examples: ["phresh service wait-discovery --event available"]
|
|
115
|
+
}, async ({ options }) => executeService(connect, {
|
|
116
|
+
$operation: "waitDiscovery",
|
|
117
|
+
event: options.event,
|
|
118
|
+
...(options.timeout === undefined ? {} : { timeout: timeout(options.timeout) })
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
function executeAddressedService(connect, options, operation) {
|
|
122
|
+
return executeService(connect, {
|
|
123
|
+
...operation,
|
|
124
|
+
program: options.program,
|
|
125
|
+
process: options.process,
|
|
126
|
+
endpoint: options.endpoint
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function executeService(connect, operation) {
|
|
130
|
+
const request = parseExecuteRequest({ $domain: "service", ...operation });
|
|
131
|
+
return connected(connect, system => system.execute(request));
|
|
132
|
+
}
|
|
133
|
+
function timeout(value) { return value === undefined ? undefined : bounded(value, "--timeout", 1); }
|
package/dist/commands/window.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseExecuteRequest } from "@phreshos/core";
|
|
1
|
+
import { parseExecuteRequest, parseWindowFrame, parseWindowTransaction } from "@phreshos/core";
|
|
2
2
|
import { defineCommand } from "../contract/command.js";
|
|
3
3
|
import { option, processOptions, timeoutOption, withJson } from "./options.js";
|
|
4
|
-
import { dataOutput, eventOutput, eventPresentation, windowGeometryPresentation, windowHeaderPresentation, windowMinimizePresentation, windowMaximizePresentation, windowOutput, windowPositionPresentation, windowPresentation, windowRaisePresentation, windowSizePresentation, windowTitlePresentation } from "./schemas.js";
|
|
4
|
+
import { dataOutput, eventOutput, eventPresentation, windowGeometryPresentation, windowFramePresentation, windowHeaderPresentation, windowMinimizePresentation, windowMaximizePresentation, windowOutput, windowPositionPresentation, windowTransactionPresentation, windowPresentation, windowRaisePresentation, windowSizePresentation, windowTitlePresentation } from "./schemas.js";
|
|
5
5
|
import { connected } from "./connection.js";
|
|
6
6
|
import { bounded, position, size } from "./input.js";
|
|
7
7
|
import { executeDescription } from "./execution.js";
|
|
@@ -31,8 +31,8 @@ export default function windowCommands(root, connect) {
|
|
|
31
31
|
examples: ["phresh window set-geometry --process main --program terminal --x 0 --y 0 --width 100% --height 100%"]
|
|
32
32
|
}, async ({ options }) => executeWindow(connect, options, {
|
|
33
33
|
$operation: "setGeometry",
|
|
34
|
-
position
|
|
35
|
-
size
|
|
34
|
+
...position(options.x, options.y),
|
|
35
|
+
...size(options.width, options.height)
|
|
36
36
|
}));
|
|
37
37
|
defineCommand(windows, {
|
|
38
38
|
...state("minimize", windowMinimizePresentation),
|
|
@@ -45,17 +45,38 @@ export default function windowCommands(root, connect) {
|
|
|
45
45
|
examples: ["phresh window maximize --process main --program terminal", "phresh window maximize --process main --program terminal --restore"]
|
|
46
46
|
}, async ({ options }) => executeWindow(connect, options, { $operation: "maximize", maximized: options.restore !== true }));
|
|
47
47
|
defineCommand(windows, {
|
|
48
|
-
...state("
|
|
49
|
-
aliases: ["
|
|
48
|
+
...state("setTitle", windowTitlePresentation),
|
|
49
|
+
aliases: ["set-title"],
|
|
50
50
|
options: withJson(...processOptions, option("--title <title>", "new Window title", { mandatory: true })),
|
|
51
|
-
examples: ["phresh window
|
|
52
|
-
}, async ({ options }) => executeWindow(connect, options, { $operation: "
|
|
51
|
+
examples: ["phresh window set-title --process main --program terminal --title Shell"]
|
|
52
|
+
}, async ({ options }) => executeWindow(connect, options, { $operation: "setTitle", title: options.title }));
|
|
53
53
|
defineCommand(windows, {
|
|
54
|
-
...state("
|
|
55
|
-
aliases: ["
|
|
54
|
+
...state("setHeader", windowHeaderPresentation),
|
|
55
|
+
aliases: ["set-header"],
|
|
56
56
|
options: withJson(...processOptions, option("--hide", "hide rather than show the Window header")),
|
|
57
|
-
examples: ["phresh window
|
|
58
|
-
}, async ({ options }) => executeWindow(connect, options, { $operation: "
|
|
57
|
+
examples: ["phresh window set-header --process main --program terminal --hide", "phresh window set-header --process main --program terminal"]
|
|
58
|
+
}, async ({ options }) => executeWindow(connect, options, { $operation: "setHeader", header: options.hide !== true }));
|
|
59
|
+
defineCommand(windows, {
|
|
60
|
+
...state("setFrame", windowFramePresentation),
|
|
61
|
+
aliases: ["set-frame"],
|
|
62
|
+
options: withJson(...processOptions, option("--default", "use the default Window frame"), option("--absent", "remove the Window frame"), option("--radius <radius>", "frame radius in pixels or full"), option("--color <color>", "Appearance color role or CSS color"), option("--without-material", "render the frame without Material"), option("--grain <value>", "frame Material grain", { parse: input => numeric(input, "--grain") }), option("--grain-amount <value>", "frame Material grain intensity", { parse: input => numeric(input, "--grain-amount") }), option("--backdrop <value>", "frame Material backdrop blur", { parse: input => numeric(input, "--backdrop") }), option("--opacity <value>", "frame Material opacity", { parse: input => numeric(input, "--opacity") }), option("--distortion <value>", "frame Material distortion", { parse: input => numeric(input, "--distortion") }), option("--saturation <value>", "frame Material saturation", { parse: input => numeric(input, "--saturation") })),
|
|
63
|
+
examples: [
|
|
64
|
+
"phresh window set-frame --process overlay --absent",
|
|
65
|
+
"phresh window set-frame --process overlay --radius full --color primary"
|
|
66
|
+
]
|
|
67
|
+
}, async ({ options }) => executeWindow(connect, options, { $operation: "setFrame", frame: frame(options) }));
|
|
68
|
+
defineCommand(windows, {
|
|
69
|
+
...state("setTransaction", windowTransactionPresentation),
|
|
70
|
+
aliases: ["set-transaction"],
|
|
71
|
+
options: withJson(...processOptions, option("--default", "use the default Appearance transaction"), option("--disabled", "disable the default Window transaction"), option("--duration <milliseconds>", "transaction duration", { parse: input => numeric(input, "--duration") }), option("--easing <easing>", "standard easing name or four comma-separated cubic Bézier values")),
|
|
72
|
+
examples: [
|
|
73
|
+
"phresh window set-transaction --process overlay --default",
|
|
74
|
+
"phresh window set-transaction --process overlay --duration 240 --easing ease-out"
|
|
75
|
+
]
|
|
76
|
+
}, async ({ options }) => executeWindow(connect, options, {
|
|
77
|
+
$operation: "setTransaction",
|
|
78
|
+
transaction: transaction(options)
|
|
79
|
+
}));
|
|
59
80
|
defineCommand(windows, {
|
|
60
81
|
...state("raise", windowRaisePresentation),
|
|
61
82
|
examples: ["phresh window raise --process main --program terminal"]
|
|
@@ -66,10 +87,10 @@ export default function windowCommands(root, connect) {
|
|
|
66
87
|
requiresSystem: true,
|
|
67
88
|
options: withJson(...processOptions, option("--event <event>", "Window event", {
|
|
68
89
|
mandatory: true,
|
|
69
|
-
choices: ["move", "resize", "
|
|
90
|
+
choices: ["move", "resize", "minimize", "maximize", "changeTitle", "changeHeader", "changeFrame", "changeTransaction", "front"]
|
|
70
91
|
}), timeoutOption),
|
|
71
92
|
output: dataOutput(eventOutput("The observed Window event"), "One Window event", eventPresentation),
|
|
72
|
-
examples: ["phresh window wait --process main --program terminal --event
|
|
93
|
+
examples: ["phresh window wait --process main --program terminal --event move --json"]
|
|
73
94
|
}, async ({ options }) => executeWindow(connect, options, {
|
|
74
95
|
$operation: "wait",
|
|
75
96
|
event: options.event,
|
|
@@ -94,3 +115,61 @@ async function executeWindow(connect, options, operation) {
|
|
|
94
115
|
});
|
|
95
116
|
return connected(connect, system => system.execute(request));
|
|
96
117
|
}
|
|
118
|
+
function frame(options) {
|
|
119
|
+
const materialValues = material(options);
|
|
120
|
+
const customized = options.radius !== undefined || options.color !== undefined || materialValues !== undefined;
|
|
121
|
+
const modes = Number(options.default === true) + Number(options.absent === true) + Number(customized);
|
|
122
|
+
if (modes !== 1)
|
|
123
|
+
throw new Error("Choose exactly one of --default, --absent, or frame customization options");
|
|
124
|
+
if (options.default)
|
|
125
|
+
return true;
|
|
126
|
+
if (options.absent)
|
|
127
|
+
return false;
|
|
128
|
+
return parseWindowFrame({
|
|
129
|
+
...(options.radius === undefined ? {} : { radius: options.radius === "full" ? "full" : numeric(options.radius, "--radius") }),
|
|
130
|
+
...(options.color === undefined ? {} : { color: options.color }),
|
|
131
|
+
...(materialValues === undefined ? {} : { material: materialValues })
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function material(options) {
|
|
135
|
+
const values = {
|
|
136
|
+
grain: options.grain,
|
|
137
|
+
grainAmount: options.grainAmount,
|
|
138
|
+
backdrop: options.backdrop,
|
|
139
|
+
opacity: options.opacity,
|
|
140
|
+
distortion: options.distortion,
|
|
141
|
+
saturation: options.saturation
|
|
142
|
+
};
|
|
143
|
+
const customized = Object.values(values).some(value => value !== undefined);
|
|
144
|
+
const modes = Number(options.withoutMaterial === true) + Number(customized);
|
|
145
|
+
if (modes > 1)
|
|
146
|
+
throw new Error("Choose only one Material mode");
|
|
147
|
+
if (options.withoutMaterial)
|
|
148
|
+
return false;
|
|
149
|
+
if (!customized)
|
|
150
|
+
return undefined;
|
|
151
|
+
return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined));
|
|
152
|
+
}
|
|
153
|
+
function transaction(options) {
|
|
154
|
+
const customized = options.duration !== undefined || options.easing !== undefined;
|
|
155
|
+
const modes = Number(options.default === true) + Number(options.disabled === true) + Number(customized);
|
|
156
|
+
if (modes !== 1)
|
|
157
|
+
throw new Error("Choose exactly one of --default, --disabled, or --duration");
|
|
158
|
+
if (options.default)
|
|
159
|
+
return true;
|
|
160
|
+
if (options.disabled)
|
|
161
|
+
return false;
|
|
162
|
+
if (options.duration === undefined)
|
|
163
|
+
throw new Error("--easing requires --duration");
|
|
164
|
+
if (options.easing === undefined)
|
|
165
|
+
return parseWindowTransaction(options.duration);
|
|
166
|
+
const pieces = options.easing.split(",").map(value => value.trim());
|
|
167
|
+
const easing = pieces.length === 4 ? pieces.map(value => numeric(value, "--easing")) : options.easing;
|
|
168
|
+
return parseWindowTransaction({ duration: options.duration, easing });
|
|
169
|
+
}
|
|
170
|
+
function numeric(value, name) {
|
|
171
|
+
const result = Number(value);
|
|
172
|
+
if (!Number.isFinite(result))
|
|
173
|
+
throw new Error(`${name} must be a finite number`);
|
|
174
|
+
return result;
|
|
175
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.66",
|
|
5
5
|
"description": "The Phresh command-line interface for Program projects and system management.",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.10"
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"packageManager": "bun@1.3.14",
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@clack/prompts": "^1.7.0",
|
|
50
|
-
"@phreshos/core": "^0.1.
|
|
51
|
-
"@phreshos/node": "^0.1.
|
|
50
|
+
"@phreshos/core": "^0.1.55",
|
|
51
|
+
"@phreshos/node": "^0.1.28",
|
|
52
52
|
"adm-zip": "^0.6.0",
|
|
53
53
|
"commander": "^15.0.0",
|
|
54
54
|
"picocolors": "^1.1.1"
|