@phreshos/client 0.1.46 → 0.1.47
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/context.js +8 -8
- package/dist/domain.d.ts +2 -2
- package/dist/domain.js +66 -41
- package/dist/service.d.ts +4 -8
- package/dist/service.js +56 -34
- package/dist/system.js +18 -1
- package/dist/wire.d.ts +2 -2
- package/dist/wire.js +2 -2
- package/package.json +3 -3
package/dist/context.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Deadline from "./deadline.js";
|
|
2
|
-
import { ClientEndpoint, ServerEndpoint, ServerTrafficHandle, TrafficHandle, endpointLifecycle, endpointEvents, process, program, visibleEndpoint,
|
|
2
|
+
import { ClientEndpoint, ServerEndpoint, ServerTrafficHandle, TrafficHandle, endpointLifecycle, endpointEvents, process, program, visibleEndpoint, presentation, window as windowHandle, } from "./domain.js";
|
|
3
3
|
import Events from "./events.js";
|
|
4
4
|
import wire from "./wire.js";
|
|
5
5
|
import { contextPermissions } from "./permissions.js";
|
|
@@ -18,12 +18,12 @@ class ContextServerHandle extends ServerEndpoint {
|
|
|
18
18
|
this.wait = events.wait;
|
|
19
19
|
this.events = events.events;
|
|
20
20
|
}
|
|
21
|
-
process() { return this.owner(); }
|
|
21
|
+
async process() { await this.running(); return this.owner(); }
|
|
22
22
|
publish = (event, payload = undefined) => {
|
|
23
23
|
wire.send("end-end", event, payload);
|
|
24
24
|
};
|
|
25
|
-
async
|
|
26
|
-
const answer = await wire.request(["
|
|
25
|
+
async running() {
|
|
26
|
+
const answer = await wire.request(["running", "server"]);
|
|
27
27
|
return answer[0];
|
|
28
28
|
}
|
|
29
29
|
async start(launch = {}) { await wire.request(["start-endpoint", undefined, "server", launch]); }
|
|
@@ -76,14 +76,14 @@ class ContextClientHandle extends ClientEndpoint {
|
|
|
76
76
|
this.wait = events.wait;
|
|
77
77
|
this.events = events.events;
|
|
78
78
|
}
|
|
79
|
-
process() { return this.owner(); }
|
|
79
|
+
async process() { await this.running(); return this.owner(); }
|
|
80
80
|
publish = (event, payload = undefined) => {
|
|
81
81
|
void wire.identity().then(identity => {
|
|
82
82
|
wire.send("end-host", "send", { identity: identity.process, reference: identity.reference }, "client", event, payload);
|
|
83
83
|
});
|
|
84
84
|
};
|
|
85
|
-
async
|
|
86
|
-
const answer = await wire.request(["
|
|
85
|
+
async running() {
|
|
86
|
+
const answer = await wire.request(["running", "client"]);
|
|
87
87
|
return answer[0];
|
|
88
88
|
}
|
|
89
89
|
async start(launch = {}) { await wire.request(["start-endpoint", undefined, "client", launch]); }
|
|
@@ -95,7 +95,7 @@ contextClient = new ContextClientHandle(owner);
|
|
|
95
95
|
class ClientContext extends Events {
|
|
96
96
|
server = contextServer;
|
|
97
97
|
window = contextClient.window;
|
|
98
|
-
|
|
98
|
+
presentation = presentation(currentAddress);
|
|
99
99
|
permissions = contextPermissions();
|
|
100
100
|
constructor() {
|
|
101
101
|
super((event, listener, impossible) => wire.on("end-end", event, value => listener(contextMessage(value)), null, impossible), (listener, impossible) => wire.onAll("end-end", (event, value) => {
|
package/dist/domain.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type AnswerOutcome, type AnswerSubscriber as CoreAnswerSubscriber, type AskCapture as CoreAskCapture, type AskMessage as CoreAskMessage, type AskSubscriber as CoreAskSubscriber, type Cleanup, type ClientTraffic as CoreClientTraffic, type ClientDeclaration, type EndpointReference as CoreEndpointReference, type EndpointSnapshot, type HandleAddress, type ProcessSnapshot, type ProgramSnapshot, type EndpointTraffic as CoreEndpointTraffic, type EndpointLifecycleEvents, type EndpointDeclaration, type Exit, type EventOptions, type
|
|
1
|
+
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type AnswerOutcome, type AnswerSubscriber as CoreAnswerSubscriber, type AskCapture as CoreAskCapture, type AskMessage as CoreAskMessage, type AskSubscriber as CoreAskSubscriber, type Cleanup, type ClientTraffic as CoreClientTraffic, type ClientDeclaration, type EndpointReference as CoreEndpointReference, type EndpointSnapshot, type HandleAddress, type ProcessSnapshot, type ProgramSnapshot, type EndpointTraffic as CoreEndpointTraffic, type EndpointLifecycleEvents, type EndpointDeclaration, type Exit, type EventOptions, type WindowPresentation, type ProgramProcessRunEvent as CoreProgramProcessRunEvent, type ProgramProcessRunOptions as CoreProgramProcessRunOptions, type ServerTraffic as CoreServerTraffic, type TrafficMessage as CoreTrafficMessage, type TrafficCapture as CoreTrafficCapture, type TrafficEvents as CoreTrafficEvents, type Window as CoreWindow, type WindowState } from "@phreshos/core";
|
|
2
2
|
import Events from "./events.js";
|
|
3
3
|
export type { HandleAddress };
|
|
4
4
|
export type EndpointDeclarationRecord = EndpointDeclaration;
|
|
@@ -83,7 +83,7 @@ export declare function process(value: unknown, endpoints?: {
|
|
|
83
83
|
export declare function endpoint(value: unknown): Endpoint;
|
|
84
84
|
export declare function claimEndpoint(reference: string, kind: "server" | "client", endpoint: Endpoint): Endpoint<{}, unknown>;
|
|
85
85
|
export declare function window(target: WindowTarget): Window;
|
|
86
|
-
export declare function
|
|
86
|
+
export declare function presentation(target: WindowTarget): WindowPresentation;
|
|
87
87
|
/** Resolves an Endpoint reference through the Client Endpoint's global handle registry. */
|
|
88
88
|
export declare function visibleEndpoint(reference: EndpointReference | null | undefined): Endpoint | null;
|
|
89
89
|
/** Runtime constructor shared by all client-visible Program handles. */
|
package/dist/domain.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, parseEndpointReference, parseProcessSnapshot, parseProgramSnapshot } from "@phreshos/core";
|
|
1
|
+
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, parseEndpointReference, parseProcessSnapshot, parseProgramSnapshot, } from "@phreshos/core";
|
|
2
2
|
import Events, { stream } from "./events.js";
|
|
3
3
|
import Deadline from "./deadline.js";
|
|
4
4
|
import HandleRegistry from "./handle-registry.js";
|
|
@@ -236,12 +236,12 @@ class ServerEndpointHandle extends CoreServerEndpoint {
|
|
|
236
236
|
this.wait = events.wait;
|
|
237
237
|
this.events = events.events;
|
|
238
238
|
}
|
|
239
|
-
async process() { return this.owner; }
|
|
239
|
+
async process() { await this.running(); return this.owner; }
|
|
240
240
|
publish = (event, payload = undefined) => {
|
|
241
241
|
wire.send("end-host", "send", this.owner.address, "server", event, payload);
|
|
242
242
|
};
|
|
243
|
-
async
|
|
244
|
-
const answer = await wire.request(["
|
|
243
|
+
async running() {
|
|
244
|
+
const answer = await wire.request(["running", "server", this.owner.address]);
|
|
245
245
|
return answer[0];
|
|
246
246
|
}
|
|
247
247
|
async start(launch = {}) { await wire.request(["start-endpoint", this.owner.address, "server", launch]); }
|
|
@@ -289,12 +289,12 @@ class ClientEndpointHandle extends CoreClientEndpoint {
|
|
|
289
289
|
this.wait = events.wait;
|
|
290
290
|
this.events = events.events;
|
|
291
291
|
}
|
|
292
|
-
async process() { return this.owner; }
|
|
292
|
+
async process() { await this.running(); return this.owner; }
|
|
293
293
|
publish = (event, payload = undefined) => {
|
|
294
294
|
wire.send("end-host", "send", this.owner.address, "client", event, payload);
|
|
295
295
|
};
|
|
296
|
-
async
|
|
297
|
-
const answer = await wire.request(["
|
|
296
|
+
async running() {
|
|
297
|
+
const answer = await wire.request(["running", "client", this.owner.address]);
|
|
298
298
|
return answer[0];
|
|
299
299
|
}
|
|
300
300
|
async start(launch = {}) { await wire.request(["start-endpoint", this.owner.address, "client", launch]); }
|
|
@@ -314,6 +314,8 @@ class WindowHandle extends Events {
|
|
|
314
314
|
}
|
|
315
315
|
async title() { return (await this.state()).title; }
|
|
316
316
|
async header() { return (await this.state()).header; }
|
|
317
|
+
async frame() { return (await this.state()).frame; }
|
|
318
|
+
async transaction() { return (await this.state()).transaction; }
|
|
317
319
|
async position() { return (await this.state()).position; }
|
|
318
320
|
async size() { return (await this.state()).size; }
|
|
319
321
|
async minimized() { return (await this.state()).minimized; }
|
|
@@ -325,40 +327,61 @@ class WindowHandle extends Events {
|
|
|
325
327
|
async setGeometry(geometry) { await wire.request(["setGeometry", await this.target(), geometry]); }
|
|
326
328
|
async minimize(minimized = true) { await wire.request(["minimize", await this.target(), minimized]); }
|
|
327
329
|
async maximize(maximized = true) { await wire.request(["maximize", await this.target(), maximized]); }
|
|
328
|
-
async
|
|
329
|
-
async
|
|
330
|
+
async setTitle(title) { await wire.request(["setTitle", await this.target(), title]); }
|
|
331
|
+
async setHeader(header) { await wire.request(["setHeader", await this.target(), header]); }
|
|
332
|
+
async setFrame(frame) { await wire.request(["setFrame", await this.target(), frame]); }
|
|
333
|
+
async setTransaction(transaction) { await wire.request(["setTransaction", await this.target(), transaction]); }
|
|
330
334
|
async raise() { await wire.request(["raise", await this.target()]); }
|
|
331
335
|
}
|
|
332
|
-
|
|
333
|
-
class LocalWindowHandle {
|
|
336
|
+
class WindowPresentationHandle extends Events {
|
|
334
337
|
target;
|
|
335
338
|
selected;
|
|
336
339
|
constructor(target, selected) {
|
|
340
|
+
super((event, listener, impossible) => {
|
|
341
|
+
if (!windowEvent(event)) {
|
|
342
|
+
impossible?.(new Error(`A Window presentation has no "${event}" event`));
|
|
343
|
+
return () => undefined;
|
|
344
|
+
}
|
|
345
|
+
return wire.on("presentation", event, listener, null, impossible);
|
|
346
|
+
}, (listener, impossible) => wire.onAll("presentation", (event, ...values) => {
|
|
347
|
+
if (typeof event === "string")
|
|
348
|
+
listener(event, values[0]);
|
|
349
|
+
}, null, impossible));
|
|
337
350
|
this.target = target;
|
|
338
351
|
this.selected = selected;
|
|
339
352
|
}
|
|
340
353
|
transaction(transaction) {
|
|
341
|
-
return new
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
async
|
|
347
|
-
async
|
|
348
|
-
async
|
|
349
|
-
async
|
|
350
|
-
async
|
|
351
|
-
async
|
|
352
|
-
async
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
async
|
|
359
|
-
async
|
|
354
|
+
return new WindowPresentationHandle(this.target, { transaction, wait: false });
|
|
355
|
+
}
|
|
356
|
+
transactionAndWait(transaction) {
|
|
357
|
+
return new WindowPresentationHandle(this.target, { transaction, wait: true });
|
|
358
|
+
}
|
|
359
|
+
async title() { return await this.read("title"); }
|
|
360
|
+
async header() { return await this.read("header"); }
|
|
361
|
+
async frame() { return await this.read("frame"); }
|
|
362
|
+
async position() { return await this.read("position"); }
|
|
363
|
+
async size() { return await this.read("size"); }
|
|
364
|
+
async minimized() { return await this.read("minimized"); }
|
|
365
|
+
async maximized() { return await this.read("maximized"); }
|
|
366
|
+
async front() { return await this.read("front"); }
|
|
367
|
+
async layer() { return await this.read("layer"); }
|
|
368
|
+
async move(position) { await this.change("windowPresentationMove", position); }
|
|
369
|
+
async resize(size) { await this.change("windowPresentationResize", size); }
|
|
370
|
+
async setGeometry(geometry) { await this.change("windowPresentationGeometry", geometry); }
|
|
371
|
+
async minimize(minimized = true) { await this.change("windowPresentationMinimize", minimized); }
|
|
372
|
+
async maximize(maximized = true) { await this.change("windowPresentationMaximize", maximized); }
|
|
373
|
+
async setTitle(title) { await this.change("windowPresentationTitle", title); }
|
|
374
|
+
async setHeader(header) { await this.change("windowPresentationHeader", header); }
|
|
375
|
+
async setFrame(frame) { await this.change("windowPresentationFrame", frame); }
|
|
376
|
+
async follow() { await this.change("windowPresentationFollow"); }
|
|
377
|
+
async unfollow() { await this.change("windowPresentationUnfollow"); }
|
|
378
|
+
async raise() { await this.change("windowPresentationRaise"); }
|
|
360
379
|
async change(operation, value) {
|
|
361
|
-
await wire.request([operation, await this.target(), value, this.selected]);
|
|
380
|
+
await wire.request([operation, await this.target(), value, this.selected?.transaction, this.selected?.wait === true]);
|
|
381
|
+
}
|
|
382
|
+
async read(property) {
|
|
383
|
+
const answer = await wire.request(["windowPresentationRead", await this.target(), property]);
|
|
384
|
+
return answer[0];
|
|
362
385
|
}
|
|
363
386
|
}
|
|
364
387
|
function deferredScoped(route, target, convert) {
|
|
@@ -384,7 +407,7 @@ function deferredScoped(route, target, convert) {
|
|
|
384
407
|
];
|
|
385
408
|
}
|
|
386
409
|
function windowEvent(event) {
|
|
387
|
-
return event === "move" || event === "resize" || event === "
|
|
410
|
+
return event === "move" || event === "resize" || event === "minimize" || event === "maximize" || event === "changeTitle" || event === "changeHeader" || event === "changeFrame" || event === "changeTransaction" || event === "front";
|
|
388
411
|
}
|
|
389
412
|
function deferred(target, register, impossible) {
|
|
390
413
|
let active = true;
|
|
@@ -396,8 +419,6 @@ function deferred(target, register, impossible) {
|
|
|
396
419
|
const failure = error instanceof Error ? error : new Error(String(error));
|
|
397
420
|
if (active && impossible)
|
|
398
421
|
impossible(failure);
|
|
399
|
-
else if (active)
|
|
400
|
-
queueMicrotask(() => { throw failure; });
|
|
401
422
|
});
|
|
402
423
|
return () => {
|
|
403
424
|
active = false;
|
|
@@ -426,11 +447,17 @@ export function endpointEvents(target, half) {
|
|
|
426
447
|
}
|
|
427
448
|
/** Start and stop transitions belonging directly to one permanent Endpoint. */
|
|
428
449
|
export function endpointLifecycle(target, half) {
|
|
429
|
-
|
|
450
|
+
const resolved = () => target();
|
|
451
|
+
const viable = async () => {
|
|
452
|
+
const address = await resolved();
|
|
453
|
+
await wire.request(["running", half, address]);
|
|
454
|
+
return address;
|
|
455
|
+
};
|
|
456
|
+
return new Events((event, listener, impossible) => deferred(impossible ? viable : resolved, subject => wire.on("process-host", endpointLifecycleEvent(event), (...values) => {
|
|
430
457
|
const message = unscoped(subject, values);
|
|
431
458
|
if (message?.[1] === half)
|
|
432
459
|
listener(undefined);
|
|
433
|
-
}, subject, impossible), impossible), (listener, impossible) => deferred(
|
|
460
|
+
}, subject, impossible), impossible), (listener, impossible) => deferred(impossible ? viable : resolved, subject => wire.onAll("process-host", (event, ...values) => {
|
|
434
461
|
if (event !== "endpointStart" && event !== "endpointStop")
|
|
435
462
|
return;
|
|
436
463
|
const message = unscoped(subject, values);
|
|
@@ -496,12 +523,10 @@ function endpointHandle(owner, kind, preferred) {
|
|
|
496
523
|
return handles.obtain(`endpoint:${owner.reference}:${kind}`, () => preferred ?? (kind === "server" ? new ServerEndpointHandle(owner) : new ClientEndpointHandle(owner)));
|
|
497
524
|
}
|
|
498
525
|
export function window(target) {
|
|
499
|
-
|
|
500
|
-
windowTargets.set(handle, target);
|
|
501
|
-
return handle;
|
|
526
|
+
return new WindowHandle(target);
|
|
502
527
|
}
|
|
503
|
-
export function
|
|
504
|
-
return new
|
|
528
|
+
export function presentation(target) {
|
|
529
|
+
return new WindowPresentationHandle(target);
|
|
505
530
|
}
|
|
506
531
|
/** Resolves an Endpoint reference through the Client Endpoint's global handle registry. */
|
|
507
532
|
export function visibleEndpoint(reference) {
|
package/dist/service.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import { type ClientService, type ServerService, type
|
|
2
|
-
export declare function prepareService<EventsMap extends object = {}, Fallback = unknown>(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare function prepareService<EventsMap extends object = {}, Fallback = unknown>(key: ServiceKey & {
|
|
6
|
-
endpoint: "client";
|
|
7
|
-
}): ClientService<EventsMap, Fallback>;
|
|
8
|
-
export declare function prepareService(key: ServiceKey): Service;
|
|
1
|
+
import { type ClientService, type ServerService, type ServiceAddress } from "@phreshos/core";
|
|
2
|
+
export declare function prepareService<EventsMap extends object = {}, Fallback = unknown>(address: ServiceAddress<"server">): ServerService<EventsMap, Fallback>;
|
|
3
|
+
export declare function prepareService<EventsMap extends object = {}, Fallback = unknown>(address: ServiceAddress<"client">): ClientService<EventsMap, Fallback>;
|
|
4
|
+
export declare function prepareService(address: ServiceAddress): ServerService | ClientService;
|
package/dist/service.js
CHANGED
|
@@ -1,46 +1,54 @@
|
|
|
1
|
-
import { ClientService as CoreClientService, ServerService as CoreServerService,
|
|
1
|
+
import { ClientService as CoreClientService, ServerService as CoreServerService, isServiceAddress } from "@phreshos/core";
|
|
2
2
|
import Deadline from "./deadline.js";
|
|
3
3
|
import Events from "./events.js";
|
|
4
4
|
import HandleRegistry from "./handle-registry.js";
|
|
5
5
|
import wire from "./wire.js";
|
|
6
6
|
const handles = new HandleRegistry();
|
|
7
7
|
class ServiceHandle {
|
|
8
|
-
|
|
8
|
+
serviceAddress;
|
|
9
9
|
lifecycle;
|
|
10
|
-
constructor(
|
|
11
|
-
this.
|
|
12
|
-
this.lifecycle = new Events(...serviceEvents(
|
|
10
|
+
constructor(serviceAddress) {
|
|
11
|
+
this.serviceAddress = serviceAddress;
|
|
12
|
+
this.lifecycle = new Events(...serviceEvents(serviceAddress, "lifecycle"));
|
|
13
13
|
}
|
|
14
14
|
publish(event, payload = undefined) {
|
|
15
|
-
wire.send("end-host", "service-send", this.
|
|
15
|
+
wire.send("end-host", "service-send", this.serviceAddress, event, payload);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
address() { return this.serviceAddress; }
|
|
18
|
+
async available() {
|
|
19
|
+
const answer = await wire.request(["service-available", this.serviceAddress]);
|
|
19
20
|
return answer[0];
|
|
20
21
|
}
|
|
21
22
|
async waitReady(timeout) {
|
|
22
|
-
await wire.request(["service-wait-ready", this.
|
|
23
|
+
await wire.request(["service-wait-ready", this.serviceAddress, timeout], timeout);
|
|
24
|
+
}
|
|
25
|
+
async programMetadata(options = {}) {
|
|
26
|
+
const iconSize = options.icon ?? "medium";
|
|
27
|
+
const [value] = await wire.request(["service-program-metadata", this.serviceAddress, iconSize]);
|
|
28
|
+
return parseServiceProgramMetadata(value);
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
class ServerHandler extends CoreServerService {
|
|
26
|
-
|
|
32
|
+
serviceAddress;
|
|
27
33
|
subscribe;
|
|
28
34
|
wait;
|
|
29
35
|
events;
|
|
30
36
|
lifecycle;
|
|
31
37
|
service;
|
|
32
|
-
constructor(
|
|
38
|
+
constructor(serviceAddress) {
|
|
33
39
|
super();
|
|
34
|
-
this.
|
|
35
|
-
this.service = new ServiceHandle(
|
|
40
|
+
this.serviceAddress = serviceAddress;
|
|
41
|
+
this.service = new ServiceHandle(serviceAddress);
|
|
36
42
|
this.lifecycle = this.service.lifecycle;
|
|
37
|
-
const events = new Events(...serviceEvents(
|
|
43
|
+
const events = new Events(...serviceEvents(serviceAddress, "events"));
|
|
38
44
|
this.subscribe = events.subscribe;
|
|
39
45
|
this.wait = events.wait;
|
|
40
46
|
this.events = events.events;
|
|
41
47
|
}
|
|
42
48
|
publish = (event, payload = undefined) => { this.service.publish(event, payload); };
|
|
43
|
-
|
|
49
|
+
address() { return this.serviceAddress; }
|
|
50
|
+
available() { return this.service.available(); }
|
|
51
|
+
programMetadata(options) { return this.service.programMetadata(options); }
|
|
44
52
|
waitReady(timeout) { return this.service.waitReady(timeout); }
|
|
45
53
|
async ask(event, payload = undefined) {
|
|
46
54
|
return await this.askWithin(new Deadline(), event, payload);
|
|
@@ -53,7 +61,7 @@ class ServerHandler extends CoreServerService {
|
|
|
53
61
|
const address = `client:${identity.process}:${crypto.randomUUID()}`;
|
|
54
62
|
const question = crypto.randomUUID();
|
|
55
63
|
const waiting = wire.expectWithin(address, deadline);
|
|
56
|
-
wire.send("end-host", "service-ask", this.
|
|
64
|
+
wire.send("end-host", "service-ask", this.serviceAddress, address, question, event, payload);
|
|
57
65
|
try {
|
|
58
66
|
return await waiting;
|
|
59
67
|
}
|
|
@@ -63,45 +71,59 @@ class ServerHandler extends CoreServerService {
|
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
class ClientHandler extends CoreClientService {
|
|
74
|
+
serviceAddress;
|
|
66
75
|
subscribe;
|
|
67
76
|
wait;
|
|
68
77
|
events;
|
|
69
78
|
lifecycle;
|
|
70
79
|
service;
|
|
71
|
-
constructor(
|
|
80
|
+
constructor(serviceAddress) {
|
|
72
81
|
super();
|
|
73
|
-
this.
|
|
82
|
+
this.serviceAddress = serviceAddress;
|
|
83
|
+
this.service = new ServiceHandle(serviceAddress);
|
|
74
84
|
this.lifecycle = this.service.lifecycle;
|
|
75
|
-
const events = new Events(...serviceEvents(
|
|
85
|
+
const events = new Events(...serviceEvents(serviceAddress, "events"));
|
|
76
86
|
this.subscribe = events.subscribe;
|
|
77
87
|
this.wait = events.wait;
|
|
78
88
|
this.events = events.events;
|
|
79
89
|
}
|
|
80
90
|
publish = (event, payload = undefined) => { this.service.publish(event, payload); };
|
|
81
|
-
|
|
91
|
+
address() { return this.serviceAddress; }
|
|
92
|
+
available() { return this.service.available(); }
|
|
93
|
+
programMetadata(options) { return this.service.programMetadata(options); }
|
|
82
94
|
waitReady(timeout) { return this.service.waitReady(timeout); }
|
|
83
95
|
}
|
|
84
|
-
export function prepareService(
|
|
85
|
-
if (!
|
|
86
|
-
throw new Error("A complete
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
process:
|
|
90
|
-
});
|
|
91
|
-
const identity = JSON.stringify([key.program ?? null, key.process, key.endpoint]);
|
|
92
|
-
if (key.endpoint === "server") {
|
|
93
|
-
const normalized = Object.freeze({ ...address, endpoint: "server" });
|
|
96
|
+
export function prepareService(address) {
|
|
97
|
+
if (!isServiceAddress(address))
|
|
98
|
+
throw new Error("A complete Service address is required");
|
|
99
|
+
const identity = JSON.stringify([address.program, address.process, address.endpoint]);
|
|
100
|
+
if (address.endpoint === "server") {
|
|
101
|
+
const normalized = Object.freeze({ program: address.program, process: address.process, endpoint: "server" });
|
|
94
102
|
return handles.obtain(`service:${identity}`, () => new ServerHandler(normalized));
|
|
95
103
|
}
|
|
96
|
-
const normalized = Object.freeze({
|
|
104
|
+
const normalized = Object.freeze({ program: address.program, process: address.process, endpoint: "client" });
|
|
97
105
|
return handles.obtain(`service:${identity}`, () => new ClientHandler(normalized));
|
|
98
106
|
}
|
|
99
|
-
function serviceEvents(
|
|
107
|
+
function serviceEvents(address, scope) {
|
|
100
108
|
return [
|
|
101
|
-
(event, listener, impossible) => wire.followService(
|
|
102
|
-
(listener, impossible) => wire.followService(
|
|
109
|
+
(event, listener, impossible) => wire.followService(address, scope, event, listener, impossible),
|
|
110
|
+
(listener, impossible) => wire.followService(address, scope, null, (event, payload) => {
|
|
103
111
|
if (typeof event === "string")
|
|
104
112
|
listener(event, payload);
|
|
105
113
|
}, impossible)
|
|
106
114
|
];
|
|
107
115
|
}
|
|
116
|
+
function parseServiceProgramMetadata(value) {
|
|
117
|
+
if (!value || typeof value !== "object")
|
|
118
|
+
throw new Error("The System returned invalid Service Program metadata");
|
|
119
|
+
const metadata = value;
|
|
120
|
+
if (typeof metadata.name !== "string" || typeof metadata.version !== "string"
|
|
121
|
+
|| !Array.isArray(metadata.icon) || metadata.icon.some(byte => typeof byte !== "number")) {
|
|
122
|
+
throw new Error("The System returned invalid Service Program metadata");
|
|
123
|
+
}
|
|
124
|
+
return Object.freeze({
|
|
125
|
+
name: metadata.name,
|
|
126
|
+
version: metadata.version,
|
|
127
|
+
icon: new Blob([Uint8Array.from(metadata.icon)], { type: "image/png" })
|
|
128
|
+
});
|
|
129
|
+
}
|
package/dist/system.js
CHANGED
|
@@ -15,18 +15,35 @@ class ClientSystem {
|
|
|
15
15
|
process = new SystemProcessHandle();
|
|
16
16
|
connection = new SystemConnectionHandle();
|
|
17
17
|
session = new SystemSessionHandle();
|
|
18
|
+
service = new SystemServiceHandle();
|
|
18
19
|
uploads = uploads;
|
|
19
20
|
network = network;
|
|
20
21
|
execute(request) {
|
|
21
22
|
return executeRequest(this, request);
|
|
22
23
|
}
|
|
23
|
-
service(key) { return prepareService(key); }
|
|
24
24
|
async *shell(command, options = {}) {
|
|
25
25
|
const { signal, ...settings } = options;
|
|
26
26
|
for await (const event of wire.stream(["shell", command, settings], undefined, signal))
|
|
27
27
|
yield parseShellEvent(event);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
class SystemServiceHandle extends Events {
|
|
31
|
+
constructor() {
|
|
32
|
+
super((event, listener, impossible) => wire.on("host-service", event, (...values) => listener(prepareService(values[1])), null, impossible), observer => wire.onAll("host-service", (event, ...values) => {
|
|
33
|
+
if (typeof event === "string")
|
|
34
|
+
observer(event, prepareService(values[1]));
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
async list() {
|
|
38
|
+
const [addresses] = await wire.request(["host-service-list"]);
|
|
39
|
+
return addresses.map(address => prepareService(address));
|
|
40
|
+
}
|
|
41
|
+
async search(name) {
|
|
42
|
+
const [addresses] = await wire.request(["host-service-search", name]);
|
|
43
|
+
return addresses.map(address => prepareService(address));
|
|
44
|
+
}
|
|
45
|
+
prepare(address) { return prepareService(address); }
|
|
46
|
+
}
|
|
30
47
|
class SystemProgramHandle extends Events {
|
|
31
48
|
constructor() {
|
|
32
49
|
super((event, listener, impossible) => wire.on("host-program", event, (...values) => listener(systemProgramEvent(event, values)), null, impossible), observer => wire.onAll("host-program", (event, ...values) => {
|
package/dist/wire.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Cleanup,
|
|
1
|
+
import type { Cleanup, ServiceAddress } from "@phreshos/core";
|
|
2
2
|
import Deadline from "./deadline.js";
|
|
3
3
|
import type { HandleAddress } from "./domain.js";
|
|
4
4
|
type Handler = (...values: unknown[]) => unknown;
|
|
@@ -37,7 +37,7 @@ declare class Wire {
|
|
|
37
37
|
/** Follow destinationless events emitted by one Endpoint. */
|
|
38
38
|
follow(target: HandleAddress | null, half: "server" | "client", event: string | null, handler: Handler, impossible?: Failure): Cleanup;
|
|
39
39
|
/** Follow one exact service lifecycle or application event route. */
|
|
40
|
-
followService(
|
|
40
|
+
followService(address: ServiceAddress, scope: "lifecycle" | "events", event: string | null, handler: Handler, impossible?: Failure): Cleanup;
|
|
41
41
|
private register;
|
|
42
42
|
private unregister;
|
|
43
43
|
private deliver;
|
package/dist/wire.js
CHANGED
|
@@ -269,12 +269,12 @@ class Wire {
|
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
271
|
/** Follow one exact service lifecycle or application event route. */
|
|
272
|
-
followService(
|
|
272
|
+
followService(address, scope, event, handler, impossible) {
|
|
273
273
|
const subscription = crypto.randomUUID();
|
|
274
274
|
const stop = this.on("service-event", subscription, handler);
|
|
275
275
|
if (impossible)
|
|
276
276
|
this.impossible.set(subscription, impossible);
|
|
277
|
-
this.send("end-host", "service-follow", subscription,
|
|
277
|
+
this.send("end-host", "service-follow", subscription, address, scope, event, impossible !== undefined);
|
|
278
278
|
return once(() => {
|
|
279
279
|
stop();
|
|
280
280
|
this.impossible.delete(subscription);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.47",
|
|
4
4
|
"description": "The SDK used by a Program's client endpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"test": "vitest run --project default"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@phreshos/core": "^0.1.
|
|
49
|
+
"@phreshos/core": "^0.1.55"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@the-link/messagepack": "^0.1.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@phreshos/core": "^0.1.
|
|
55
|
+
"@phreshos/core": "^0.1.55",
|
|
56
56
|
"typescript": "^6.0.3",
|
|
57
57
|
"vitest": "^4.1.10"
|
|
58
58
|
}
|