@phreshos/client 0.1.25 → 0.1.27
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 +11 -7
- package/dist/context.d.ts +10 -4
- package/dist/context.js +21 -19
- package/dist/domain.d.ts +27 -7
- package/dist/domain.js +58 -34
- package/dist/events.d.ts +7 -3
- package/dist/events.js +60 -53
- package/dist/main.d.ts +4 -5
- package/dist/main.js +0 -1
- package/dist/service.js +20 -33
- package/dist/wire.d.ts +2 -2
- package/dist/wire.js +2 -2
- package/package.json +3 -3
- package/dist/channel.d.ts +0 -12
- package/dist/channel.js +0 -22
package/README.md
CHANGED
|
@@ -80,7 +80,10 @@ const service = system.service({
|
|
|
80
80
|
})
|
|
81
81
|
|
|
82
82
|
await service.waitReady()
|
|
83
|
-
if (await service.enabled()) await service.
|
|
83
|
+
if (await service.enabled()) await service.ask("value")
|
|
84
|
+
|
|
85
|
+
service.subscribe("changed", message => console.log(message))
|
|
86
|
+
service.lifecycle.subscribe("disable", () => console.log("unavailable"))
|
|
84
87
|
```
|
|
85
88
|
|
|
86
89
|
A Client may traverse `Process.parent()` through any number of ancestors in
|
|
@@ -98,8 +101,8 @@ into the endpoint. Identity, Theme, Process, Window, readiness, lifecycle, and
|
|
|
98
101
|
application values enter only in response to an explicit request or a live
|
|
99
102
|
registration made by Program code.
|
|
100
103
|
|
|
101
|
-
`Context` combines navigation into the executing Client's
|
|
102
|
-
|
|
104
|
+
`Context` combines communication with navigation into the executing Client's
|
|
105
|
+
Process. The paired Server is explicitly named as
|
|
103
106
|
`context.server`; its publishing, asking, existence, readiness, start, and stop
|
|
104
107
|
operations never masquerade as properties of `context`. `context.stop()` stops
|
|
105
108
|
the executing Client, while complete Process exit remains available only
|
|
@@ -131,11 +134,12 @@ them. These are the same domain classes used by the Server SDK, so
|
|
|
131
134
|
`ClientTraffic`, is a type-only capability owned by Client and has no
|
|
132
135
|
independent `instanceof` identity.
|
|
133
136
|
|
|
134
|
-
The executing Client's
|
|
137
|
+
The executing Client's communication belongs directly to `context`. Its
|
|
135
138
|
subscription tools receive events addressed to this Client, while `publish()`
|
|
136
|
-
emits outward from this Client without choosing a destination. Existence
|
|
137
|
-
readiness
|
|
138
|
-
`context.stop()`,
|
|
139
|
+
emits outward from this Client without choosing a destination. Existence and
|
|
140
|
+
readiness belong to `context.server`; the current Client stops through
|
|
141
|
+
`context.stop()`, and explicit Endpoint handles expose their own
|
|
142
|
+
`endpoint.lifecycle` subscriptions.
|
|
139
143
|
|
|
140
144
|
An Endpoint handle is also a selective source: `endpoint.subscribe()` follows
|
|
141
145
|
destinationless events emitted by that Endpoint. Its `traffic` property remains
|
package/dist/context.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Client, Server, type Process, type Program, type Window } from "./domain.js";
|
|
1
|
+
import type { Context as CoreContext, ContextCapture as CoreContextCapture, ContextEvents as CoreContextEvents, ContextMessage as CoreContextMessage } from "@phreshos/core";
|
|
2
|
+
import { Client, Server, type Endpoint, type Process, type Program, type Window } from "./domain.js";
|
|
3
3
|
/** The executing Process's canonical Server handle. */
|
|
4
4
|
export type ContextServer<Events extends object = {}> = Server<Events>;
|
|
5
|
-
/**
|
|
6
|
-
export
|
|
5
|
+
/** One value addressed to the current Client, with a client-visible sender. */
|
|
6
|
+
export type ContextMessage<Payload = unknown> = CoreContextMessage<Payload, Endpoint | null>;
|
|
7
|
+
/** Applies the client-visible sender envelope to known Context events. */
|
|
8
|
+
export type ContextEvents<Events extends object> = CoreContextEvents<Events, Endpoint | null>;
|
|
9
|
+
/** Every event observable through the current Client Context. */
|
|
10
|
+
export type ContextCapture<Events extends object = {}> = CoreContextCapture<Events, Endpoint | null>;
|
|
11
|
+
/** Client runtime context: inbound communication, owner hierarchy, and paired Server. */
|
|
12
|
+
export interface Context<Events extends object = {}> extends CoreContext<Events, Endpoint | null>, Pick<Client, "service"> {
|
|
7
13
|
/** The same Server handle exposed by the executing Process. */
|
|
8
14
|
readonly server: ContextServer;
|
|
9
15
|
/** Presentation capability of the executing Client. */
|
package/dist/context.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { channel } from "./channel.js";
|
|
2
1
|
import Deadline from "./deadline.js";
|
|
3
|
-
import { Client, Server, ServerTrafficHandle, TrafficHandle, bindEvents, endpointEvents, process, program, window as windowHandle } from "./domain.js";
|
|
2
|
+
import { Client, Server, ServerTrafficHandle, TrafficHandle, bindEvents, endpointLifecycle, endpointEvents, process, program, visibleEndpoint, window as windowHandle } from "./domain.js";
|
|
3
|
+
import Events from "./events.js";
|
|
4
4
|
import wire from "./wire.js";
|
|
5
|
-
import { endpointService } from "./service.js";
|
|
5
|
+
import { disableCurrentService, enableCurrentService, endpointService } from "./service.js";
|
|
6
6
|
import { currentProgramPermission } from "./permissions.js";
|
|
7
7
|
const ServerBase = Server;
|
|
8
8
|
const ClientBase = Client;
|
|
9
9
|
class ContextServerHandle extends ServerBase {
|
|
10
10
|
owner;
|
|
11
11
|
traffic = new ServerTrafficHandle(null, "server");
|
|
12
|
+
lifecycle = endpointLifecycle(currentAddress, "server");
|
|
12
13
|
constructor(owner) {
|
|
13
14
|
super();
|
|
14
15
|
this.owner = owner;
|
|
@@ -57,10 +58,8 @@ contextServer = new ContextServerHandle(owner);
|
|
|
57
58
|
class ContextClientHandle extends ClientBase {
|
|
58
59
|
owner;
|
|
59
60
|
traffic = new TrafficHandle(null, "client");
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return { identity: identity.process, reference: identity.reference };
|
|
63
|
-
});
|
|
61
|
+
lifecycle = endpointLifecycle(currentAddress, "client");
|
|
62
|
+
window = windowHandle(currentAddress);
|
|
64
63
|
constructor(owner) {
|
|
65
64
|
super();
|
|
66
65
|
this.owner = owner;
|
|
@@ -81,12 +80,15 @@ class ContextClientHandle extends ClientBase {
|
|
|
81
80
|
service() { return endpointService(null, "client"); }
|
|
82
81
|
}
|
|
83
82
|
contextClient = new ContextClientHandle(owner);
|
|
84
|
-
class ClientContext {
|
|
83
|
+
class ClientContext extends Events {
|
|
85
84
|
server = contextServer;
|
|
86
85
|
window = contextClient.window;
|
|
87
86
|
permission = currentProgramPermission;
|
|
88
87
|
constructor() {
|
|
89
|
-
|
|
88
|
+
super((event, listener, impossible) => wire.on("end-end", event, value => listener(contextMessage(value)), null, impossible), (listener, impossible) => wire.onAll("end-end", (event, value) => {
|
|
89
|
+
if (typeof event === "string")
|
|
90
|
+
listener(event, contextMessage(value));
|
|
91
|
+
}, null, impossible));
|
|
90
92
|
}
|
|
91
93
|
process() { return owner(); }
|
|
92
94
|
async parent() {
|
|
@@ -103,17 +105,17 @@ class ClientContext {
|
|
|
103
105
|
}
|
|
104
106
|
async stop() { await wire.request(["stop-current"]); }
|
|
105
107
|
service() { return endpointService(null, "client"); }
|
|
108
|
+
publish(event, payload = undefined) { wire.send("end-host", "emit", event, payload); }
|
|
109
|
+
async enableService(name) { await enableCurrentService(name); }
|
|
110
|
+
async disableService() { await disableCurrentService(); }
|
|
106
111
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
enableService: source.enableService.bind(source),
|
|
115
|
-
disableService: source.disableService.bind(source)
|
|
116
|
-
});
|
|
112
|
+
async function currentAddress() {
|
|
113
|
+
const identity = await wire.identity();
|
|
114
|
+
return { identity: identity.process, reference: identity.reference };
|
|
115
|
+
}
|
|
116
|
+
function contextMessage(value) {
|
|
117
|
+
const raw = value;
|
|
118
|
+
return { from: visibleEndpoint(raw.from), payload: raw.payload };
|
|
117
119
|
}
|
|
118
120
|
/** Inbound events, owner hierarchy, and paired Server for this Client runtime. */
|
|
119
121
|
export const context = new ClientContext();
|
package/dist/domain.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Client as CoreClient, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type
|
|
1
|
+
import { Client as CoreClient, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, 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 EndpointTraffic as CoreEndpointTraffic, type Exit, type EventOptions, type Launch, type LocalWindow, type Outcome, type Permission, type Position, type ProgramProcess as CoreProgramProcess, type ServerTraffic as CoreServerTraffic, type Size, 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 interface HandleAddress {
|
|
4
4
|
identity: string;
|
|
@@ -41,7 +41,7 @@ export interface EndpointReference {
|
|
|
41
41
|
}
|
|
42
42
|
export type WindowRecord = WindowState;
|
|
43
43
|
/** Program handle visible inside a structurally isolated Client. */
|
|
44
|
-
export type Program
|
|
44
|
+
export type Program = Omit<CoreProgram, "process"> & {
|
|
45
45
|
/** Effective permission decisions owned by this Program. */
|
|
46
46
|
readonly permission: Permission;
|
|
47
47
|
/** Operations and lifecycle observation for this Program's Processes. */
|
|
@@ -65,7 +65,7 @@ export type ProgramProcess = Omit<CoreProgramProcess, "list" | "first" | "last"
|
|
|
65
65
|
}>): Promise<Process>;
|
|
66
66
|
};
|
|
67
67
|
/** Process handle visible inside a structurally isolated Client. */
|
|
68
|
-
export type Process
|
|
68
|
+
export type Process = Omit<CoreProcess, "server" | "client" | "program" | "parent"> & {
|
|
69
69
|
/** Permanent handle to this Process's Server. */
|
|
70
70
|
readonly server: Server;
|
|
71
71
|
/** Permanent handle to this Process's Client. */
|
|
@@ -86,13 +86,13 @@ export type AskMessage<Payload = unknown> = CoreAskMessage<Payload, Server | nul
|
|
|
86
86
|
/** One question observable in client-visible Endpoint traffic. */
|
|
87
87
|
export type AskCapture<Payload = unknown> = CoreAskCapture<Payload, Server | null>;
|
|
88
88
|
/** Callback that observes questions sent by a client-visible Endpoint. */
|
|
89
|
-
export type
|
|
89
|
+
export type AskSubscriber<Payload = unknown> = CoreAskSubscriber<Payload, Server | null>;
|
|
90
90
|
/** Answer with an Endpoint destination hidden when it crosses the Client boundary. */
|
|
91
91
|
export type AnswerMessage<Result = unknown> = CoreAnswerMessage<Result, Endpoint | null>;
|
|
92
92
|
/** One answer observable in client-visible Server traffic. */
|
|
93
93
|
export type AnswerCapture<Result = unknown> = CoreAnswerCapture<Result, Endpoint | null>;
|
|
94
94
|
/** Callback that observes answers sent by a client-visible Server. */
|
|
95
|
-
export type
|
|
95
|
+
export type AnswerSubscriber<Result = unknown> = CoreAnswerSubscriber<Result, Endpoint | null>;
|
|
96
96
|
/** Directed communication originating from one client-visible Endpoint. */
|
|
97
97
|
export type EndpointTraffic<Events extends object = {}> = CoreEndpointTraffic<Events, Endpoint | null, Server | null>;
|
|
98
98
|
/** Directed communication originating from one client-visible Server. */
|
|
@@ -131,15 +131,35 @@ export declare class TrafficHandle extends Events {
|
|
|
131
131
|
protected readonly target: HandleAddress | null;
|
|
132
132
|
protected readonly kind: "server" | "client";
|
|
133
133
|
constructor(target: HandleAddress | null, kind: "server" | "client");
|
|
134
|
-
|
|
134
|
+
subscribeAsks(subscriber: (capture: AskCapture) => unknown): Cleanup;
|
|
135
|
+
asks(options?: EventOptions): AsyncIterableIterator<Readonly<{
|
|
136
|
+
event: string;
|
|
137
|
+
questionId: string;
|
|
138
|
+
message: Readonly<{
|
|
139
|
+
to: Server<{}> | null;
|
|
140
|
+
payload: unknown;
|
|
141
|
+
}>;
|
|
142
|
+
}>>;
|
|
143
|
+
private followAsks;
|
|
135
144
|
}
|
|
136
145
|
export declare class ServerTrafficHandle extends TrafficHandle {
|
|
137
|
-
|
|
146
|
+
subscribeAnswers(subscriber: (capture: AnswerCapture) => unknown): Cleanup;
|
|
147
|
+
answers(options?: EventOptions): AsyncIterableIterator<Readonly<{
|
|
148
|
+
event: string;
|
|
149
|
+
questionId: string;
|
|
150
|
+
message: Readonly<{
|
|
151
|
+
to: Endpoint<{}> | null;
|
|
152
|
+
outcome: Outcome<unknown>;
|
|
153
|
+
}>;
|
|
154
|
+
}>>;
|
|
155
|
+
private followAnswers;
|
|
138
156
|
}
|
|
139
157
|
type WindowTarget = () => Promise<HandleAddress>;
|
|
140
158
|
export declare function scoped(route: string, subject: string | null, convert: (event: string, values: unknown[]) => unknown): Events;
|
|
141
159
|
/** Destinationless events originating from one Endpoint handle. */
|
|
142
160
|
export declare function endpointEvents(target: HandleAddress | null, half: "server" | "client"): Events;
|
|
161
|
+
/** Start and stop transitions belonging directly to one permanent Endpoint. */
|
|
162
|
+
export declare function endpointLifecycle(target: WindowTarget, half: "server" | "client"): Events;
|
|
143
163
|
export declare function exit(code: unknown, signal: unknown): Exit;
|
|
144
164
|
export declare function trafficMessage(value: unknown): TrafficMessage;
|
|
145
165
|
export declare function bindEvents(target: object, events: Events): void;
|
package/dist/domain.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Client as CoreClient, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer } from "@phreshos/core";
|
|
2
|
-
import Events from "./events.js";
|
|
2
|
+
import Events, { stream } from "./events.js";
|
|
3
3
|
import Deadline from "./deadline.js";
|
|
4
4
|
import HandleRegistry from "./handle-registry.js";
|
|
5
5
|
import { area, sql, store } from "./storage.js";
|
|
@@ -165,38 +165,52 @@ export class TrafficHandle extends Events {
|
|
|
165
165
|
target;
|
|
166
166
|
kind;
|
|
167
167
|
constructor(target, kind) {
|
|
168
|
-
super((event, listener, impossible) => wire.observe(target, kind, "publish", event, value => listener(trafficMessage(value)), impossible),
|
|
168
|
+
super((event, listener, impossible) => wire.observe(target, kind, "publish", event, value => listener(trafficMessage(value)), impossible), (listener, impossible) => wire.observe(target, kind, "publish", null, (event, value) => {
|
|
169
169
|
if (typeof event === "string")
|
|
170
|
-
|
|
171
|
-
}));
|
|
170
|
+
listener(event, trafficMessage(value));
|
|
171
|
+
}, impossible));
|
|
172
172
|
this.target = target;
|
|
173
173
|
this.kind = kind;
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
subscribeAsks(subscriber) {
|
|
176
|
+
return this.followAsks(subscriber);
|
|
177
|
+
}
|
|
178
|
+
asks(options) {
|
|
179
|
+
return stream((subscriber, impossible) => this.followAsks(subscriber, impossible), options);
|
|
180
|
+
}
|
|
181
|
+
followAsks(subscriber, impossible) {
|
|
176
182
|
return wire.observe(this.target, this.kind, "ask", null, (event, questionId, value) => {
|
|
177
183
|
if (typeof event !== "string" || typeof questionId !== "string")
|
|
178
184
|
return;
|
|
179
|
-
|
|
180
|
-
});
|
|
185
|
+
subscriber({ event, questionId, message: trafficMessage(value) });
|
|
186
|
+
}, impossible);
|
|
181
187
|
}
|
|
182
188
|
}
|
|
183
189
|
export class ServerTrafficHandle extends TrafficHandle {
|
|
184
|
-
|
|
190
|
+
subscribeAnswers(subscriber) {
|
|
191
|
+
return this.followAnswers(subscriber);
|
|
192
|
+
}
|
|
193
|
+
answers(options) {
|
|
194
|
+
return stream((subscriber, impossible) => this.followAnswers(subscriber, impossible), options);
|
|
195
|
+
}
|
|
196
|
+
followAnswers(subscriber, impossible) {
|
|
185
197
|
return wire.observe(this.target, "server", "answer", null, (event, questionId, value) => {
|
|
186
198
|
if (typeof event !== "string" || typeof questionId !== "string")
|
|
187
199
|
return;
|
|
188
200
|
const raw = value;
|
|
189
|
-
|
|
190
|
-
});
|
|
201
|
+
subscriber({ event, questionId, message: { to: visibleEndpoint(raw.to), outcome: raw.outcome } });
|
|
202
|
+
}, impossible);
|
|
191
203
|
}
|
|
192
204
|
}
|
|
193
205
|
class ServerHandle extends ServerBase {
|
|
194
206
|
owner;
|
|
195
207
|
traffic;
|
|
208
|
+
lifecycle;
|
|
196
209
|
constructor(owner) {
|
|
197
210
|
super();
|
|
198
211
|
this.owner = owner;
|
|
199
212
|
this.traffic = new ServerTrafficHandle(owner.address, "server");
|
|
213
|
+
this.lifecycle = endpointLifecycle(() => Promise.resolve(owner.address), "server");
|
|
200
214
|
bindEvents(this, endpointEvents(owner.address, "server"));
|
|
201
215
|
}
|
|
202
216
|
async process() { return this.owner; }
|
|
@@ -234,11 +248,13 @@ class ServerHandle extends ServerBase {
|
|
|
234
248
|
class ClientHandle extends ClientBase {
|
|
235
249
|
owner;
|
|
236
250
|
traffic;
|
|
251
|
+
lifecycle;
|
|
237
252
|
window;
|
|
238
253
|
constructor(owner) {
|
|
239
254
|
super();
|
|
240
255
|
this.owner = owner;
|
|
241
256
|
this.traffic = new TrafficHandle(owner.address, "client");
|
|
257
|
+
this.lifecycle = endpointLifecycle(() => Promise.resolve(owner.address), "client");
|
|
242
258
|
this.window = window(async () => owner.address);
|
|
243
259
|
bindEvents(this, endpointEvents(owner.address, "client"));
|
|
244
260
|
}
|
|
@@ -328,13 +344,13 @@ function deferredScoped(route, target, convert) {
|
|
|
328
344
|
listener(convert(event, message));
|
|
329
345
|
}, subject, impossible), impossible);
|
|
330
346
|
},
|
|
331
|
-
|
|
347
|
+
(listener, impossible) => deferred(target, subject => wire.onAll(route, (event, ...values) => {
|
|
332
348
|
if (typeof event !== "string" || !windowEvent(event))
|
|
333
349
|
return;
|
|
334
350
|
const message = unscoped(subject, values);
|
|
335
351
|
if (message)
|
|
336
|
-
|
|
337
|
-
}, subject))
|
|
352
|
+
listener(event, convert(event, message));
|
|
353
|
+
}, subject, impossible), impossible)
|
|
338
354
|
];
|
|
339
355
|
}
|
|
340
356
|
function windowEvent(event) {
|
|
@@ -363,20 +379,41 @@ export function scoped(route, subject, convert) {
|
|
|
363
379
|
const message = unscoped(subject, values);
|
|
364
380
|
if (message)
|
|
365
381
|
listener(convert(event, message));
|
|
366
|
-
}, subject, impossible),
|
|
382
|
+
}, subject, impossible), (listener, impossible) => wire.onAll(route, (event, ...values) => {
|
|
367
383
|
if (typeof event !== "string")
|
|
368
384
|
return;
|
|
369
385
|
const message = unscoped(subject, values);
|
|
370
386
|
if (message)
|
|
371
|
-
|
|
372
|
-
}, subject));
|
|
387
|
+
listener(event, convert(event, message));
|
|
388
|
+
}, subject, impossible));
|
|
373
389
|
}
|
|
374
390
|
/** Destinationless events originating from one Endpoint handle. */
|
|
375
391
|
export function endpointEvents(target, half) {
|
|
376
|
-
return new Events((event, listener, impossible) => wire.follow(target, half, event, listener, impossible),
|
|
392
|
+
return new Events((event, listener, impossible) => wire.follow(target, half, event, listener, impossible), (listener, impossible) => wire.follow(target, half, null, (event, payload) => {
|
|
377
393
|
if (typeof event === "string")
|
|
378
|
-
|
|
379
|
-
}));
|
|
394
|
+
listener(event, payload);
|
|
395
|
+
}, impossible));
|
|
396
|
+
}
|
|
397
|
+
/** Start and stop transitions belonging directly to one permanent Endpoint. */
|
|
398
|
+
export function endpointLifecycle(target, half) {
|
|
399
|
+
return new Events((event, listener, impossible) => deferred(target, subject => wire.on("process-host", endpointLifecycleEvent(event), (...values) => {
|
|
400
|
+
const message = unscoped(subject, values);
|
|
401
|
+
if (message?.[1] === half)
|
|
402
|
+
listener(undefined);
|
|
403
|
+
}, subject, impossible), impossible), (listener, impossible) => deferred(target, subject => wire.onAll("process-host", (event, ...values) => {
|
|
404
|
+
if (event !== "endpointStart" && event !== "endpointStop")
|
|
405
|
+
return;
|
|
406
|
+
const message = unscoped(subject, values);
|
|
407
|
+
if (message?.[1] === half)
|
|
408
|
+
listener(event === "endpointStart" ? "start" : "stop", undefined);
|
|
409
|
+
}, subject, impossible), impossible));
|
|
410
|
+
}
|
|
411
|
+
function endpointLifecycleEvent(event) {
|
|
412
|
+
if (event === "start")
|
|
413
|
+
return "endpointStart";
|
|
414
|
+
if (event === "stop")
|
|
415
|
+
return "endpointStop";
|
|
416
|
+
return event;
|
|
380
417
|
}
|
|
381
418
|
function unscoped(subject, values) {
|
|
382
419
|
if (subject === null)
|
|
@@ -384,8 +421,6 @@ function unscoped(subject, values) {
|
|
|
384
421
|
return values[0] === subject ? values.slice(1) : null;
|
|
385
422
|
}
|
|
386
423
|
function programProcessEvent(event, values) {
|
|
387
|
-
if (event === "endpointStart" || event === "endpointStop")
|
|
388
|
-
return lifecycleEndpoint(values[0], values[1]);
|
|
389
424
|
if (event === "create")
|
|
390
425
|
return process(values[0]);
|
|
391
426
|
if (event === "exit")
|
|
@@ -394,24 +429,14 @@ function programProcessEvent(event, values) {
|
|
|
394
429
|
}
|
|
395
430
|
function programEvent(event, values) {
|
|
396
431
|
if (event === "uninstall")
|
|
397
|
-
return
|
|
432
|
+
return values[0] === true;
|
|
398
433
|
return undefined;
|
|
399
434
|
}
|
|
400
435
|
function processEvent(event, values) {
|
|
401
|
-
if (event === "endpointStart" || event === "endpointStop")
|
|
402
|
-
return lifecycleEndpoint(values[0], values[1]);
|
|
403
436
|
if (event === "exit")
|
|
404
437
|
return exit(values[0], values[1]);
|
|
405
438
|
return undefined;
|
|
406
439
|
}
|
|
407
|
-
function lifecycleEndpoint(record, kind) {
|
|
408
|
-
const owner = process(record);
|
|
409
|
-
if (kind === "server")
|
|
410
|
-
return owner.server;
|
|
411
|
-
if (kind === "client")
|
|
412
|
-
return owner.client;
|
|
413
|
-
throw new Error("The system returned an invalid Endpoint lifecycle event");
|
|
414
|
-
}
|
|
415
440
|
export function exit(code, signal) {
|
|
416
441
|
const namedSignal = stringOrNull(signal);
|
|
417
442
|
return { status: namedSignal === null ? "exited" : "signaled", code: numberOrNull(code), signal: namedSignal };
|
|
@@ -426,8 +451,7 @@ export function bindEvents(target, events) {
|
|
|
426
451
|
Object.assign(target, {
|
|
427
452
|
subscribe: events.subscribe.bind(events),
|
|
428
453
|
waitFor: events.waitFor.bind(events),
|
|
429
|
-
events: events.events.bind(events)
|
|
430
|
-
observe: events.observe.bind(events)
|
|
454
|
+
events: events.events.bind(events)
|
|
431
455
|
});
|
|
432
456
|
}
|
|
433
457
|
export function program(record) {
|
package/dist/events.d.ts
CHANGED
|
@@ -2,15 +2,19 @@ import type { Capture, Cleanup, EventOptions } from "@phreshos/core";
|
|
|
2
2
|
export declare const defaultTimeout = 10000;
|
|
3
3
|
type Failure = (error: Error) => void;
|
|
4
4
|
type Listener = (message: unknown) => unknown;
|
|
5
|
-
type
|
|
5
|
+
type EveryListener = (event: string, message: unknown) => unknown;
|
|
6
|
+
type Register<Message> = (listener: (message: Message) => unknown, impossible?: Failure) => Cleanup;
|
|
6
7
|
/** SDK-owned waits, queues and callbacks over boundary forwarding state. */
|
|
7
8
|
export default class Events {
|
|
8
9
|
private readonly listen;
|
|
9
10
|
private readonly listenAll;
|
|
10
|
-
constructor(listen: (event: string, listener: Listener, impossible?: Failure) => Cleanup, listenAll: (
|
|
11
|
+
constructor(listen: (event: string, listener: Listener, impossible?: Failure) => Cleanup, listenAll: (listener: EveryListener, impossible?: Failure) => Cleanup);
|
|
11
12
|
subscribe(event: string, subscriber: Listener): Cleanup;
|
|
13
|
+
subscribe(subscriber: (capture: Capture<string, unknown>) => unknown): Cleanup;
|
|
12
14
|
waitFor(event: string, timeout?: number): Promise<unknown>;
|
|
13
15
|
events(event: string, options?: EventOptions): AsyncIterableIterator<unknown>;
|
|
14
|
-
|
|
16
|
+
events(options?: EventOptions): AsyncIterableIterator<Capture<string, unknown>>;
|
|
15
17
|
}
|
|
18
|
+
/** Converts one persistent registration into a bounded asynchronous iterator. */
|
|
19
|
+
export declare function stream<Message>(register: Register<Message>, options?: EventOptions): AsyncIterableIterator<Message>;
|
|
16
20
|
export {};
|
package/dist/events.js
CHANGED
|
@@ -7,8 +7,10 @@ export default class Events {
|
|
|
7
7
|
this.listen = listen;
|
|
8
8
|
this.listenAll = listenAll;
|
|
9
9
|
}
|
|
10
|
-
subscribe(
|
|
11
|
-
|
|
10
|
+
subscribe(eventOrSubscriber, subscriber) {
|
|
11
|
+
if (typeof eventOrSubscriber === "string")
|
|
12
|
+
return this.listen(eventOrSubscriber, subscriber);
|
|
13
|
+
return this.listenAll((event, message) => eventOrSubscriber({ event, message }));
|
|
12
14
|
}
|
|
13
15
|
waitFor(event, timeout = defaultTimeout) {
|
|
14
16
|
return new Promise((resolve, reject) => {
|
|
@@ -26,58 +28,63 @@ export default class Events {
|
|
|
26
28
|
stop = this.listen(event, message => finish(() => resolve(message)), error => finish(() => reject(error)));
|
|
27
29
|
});
|
|
28
30
|
}
|
|
29
|
-
events(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
throw new Error("An event queue capacity must be a non-negative integer or Infinity");
|
|
31
|
+
events(eventOrOptions = {}, namedOptions = {}) {
|
|
32
|
+
if (typeof eventOrOptions === "string") {
|
|
33
|
+
return stream((listener, impossible) => this.listen(eventOrOptions, listener, impossible), namedOptions);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
return (async function* () {
|
|
36
|
-
const queue = [];
|
|
37
|
-
let ended = false;
|
|
38
|
-
let failure = null;
|
|
39
|
-
let wake = null;
|
|
40
|
-
const stop = listen(event, message => {
|
|
41
|
-
if (ended || failure)
|
|
42
|
-
return;
|
|
43
|
-
if (queue.length >= capacity)
|
|
44
|
-
failure = new Error(`Event queue exceeded its capacity of ${capacity}`);
|
|
45
|
-
else
|
|
46
|
-
queue.push(message);
|
|
47
|
-
wake?.();
|
|
48
|
-
wake = null;
|
|
49
|
-
}, error => {
|
|
50
|
-
if (ended || failure)
|
|
51
|
-
return;
|
|
52
|
-
failure = error;
|
|
53
|
-
wake?.();
|
|
54
|
-
wake = null;
|
|
55
|
-
});
|
|
56
|
-
const abort = () => {
|
|
57
|
-
ended = true;
|
|
58
|
-
wake?.();
|
|
59
|
-
wake = null;
|
|
60
|
-
};
|
|
61
|
-
options.signal?.addEventListener("abort", abort, { once: true });
|
|
62
|
-
try {
|
|
63
|
-
while (!ended) {
|
|
64
|
-
if (queue.length) {
|
|
65
|
-
yield queue.shift();
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (failure)
|
|
69
|
-
throw failure;
|
|
70
|
-
await new Promise(resolve => { wake = resolve; });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
finally {
|
|
74
|
-
ended = true;
|
|
75
|
-
stop();
|
|
76
|
-
options.signal?.removeEventListener("abort", abort);
|
|
77
|
-
}
|
|
78
|
-
})();
|
|
35
|
+
return stream((listener, impossible) => this.listenAll((event, message) => listener({ event, message }), impossible), eventOrOptions);
|
|
79
36
|
}
|
|
80
|
-
|
|
81
|
-
|
|
37
|
+
}
|
|
38
|
+
/** Converts one persistent registration into a bounded asynchronous iterator. */
|
|
39
|
+
export function stream(register, options = {}) {
|
|
40
|
+
const capacity = options.capacity ?? 64;
|
|
41
|
+
if (capacity !== Infinity && (!Number.isInteger(capacity) || capacity < 0)) {
|
|
42
|
+
throw new Error("An event queue capacity must be a non-negative integer or Infinity");
|
|
82
43
|
}
|
|
44
|
+
return (async function* () {
|
|
45
|
+
const queue = [];
|
|
46
|
+
let ended = false;
|
|
47
|
+
let failure = null;
|
|
48
|
+
let wake = null;
|
|
49
|
+
const stop = register(message => {
|
|
50
|
+
if (ended || failure)
|
|
51
|
+
return;
|
|
52
|
+
if (queue.length >= capacity)
|
|
53
|
+
failure = new Error(`Event queue exceeded its capacity of ${capacity}`);
|
|
54
|
+
else
|
|
55
|
+
queue.push(message);
|
|
56
|
+
wake?.();
|
|
57
|
+
wake = null;
|
|
58
|
+
}, error => {
|
|
59
|
+
if (ended || failure)
|
|
60
|
+
return;
|
|
61
|
+
failure = error;
|
|
62
|
+
wake?.();
|
|
63
|
+
wake = null;
|
|
64
|
+
});
|
|
65
|
+
const abort = () => {
|
|
66
|
+
ended = true;
|
|
67
|
+
wake?.();
|
|
68
|
+
wake = null;
|
|
69
|
+
};
|
|
70
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
71
|
+
if (options.signal?.aborted)
|
|
72
|
+
abort();
|
|
73
|
+
try {
|
|
74
|
+
while (!ended) {
|
|
75
|
+
if (queue.length) {
|
|
76
|
+
yield queue.shift();
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (failure)
|
|
80
|
+
throw failure;
|
|
81
|
+
await new Promise(resolve => { wake = resolve; });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
ended = true;
|
|
86
|
+
stop();
|
|
87
|
+
options.signal?.removeEventListener("abort", abort);
|
|
88
|
+
}
|
|
89
|
+
})();
|
|
83
90
|
}
|
package/dist/main.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { system, type System } from "./system.js";
|
|
2
2
|
export { type SystemPointer, type PointerEvents, type PointerPosition } from "./pointer.js";
|
|
3
3
|
export { type DesktopEvents, type DesktopSize, type SystemDesktop } from "./desktop.js";
|
|
4
|
-
export { context, type Context, type ContextServer } from "./context.js";
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export type { Askable, Capture, Captures, ClientDeclaration, Cleanup, DirectoryStat, EndpointDeclaration, EntryStat, EventMessage, EventName, EventObserver, EventOptions, EventSubscriber, Exit, FileStat, Launch, LaunchClient, Layer, LogKind, LogRecord, LogSource, Message, OtherStat, Outcome, PermissionDecision, Permission, Position, Storage, ProgramEvents, ProgramProcessEvents, ProgramProcessExit, ProgramSql, ProgramStore, ProcessEvents, Publishable, SystemUploads, Upload, Size, Subscribable, SubscribableEvents, SubscribableFallback, TimedAskable, TimedPermission, Timeoutable, Appearance, AppearanceEvents, AppearanceSource, AppearanceSurface, AnimationsPreference, DesktopPreferences, DesktopPreferencesEvents, DesktopPreferencesUpdate, SystemDesktopPreferences, ThemedValue, Theme, ThemePreference, Value, WindowEvents, WindowGeometry, WindowLayer, WindowState, Easing, LocalWindow, LocalWindowSurface, VisibilityTransition, Transaction } from "@phreshos/core";
|
|
4
|
+
export { context, type Context, type ContextCapture, type ContextEvents, type ContextMessage, type ContextServer } from "./context.js";
|
|
5
|
+
export { ClientService, ServerService, Service, type ServiceKey, type ServiceLifecycle, type ServiceLifecycleEvents } from "@phreshos/core";
|
|
6
|
+
export { Client, Endpoint, Process, Program, Server, type Window, type ProgramProcess, type AnswerCapture, type AnswerMessage, type AnswerSubscriber, type AskCapture, type AskMessage, type AskSubscriber, type ClientTraffic, type EndpointTraffic, type ServerTraffic, type TrafficCapture, type TrafficEvents, type TrafficMessage } from "./domain.js";
|
|
7
|
+
export type { Askable, Capture, Captures, CaptureSubscriber, ClientDeclaration, Cleanup, DirectoryStat, EndpointDeclaration, EndpointLifecycle, EndpointLifecycleEvents, EntryStat, EventMessage, EventName, EventOptions, EventSubscriber, Exit, FileStat, Launch, LaunchClient, Layer, LogKind, LogRecord, LogSource, Message, OtherStat, Outcome, PermissionDecision, Permission, Position, Storage, ProgramEvents, ProgramProcessEvents, ProgramProcessExit, ProgramSql, ProgramStore, ProcessEvents, Publishable, SystemUploads, Upload, Size, Subscribable, SubscribableEvents, SubscribableFallback, TimedAskable, TimedPermission, Timeoutable, Appearance, AppearanceEvents, AppearanceSource, AppearanceSurface, AnimationsPreference, DesktopPreferences, DesktopPreferencesEvents, DesktopPreferencesUpdate, SystemDesktopPreferences, ThemedValue, Theme, ThemePreference, Value, WindowEvents, WindowGeometry, WindowLayer, WindowState, Easing, LocalWindow, LocalWindowSurface, VisibilityTransition, Transaction } from "@phreshos/core";
|
package/dist/main.js
CHANGED
|
@@ -2,6 +2,5 @@ export { system } from "./system.js";
|
|
|
2
2
|
export {} from "./pointer.js";
|
|
3
3
|
export {} from "./desktop.js";
|
|
4
4
|
export { context } from "./context.js";
|
|
5
|
-
export {} from "./channel.js";
|
|
6
5
|
export { ClientService, ServerService, Service } from "@phreshos/core";
|
|
7
6
|
export { Client, Endpoint, Process, Program, Server } from "./domain.js";
|
package/dist/service.js
CHANGED
|
@@ -6,11 +6,16 @@ import wire from "./wire.js";
|
|
|
6
6
|
const handles = new HandleRegistry();
|
|
7
7
|
const ServerServiceBase = CoreServerService;
|
|
8
8
|
const ClientServiceBase = CoreClientService;
|
|
9
|
-
class
|
|
9
|
+
class ServerHandler extends ServerServiceBase {
|
|
10
10
|
key;
|
|
11
|
+
name;
|
|
12
|
+
lifecycle;
|
|
11
13
|
constructor(key) {
|
|
12
|
-
super(
|
|
14
|
+
super();
|
|
13
15
|
this.key = key;
|
|
16
|
+
this.name = key.name;
|
|
17
|
+
this.lifecycle = new Events(...serviceEvents(key, "lifecycle"));
|
|
18
|
+
bindEvents(this, new Events(...serviceEvents(key, "events")));
|
|
14
19
|
}
|
|
15
20
|
publish(event, payload = undefined) {
|
|
16
21
|
wire.send("end-host", "service-send", this.key, event, payload);
|
|
@@ -25,6 +30,13 @@ class ServerChannelHandle extends Events {
|
|
|
25
30
|
}
|
|
26
31
|
};
|
|
27
32
|
}
|
|
33
|
+
async enabled() {
|
|
34
|
+
const answer = await wire.request(["service-enabled", this.key]);
|
|
35
|
+
return answer[0];
|
|
36
|
+
}
|
|
37
|
+
async waitReady(timeout) {
|
|
38
|
+
await wire.request(["service-wait-ready", this.key, timeout], timeout);
|
|
39
|
+
}
|
|
28
40
|
async askWithin(deadline, event, payload) {
|
|
29
41
|
const identity = await wire.identity();
|
|
30
42
|
const address = `client:${identity.process}:${crypto.randomUUID()}`;
|
|
@@ -39,40 +51,16 @@ class ServerChannelHandle extends Events {
|
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
53
|
}
|
|
42
|
-
class ClientChannelHandle extends Events {
|
|
43
|
-
constructor(key) {
|
|
44
|
-
super(...serviceEvents(key, "channel"));
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
class ServerHandler extends ServerServiceBase {
|
|
48
|
-
key;
|
|
49
|
-
name;
|
|
50
|
-
channel;
|
|
51
|
-
constructor(key) {
|
|
52
|
-
super();
|
|
53
|
-
this.key = key;
|
|
54
|
-
this.name = key.name;
|
|
55
|
-
this.channel = new ServerChannelHandle(key);
|
|
56
|
-
bindEvents(this, new Events(...serviceEvents(key, "lifecycle")));
|
|
57
|
-
}
|
|
58
|
-
async enabled() {
|
|
59
|
-
const answer = await wire.request(["service-enabled", this.key]);
|
|
60
|
-
return answer[0];
|
|
61
|
-
}
|
|
62
|
-
async waitReady(timeout) {
|
|
63
|
-
await wire.request(["service-wait-ready", this.key, timeout], timeout);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
54
|
class ClientHandler extends ClientServiceBase {
|
|
67
55
|
key;
|
|
68
56
|
name;
|
|
69
|
-
|
|
57
|
+
lifecycle;
|
|
70
58
|
constructor(key) {
|
|
71
59
|
super();
|
|
72
60
|
this.key = key;
|
|
73
61
|
this.name = key.name;
|
|
74
|
-
this.
|
|
75
|
-
bindEvents(this, new Events(...serviceEvents(key, "
|
|
62
|
+
this.lifecycle = new Events(...serviceEvents(key, "lifecycle"));
|
|
63
|
+
bindEvents(this, new Events(...serviceEvents(key, "events")));
|
|
76
64
|
}
|
|
77
65
|
async enabled() {
|
|
78
66
|
const answer = await wire.request(["service-enabled", this.key]);
|
|
@@ -106,9 +94,9 @@ export async function endpointService(target, endpoint) {
|
|
|
106
94
|
function serviceEvents(key, scope) {
|
|
107
95
|
return [
|
|
108
96
|
(event, listener) => wire.followService(key, scope, event, listener),
|
|
109
|
-
(
|
|
97
|
+
(listener) => wire.followService(key, scope, null, (event, payload) => {
|
|
110
98
|
if (typeof event === "string")
|
|
111
|
-
|
|
99
|
+
listener(event, payload);
|
|
112
100
|
})
|
|
113
101
|
];
|
|
114
102
|
}
|
|
@@ -116,7 +104,6 @@ function bindEvents(target, events) {
|
|
|
116
104
|
Object.assign(target, {
|
|
117
105
|
subscribe: events.subscribe.bind(events),
|
|
118
106
|
waitFor: events.waitFor.bind(events),
|
|
119
|
-
events: events.events.bind(events)
|
|
120
|
-
observe: events.observe.bind(events)
|
|
107
|
+
events: events.events.bind(events)
|
|
121
108
|
});
|
|
122
109
|
}
|
package/dist/wire.d.ts
CHANGED
|
@@ -32,12 +32,12 @@ declare class Wire {
|
|
|
32
32
|
expectWithin(question: string, deadline: Deadline): Promise<unknown>;
|
|
33
33
|
forget(question: string): void;
|
|
34
34
|
on(route: string, event: string, handler: Handler, subject?: string | null, impossible?: Failure): Cleanup;
|
|
35
|
-
onAll(route: string, handler: Handler, subject?: string | null): Cleanup;
|
|
35
|
+
onAll(route: string, handler: Handler, subject?: string | null, impossible?: Failure): Cleanup;
|
|
36
36
|
observe(target: HandleAddress | null, half: "server" | "client", kind: TrafficKind, event: string | null, handler: Handler, impossible?: Failure): Cleanup;
|
|
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(key: ServiceKey, scope: "lifecycle" | "
|
|
40
|
+
followService(key: ServiceKey, scope: "lifecycle" | "events", event: string | null, handler: Handler): Cleanup;
|
|
41
41
|
samplePointer(movementX: number, movementY: number): void;
|
|
42
42
|
private register;
|
|
43
43
|
private unregister;
|
package/dist/wire.js
CHANGED
|
@@ -221,11 +221,11 @@ class Wire {
|
|
|
221
221
|
this.unregister(subscription);
|
|
222
222
|
});
|
|
223
223
|
}
|
|
224
|
-
onAll(route, handler, subject = null) {
|
|
224
|
+
onAll(route, handler, subject = null, impossible) {
|
|
225
225
|
const handlers = this.every.get(route) ?? new Set();
|
|
226
226
|
handlers.add(handler);
|
|
227
227
|
this.every.set(route, handlers);
|
|
228
|
-
const subscription = this.register("publish", route, null, subject);
|
|
228
|
+
const subscription = this.register("publish", route, null, subject, impossible);
|
|
229
229
|
return once(() => {
|
|
230
230
|
handlers.delete(handler);
|
|
231
231
|
if (!handlers.size)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "The SDK used by a Program's client endpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"prepack": "node --run build"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@phreshos/core": "^0.1.
|
|
50
|
+
"@phreshos/core": "^0.1.27"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@msgpack/msgpack": "^3.1.3"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@phreshos/core": "^0.1.
|
|
56
|
+
"@phreshos/core": "^0.1.27",
|
|
57
57
|
"typescript": "^6.0.3"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/dist/channel.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Channel as CoreChannel, ChannelCapture as CoreChannelCapture, ChannelEvents as CoreChannelEvents, ChannelMessage as CoreChannelMessage } from "@phreshos/core";
|
|
2
|
-
import { type Endpoint } from "./domain.js";
|
|
3
|
-
/** One value addressed to the current Client, with a client-visible sender. */
|
|
4
|
-
export type ChannelMessage<Payload = unknown> = CoreChannelMessage<Payload, Endpoint | null>;
|
|
5
|
-
/** Applies the client-visible sender envelope to known Channel events. */
|
|
6
|
-
export type ChannelEvents<Events extends object> = CoreChannelEvents<Events, Endpoint | null>;
|
|
7
|
-
/** Every event observable through the current Client's Channel. */
|
|
8
|
-
export type ChannelCapture<Events extends object = {}> = CoreChannelCapture<Events, Endpoint | null>;
|
|
9
|
-
/** Events explicitly accepted by the current Client. */
|
|
10
|
-
export interface Channel<Events extends object = {}> extends CoreChannel<Events, Endpoint | null> {
|
|
11
|
-
}
|
|
12
|
-
export declare const channel: Channel;
|
package/dist/channel.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { visibleEndpoint } from "./domain.js";
|
|
2
|
-
import Events from "./events.js";
|
|
3
|
-
import wire from "./wire.js";
|
|
4
|
-
import { disableCurrentService, enableCurrentService } from "./service.js";
|
|
5
|
-
class ClientChannel extends Events {
|
|
6
|
-
constructor() {
|
|
7
|
-
super((event, listener, impossible) => wire.on("end-end", event, value => listener(message(value)), null, impossible), observer => wire.onAll("end-end", (event, value) => {
|
|
8
|
-
if (typeof event === "string")
|
|
9
|
-
observer(event, message(value));
|
|
10
|
-
}));
|
|
11
|
-
}
|
|
12
|
-
publish(event, payload = undefined) {
|
|
13
|
-
wire.send("end-host", "emit", event, payload);
|
|
14
|
-
}
|
|
15
|
-
async enableService(name) { await enableCurrentService(name); }
|
|
16
|
-
async disableService() { await disableCurrentService(); }
|
|
17
|
-
}
|
|
18
|
-
function message(value) {
|
|
19
|
-
const raw = value;
|
|
20
|
-
return { from: visibleEndpoint(raw.from), payload: raw.payload };
|
|
21
|
-
}
|
|
22
|
-
export const channel = new ClientChannel();
|