@phreshos/node 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { gatewayAddress } from "./address.js";
2
- export { Client, Endpoint, Process, Program, Server, System, type ProgramProcessRunEvent, type ProgramProcessRunOptions } from "./system.js";
2
+ export { Client, ClientService, Endpoint, Process, Program, Server, ServerService, System, type ProgramProcessRunEvent, type ProgramProcessRunOptions } from "./system.js";
3
+ export { Service, type ClientServiceChannel, type ServerServiceChannel, type ServiceChannel, type ServiceKey, type ServiceLifecycleEvents } from "@phreshos/core";
3
4
  export { resolveHome } from "./home.js";
4
5
  export { Project, type Manifest, type PackedProject, type ProjectMode, type ProjectOptions, type ProjectRunOptions } from "./project.js";
package/dist/main.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { gatewayAddress } from "./address.js";
2
- export { Client, Endpoint, Process, Program, Server, System } from "./system.js";
2
+ export { Client, ClientService, Endpoint, Process, Program, Server, ServerService, System } from "./system.js";
3
+ export { Service } from "@phreshos/core";
3
4
  export { resolveHome } from "./home.js";
4
5
  export { Project } from "./project.js";
package/dist/system.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { Client as CoreClient, ClientServiceHandler as CoreClientServiceHandler, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, ServerServiceHandler as CoreServerServiceHandler, type ClientDeclaration, type ClientServiceChannel, type EndpointDeclaration, type Launch, type LaunchClient, type Position, type ProgramDefinition, type ProgramCommandChunk, type ServerServiceChannel, type ServiceKey, type Size, type System as CoreSystem, type SystemClientEntity, type SystemEndpointEntity, type SystemProcessEntity, type SystemProcess, type SystemProgram, type SystemProgramEntity, type SystemProgramProcessEvents, type SystemServerEntity, type SystemUploads, type WritableAppearance, type Window, type WindowEvents, type WindowGeometry } from "@phreshos/core";
2
- import Events from "./events.js";
3
- import { type TransportEvent } from "./transport.js";
1
+ import { Client as CoreClient, ClientService as CoreClientService, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, ServerService as CoreServerService, type ProgramDefinition, type ProgramCommandChunk, type ServiceKey, type System as CoreSystem, type SystemClientEntity, type SystemEndpointEntity, type SystemProcessEntity, type SystemProcess, type SystemProgram, type SystemProgramEntity, type SystemServerEntity, type SystemUploads, type WritableAppearance } from "@phreshos/core";
4
2
  export type ProgramProcessRunOptions = Readonly<{
5
3
  signal?: AbortSignal;
6
4
  }>;
@@ -14,29 +12,13 @@ export type ProgramProcessRunEvent = Readonly<{
14
12
  process: SystemProcessEntity;
15
13
  exit: import("@phreshos/core").Exit;
16
14
  }>;
17
- interface SystemTransport {
18
- control(request: object, signal?: AbortSignal): Promise<unknown>;
19
- api(request: object, signal?: AbortSignal): Promise<unknown>;
20
- lifecycle(request: object, signal?: AbortSignal): AsyncGenerator<TransportEvent, void, void>;
21
- }
22
- declare const ProgramBase: new () => object;
23
- declare const ProcessBase: new () => object;
24
- declare const ServerBase: new () => object;
25
- declare const ClientBase: new () => object;
26
15
  /** One connected owner-local implementation of the shared System contract. */
27
16
  export declare class System implements CoreSystem {
28
- private readonly connection;
29
- readonly home: string;
30
- readonly address: string;
31
17
  readonly storage: import("@phreshos/core").Storage;
32
18
  readonly appearance: WritableAppearance;
33
19
  readonly program: SystemProgram;
34
20
  readonly process: SystemProcess;
35
21
  readonly uploads: SystemUploads;
36
- readonly transport: SystemTransport;
37
- private closed;
38
- private readonly lifetime;
39
- private readonly handles;
40
22
  private constructor();
41
23
  /** Connect to the System selected by argument, environment, or owner default. */
42
24
  static connect(home?: string): Promise<System>;
@@ -50,197 +32,14 @@ export declare class System implements CoreSystem {
50
32
  service<EventsMap extends object = {}>(key: ServiceKey & {
51
33
  endpoint: "client";
52
34
  }): ClientService<EventsMap>;
53
- programHandle(snapshot: ProgramSnapshot): ProgramHandle;
54
- processHandle(snapshot: ProcessSnapshot): ProcessHandle;
55
- private signal;
56
- private requireConnected;
57
- }
58
- interface ProgramHandle extends SystemProgramEntity {
59
- }
60
- declare class ProgramHandle extends ProgramBase {
61
- private readonly system;
62
- private readonly reference;
63
- readonly identity: string;
64
- readonly process: ProgramProcesses;
65
- readonly startup: ProgramStartup;
66
- private snapshot;
67
- constructor(system: System, snapshot: ProgramSnapshot);
68
- get name(): string;
69
- get version(): string | null;
70
- get description(): string | null;
71
- get hasAgent(): boolean;
72
- get server(): EndpointDeclaration | null;
73
- get client(): ClientDeclaration | null;
74
- update(snapshot: ProgramSnapshot): void;
75
- agent(): Promise<string | null>;
76
- installed(): Promise<boolean>;
77
- install(): AsyncGenerator<Readonly<{
78
- stream: "stdout" | "stderr";
79
- text: string;
80
- }>, void, void>;
81
- uninstall(everything?: boolean): AsyncGenerator<Readonly<{
82
- stream: "stdout" | "stderr";
83
- text: string;
84
- }>, void, void>;
85
- forget(): Promise<void>;
86
- address(): Readonly<{
87
- identity: string;
88
- reference: string;
89
- }>;
90
- }
91
- declare class ProgramStartup {
92
- private readonly system;
93
- private readonly program;
94
- constructor(system: System, program: ProgramHandle);
95
- get(): Promise<Readonly<{
96
- name?: string;
97
- server?: boolean;
98
- client?: boolean | LaunchClient;
99
- options?: Readonly<Record<string, string>>;
100
- }> | null>;
101
- enable(launch?: Launch): Promise<void>;
102
- disable(): Promise<void>;
103
- private change;
104
- }
105
- declare class ProgramProcesses extends Events<SystemProgramProcessEvents> {
106
- private readonly system;
107
- private readonly program;
108
- constructor(system: System, program: ProgramHandle);
109
- list(): Promise<ProcessHandle[]>;
110
- first(): Promise<ProcessHandle | null>;
111
- last(): Promise<ProcessHandle | null>;
112
- find(identityOrName: string): Promise<ProcessHandle | null>;
113
- create(launch?: Launch): Promise<ProcessHandle>;
114
- run(launch?: Launch, options?: ProgramProcessRunOptions): AsyncGenerator<ProgramProcessRunEvent, void, void>;
115
- findOrCreate(launch: Launch & {
116
- name: string;
117
- }): Promise<ProcessHandle>;
118
- exitAll(): Promise<string[]>;
119
- private createExact;
120
- }
121
- interface ProcessHandle extends SystemProcessEntity {
122
- }
123
- declare class ProcessHandle extends ProcessBase {
124
- private readonly system;
125
- private readonly snapshot;
126
- readonly identity: string;
127
- readonly name: string | null;
128
- readonly startedAt: Date;
129
- readonly server: ServerEndpoint;
130
- readonly client: ClientEndpoint;
131
- constructor(system: System, snapshot: ProcessSnapshot);
132
- program(): ProgramHandle;
133
- exit(): Promise<void>;
134
- exited(): Promise<boolean>;
135
- }
136
- interface ServerEndpoint extends SystemServerEntity {
137
- }
138
- declare class ServerEndpoint extends ServerBase {
139
- private readonly system;
140
- private readonly owner;
141
- readonly endpoint: "server";
142
- private readonly base;
143
- constructor(system: System, owner: ProcessHandle);
144
- process(): Promise<ProcessHandle>;
145
- exists(): Promise<boolean>;
146
- start(): Promise<void>;
147
- stop(): Promise<void>;
148
- publish(event: string, payload?: unknown): void;
149
- ask<Answer = unknown>(event: string, payload?: unknown): Promise<Answer>;
150
- timeout(milliseconds: number): {
151
- ask: <Answer = unknown>(event: string, payload?: unknown) => Promise<Answer>;
152
- };
153
- waitReady(timeout?: number): Promise<void>;
154
- service<EventsMap extends object = {}>(): Promise<ServerService<EventsMap> | null>;
155
- }
156
- interface ClientEndpoint extends SystemClientEntity {
157
- }
158
- declare class ClientEndpoint extends ClientBase {
159
- readonly endpoint: "client";
160
- readonly window: SystemWindow;
161
- private readonly base;
162
- constructor(system: System, owner: ProcessHandle);
163
- process(): Promise<ProcessHandle>;
164
- exists(): Promise<boolean>;
165
- start(overrides?: LaunchClient): Promise<void>;
166
- stop(): Promise<void>;
167
- publish(event: string, payload?: unknown): void;
168
- service<EventsMap extends object = {}>(): Promise<ClientService<EventsMap> | null>;
169
- }
170
- declare class SystemWindow extends Events<WindowEvents> implements Window {
171
- private readonly system;
172
- private readonly process;
173
- constructor(system: System, process: ProcessHandle);
174
- title(): Promise<string>;
175
- position(): Promise<Readonly<{
176
- x: import("@phreshos/core").Value;
177
- y: import("@phreshos/core").Value;
178
- }>>;
179
- size(): Promise<Readonly<{
180
- width: import("@phreshos/core").Value;
181
- height: import("@phreshos/core").Value;
182
- }>>;
183
- minimized(): Promise<boolean>;
184
- front(): Promise<boolean>;
185
- layer(): Promise<import("@phreshos/core").Layer>;
186
- location(): Promise<string>;
187
- move(position: Position): Promise<void>;
188
- resize(size: Size): Promise<void>;
189
- setGeometry(geometry: WindowGeometry): Promise<void>;
190
- minimize(minimized?: boolean): Promise<void>;
191
- changeTitle(title: string): Promise<void>;
192
- raise(): Promise<void>;
193
- private snapshot;
194
- private change;
195
- }
196
- declare class ServerService<EventsMap extends object = {}> extends CoreServerServiceHandler<EventsMap> {
197
- readonly name: string;
198
- readonly channel: ServerServiceChannel<EventsMap>;
199
- private readonly base;
200
- constructor(system: System, key: ServiceKey & {
201
- endpoint: "server";
202
- });
203
- enabled(): Promise<boolean>;
204
- waitReady(timeout?: number): Promise<void>;
205
- }
206
- declare class ClientService<EventsMap extends object = {}> extends CoreClientServiceHandler<EventsMap> {
207
- readonly name: string;
208
- readonly channel: ClientServiceChannel<EventsMap>;
209
- private readonly base;
210
- constructor(system: System, key: ServiceKey & {
211
- endpoint: "client";
212
- });
213
- enabled(): Promise<boolean>;
214
- waitReady(timeout?: number): Promise<void>;
215
35
  }
216
- interface ProgramSnapshot {
217
- reference: string;
218
- identity: string;
219
- name: string;
220
- version: string | null;
221
- description: string | null;
222
- installed?: boolean;
223
- hasAgent: boolean;
224
- server: {
225
- start: boolean;
226
- } | null;
227
- client: ClientDeclaration | null;
36
+ /** Node-SDK handle for a Service provided by a Server Endpoint. */
37
+ export declare class ServerService<EventsMap extends object = {}> extends CoreServerService<EventsMap> {
38
+ protected constructor();
228
39
  }
229
- interface ProcessSnapshot {
230
- reference: string;
231
- identity: string;
232
- name: string | null;
233
- program: string;
234
- programSnapshot?: ProgramSnapshot;
235
- startedAt: string;
236
- server: {
237
- declared: boolean;
238
- running: boolean;
239
- };
240
- client: {
241
- declared: boolean;
242
- running: boolean;
243
- };
40
+ /** Node-SDK handle for a Service provided by a Client Endpoint. */
41
+ export declare class ClientService<EventsMap extends object = {}> extends CoreClientService<EventsMap> {
42
+ protected constructor();
244
43
  }
245
44
  export type Program = SystemProgramEntity;
246
45
  export declare const Program: typeof CoreProgram;
@@ -252,4 +51,3 @@ export type Server<EventsMap extends object = {}> = SystemServerEntity<EventsMap
252
51
  export declare const Server: typeof CoreServer;
253
52
  export type Client<EventsMap extends object = {}> = SystemClientEntity<EventsMap>;
254
53
  export declare const Client: typeof CoreClient;
255
- export {};
package/dist/system.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Client as CoreClient, ClientServiceHandler as CoreClientServiceHandler, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, ServerServiceHandler as CoreServerServiceHandler } from "@phreshos/core";
1
+ import { Client as CoreClient, ClientService as CoreClientService, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, ServerService as CoreServerService, isServiceKey } from "@phreshos/core";
2
2
  import { homedir } from "node:os";
3
3
  import { gatewayAddress } from "./address.js";
4
4
  import Events from "./events.js";
@@ -7,85 +7,95 @@ import { resolveHome } from "./home.js";
7
7
  import { filesystemStorage } from "./storage.js";
8
8
  import { openConnection, request, streamProgram } from "./transport.js";
9
9
  import Uploads from "./uploads.js";
10
+ const systems = new WeakMap();
10
11
  const ProgramBase = CoreProgram;
11
12
  const ProcessBase = CoreProcess;
12
13
  const ServerBase = CoreServer;
13
14
  const ClientBase = CoreClient;
14
15
  /** One connected owner-local implementation of the shared System contract. */
15
16
  export class System {
16
- connection;
17
- home;
18
- address;
19
17
  storage = filesystemStorage(homedir(), "the native home directory");
20
18
  appearance;
21
19
  program;
22
20
  process;
23
21
  uploads;
24
- transport;
25
- closed = false;
26
- lifetime = new AbortController();
27
- handles = new HandleRegistry();
28
- constructor(home, address, connection) {
29
- this.connection = connection;
30
- this.home = home;
31
- this.address = address;
32
- this.transport = {
33
- control: (value, signal) => request(address, "system", value, this.signal(signal)),
34
- api: (value, signal) => request(address, "api", value, this.signal(signal)),
35
- lifecycle: (value, signal) => streamProgram(address, value, this.signal(signal))
22
+ constructor(address, connection) {
23
+ const lifetime = new AbortController();
24
+ const handles = new HandleRegistry();
25
+ const transport = {
26
+ control: (value, signal) => request(address, "system", value, connectedSignal(this, signal)),
27
+ api: (value, signal) => request(address, "api", value, connectedSignal(this, signal)),
28
+ lifecycle: (value, signal) => streamProgram(address, value, connectedSignal(this, signal))
36
29
  };
37
- this.appearance = new SystemAppearance(this.transport);
30
+ systems.set(this, { address, connection, handles, lifetime, transport, closed: false });
31
+ this.appearance = new SystemAppearance(transport);
38
32
  this.program = new ProgramRegistry(this);
39
33
  this.process = new ProcessRegistry(this);
40
- this.uploads = new Uploads(value => this.transport.api(value));
34
+ this.uploads = new Uploads(value => transport.api(value));
41
35
  }
42
36
  /** Connect to the System selected by argument, environment, or owner default. */
43
37
  static async connect(home) {
44
38
  const resolved = resolveHome(home);
45
39
  const address = gatewayAddress(resolved);
46
- return new System(resolved, address, await openConnection(address));
40
+ return new System(address, await openConnection(address));
47
41
  }
48
42
  /** Atomically replace one runtime Program without touching its installed form. */
49
43
  async forceCreateProgram(source) {
50
- this.requireConnected();
51
- for await (const event of this.transport.lifecycle({ word: "force-create", program: source })) {
44
+ requireConnected(this);
45
+ for await (const event of transport(this).lifecycle({ word: "force-create", program: source })) {
52
46
  if (event.event === "created")
53
- return this.programHandle(required(event.program));
47
+ return programHandle(this, required(event.program));
54
48
  }
55
49
  throw new Error("The System did not confirm the created Program");
56
50
  }
57
51
  /** Close this owner connection and abort every attached operation it owns. */
58
52
  async disconnect() {
59
- if (this.closed)
53
+ const state = systemState(this);
54
+ if (state.closed)
60
55
  return;
61
- this.closed = true;
62
- this.lifetime.abort(new Error("This System connection is closed"));
63
- this.connection.destroy();
64
- this.handles.clear();
56
+ state.closed = true;
57
+ state.lifetime.abort(new Error("This System connection is closed"));
58
+ state.connection.destroy();
59
+ state.handles.clear();
65
60
  }
66
61
  service(key) {
67
- this.requireConnected();
68
- return key.endpoint === "server"
69
- ? new ServerService(this, key)
70
- : new ClientService(this, key);
71
- }
72
- programHandle(snapshot) {
73
- const handle = this.handles.obtain(`program:${snapshot.reference}`, () => new ProgramHandle(this, snapshot));
74
- handle.update(snapshot);
75
- return handle;
76
- }
77
- processHandle(snapshot) {
78
- return this.handles.obtain(`process:${snapshot.reference}`, () => new ProcessHandle(this, snapshot));
79
- }
80
- signal(signal) {
81
- this.requireConnected();
82
- return signal ? AbortSignal.any([signal, this.lifetime.signal]) : this.lifetime.signal;
83
- }
84
- requireConnected() {
85
- if (this.closed)
86
- throw new Error("This System connection is closed");
62
+ requireConnected(this);
63
+ if (!isServiceKey(key))
64
+ throw new Error("A complete service key is required");
65
+ const normalized = Object.freeze({ program: key.program, endpoint: key.endpoint, name: key.name });
66
+ const identity = JSON.stringify([normalized.program, normalized.endpoint, normalized.name]);
67
+ return systemState(this).handles.obtain(`service:${identity}`, () => normalized.endpoint === "server"
68
+ ? new ServerServiceHandle(this, normalized)
69
+ : new ClientServiceHandle(this, normalized));
87
70
  }
88
71
  }
72
+ function systemState(system) {
73
+ const state = systems.get(system);
74
+ if (!state)
75
+ throw new Error("Unknown System connection");
76
+ return state;
77
+ }
78
+ function requireConnected(system) {
79
+ if (systemState(system).closed)
80
+ throw new Error("This System connection is closed");
81
+ }
82
+ function connectedSignal(system, signal) {
83
+ const lifetime = systemState(system).lifetime.signal;
84
+ requireConnected(system);
85
+ return signal ? AbortSignal.any([signal, lifetime]) : lifetime;
86
+ }
87
+ function transport(system) {
88
+ requireConnected(system);
89
+ return systemState(system).transport;
90
+ }
91
+ function programHandle(system, snapshot) {
92
+ const handle = systemState(system).handles.obtain(`program:${snapshot.reference}`, () => new ProgramHandle(system, snapshot));
93
+ handle.update(snapshot);
94
+ return handle;
95
+ }
96
+ function processHandle(system, snapshot) {
97
+ return systemState(system).handles.obtain(`process:${snapshot.reference}`, () => new ProcessHandle(system, snapshot));
98
+ }
89
99
  class SystemAppearance extends Events {
90
100
  transport;
91
101
  constructor(transport) {
@@ -102,7 +112,7 @@ class SystemAppearance extends Events {
102
112
  class ProgramRegistry extends Events {
103
113
  system;
104
114
  constructor(system) {
105
- super(["create", "forget", "install", "uninstall"], (event, signal, timeout) => (system.transport.control({ capability: "program", operation: "wait", input: { event, timeout } }, signal)
115
+ super(["create", "forget", "install", "uninstall"], (event, signal, timeout) => (transport(system).control({ capability: "program", operation: "wait", input: { event, timeout } }, signal)
106
116
  .then(value => this.event(value))));
107
117
  this.system = system;
108
118
  }
@@ -110,12 +120,12 @@ class ProgramRegistry extends Events {
110
120
  const programs = [];
111
121
  let offset = 0;
112
122
  while (true) {
113
- const page = await this.system.transport.control({
123
+ const page = await transport(this.system).control({
114
124
  capability: "program",
115
125
  operation: "list",
116
126
  input: { installedOnly: onlyInstalled, limit: 100, offset }
117
127
  });
118
- programs.push(...page.data.map(snapshot => this.system.programHandle(snapshot)));
128
+ programs.push(...page.data.map(snapshot => programHandle(this.system, snapshot)));
119
129
  offset += page.data.length;
120
130
  if (!page.truncated || !page.data.length)
121
131
  return programs;
@@ -123,8 +133,8 @@ class ProgramRegistry extends Events {
123
133
  }
124
134
  async find(identity) {
125
135
  try {
126
- const snapshot = await this.system.transport.control({ capability: "program", operation: "inspect", input: { program: identity } });
127
- return this.system.programHandle(snapshot);
136
+ const snapshot = await transport(this.system).control({ capability: "program", operation: "inspect", input: { program: identity } });
137
+ return programHandle(this.system, snapshot);
128
138
  }
129
139
  catch (error) {
130
140
  if (unknown(error, "Program"))
@@ -133,9 +143,9 @@ class ProgramRegistry extends Events {
133
143
  }
134
144
  }
135
145
  async create(source) {
136
- for await (const event of this.system.transport.lifecycle({ word: "create", program: source })) {
146
+ for await (const event of transport(this.system).lifecycle({ word: "create", program: source })) {
137
147
  if (event.event === "created")
138
- return this.system.programHandle(required(event.program));
148
+ return programHandle(this.system, required(event.program));
139
149
  }
140
150
  throw new Error("The System did not confirm the created Program");
141
151
  }
@@ -143,9 +153,9 @@ class ProgramRegistry extends Events {
143
153
  const waited = value;
144
154
  if (waited.event === "uninstall") {
145
155
  const payload = waited.payload;
146
- return { program: this.system.programHandle(required(payload.program)), everythingRemoved: payload.everythingRemoved === true };
156
+ return { program: programHandle(this.system, required(payload.program)), everythingRemoved: payload.everythingRemoved === true };
147
157
  }
148
- return this.system.programHandle(required(waited.payload));
158
+ return programHandle(this.system, required(waited.payload));
149
159
  }
150
160
  }
151
161
  class ProgramHandle extends ProgramBase {
@@ -159,7 +169,7 @@ class ProgramHandle extends ProgramBase {
159
169
  super();
160
170
  this.system = system;
161
171
  this.snapshot = snapshot;
162
- bindEvents(this, new Events(["forget", "uninstall"], (event, signal, timeout) => system.transport.control({
172
+ bindEvents(this, new Events(["forget", "uninstall"], (event, signal, timeout) => transport(system).control({
163
173
  capability: "program", operation: "wait", input: { program: snapshot.identity, event, timeout }
164
174
  }, signal).then(value => value.payload)));
165
175
  this.reference = snapshot.reference;
@@ -192,11 +202,11 @@ class ProgramHandle extends ProgramBase {
192
202
  async agent() {
193
203
  if (!this.hasAgent)
194
204
  return null;
195
- const value = await this.system.transport.control({ capability: "program", operation: "agent", input: { program: this.identity } });
205
+ const value = await transport(this.system).control({ capability: "program", operation: "agent", input: { program: this.identity } });
196
206
  return typeof value.content === "string" ? value.content : null;
197
207
  }
198
208
  async installed() {
199
- for await (const event of this.system.transport.lifecycle({ word: "installed", handle: this.address() })) {
209
+ for await (const event of transport(this.system).lifecycle({ word: "installed", handle: this.address() })) {
200
210
  if (event.event === "installedState")
201
211
  return event.installed === true;
202
212
  }
@@ -205,7 +215,7 @@ class ProgramHandle extends ProgramBase {
205
215
  install() { return command(this.system, { word: "install-existing", handle: this.address() }); }
206
216
  uninstall(everything = false) { return command(this.system, { word: "uninstall-existing", handle: this.address(), everything }); }
207
217
  async forget() {
208
- for await (const _event of this.system.transport.lifecycle({ word: "forget", handle: this.address() })) { /* consume completion */ }
218
+ for await (const _event of transport(this.system).lifecycle({ word: "forget", handle: this.address() })) { /* consume completion */ }
209
219
  }
210
220
  address() { return Object.freeze({ identity: this.identity, reference: this.reference }); }
211
221
  }
@@ -217,7 +227,7 @@ class ProgramStartup {
217
227
  this.program = program;
218
228
  }
219
229
  async get() {
220
- for await (const event of this.system.transport.lifecycle({
230
+ for await (const event of transport(this.system).lifecycle({
221
231
  word: "startup", handle: this.program.address(), operation: "get"
222
232
  })) {
223
233
  if (event.event === "startup")
@@ -232,7 +242,7 @@ class ProgramStartup {
232
242
  await this.change("disable");
233
243
  }
234
244
  async change(operation, launch) {
235
- for await (const event of this.system.transport.lifecycle({
245
+ for await (const event of transport(this.system).lifecycle({
236
246
  word: "startup", handle: this.program.address(), operation, launch
237
247
  })) {
238
248
  if (event.event === "startup")
@@ -245,7 +255,7 @@ class ProgramProcesses extends Events {
245
255
  system;
246
256
  program;
247
257
  constructor(system, program) {
248
- super(["endpointStart", "endpointStop", "create", "exit"], (event, signal, timeout) => system.transport.control({
258
+ super(["endpointStart", "endpointStop", "create", "exit"], (event, signal, timeout) => transport(system).control({
249
259
  capability: "process", operation: "wait", input: { program: program.identity, event, timeout }
250
260
  }, signal).then(value => processEvent(system, value)));
251
261
  this.system = system;
@@ -261,13 +271,13 @@ class ProgramProcesses extends Events {
261
271
  create(launch = {}) { return this.createExact("create-process", launch); }
262
272
  async *run(launch = {}, options = {}) {
263
273
  let process = null;
264
- for await (const event of this.system.transport.lifecycle({
274
+ for await (const event of transport(this.system).lifecycle({
265
275
  word: "run-process",
266
276
  handle: this.program.address(),
267
277
  launch
268
278
  }, options.signal)) {
269
279
  if (event.event === "started") {
270
- process = this.system.processHandle(required(event.process));
280
+ process = processHandle(this.system, required(event.process));
271
281
  yield Object.freeze({ event: "started", process });
272
282
  }
273
283
  else if (event.event === "output") {
@@ -308,9 +318,9 @@ class ProgramProcesses extends Events {
308
318
  return processes.map(process => process.identity);
309
319
  }
310
320
  async createExact(word, launch) {
311
- for await (const event of this.system.transport.lifecycle({ word, handle: this.program.address(), launch })) {
321
+ for await (const event of transport(this.system).lifecycle({ word, handle: this.program.address(), launch })) {
312
322
  if (event.event === "createdProcess")
313
- return this.system.processHandle(required(event.process));
323
+ return processHandle(this.system, required(event.process));
314
324
  }
315
325
  throw new Error("The System did not confirm the created Process");
316
326
  }
@@ -318,7 +328,7 @@ class ProgramProcesses extends Events {
318
328
  class ProcessRegistry extends Events {
319
329
  system;
320
330
  constructor(system) {
321
- super(["endpointStart", "endpointStop", "create", "exit"], (event, signal, timeout) => system.transport.control({
331
+ super(["endpointStart", "endpointStop", "create", "exit"], (event, signal, timeout) => transport(system).control({
322
332
  capability: "process", operation: "wait", input: { event, timeout }
323
333
  }, signal).then(value => processEvent(system, value)));
324
334
  this.system = system;
@@ -326,8 +336,8 @@ class ProcessRegistry extends Events {
326
336
  list() { return listProcesses(this.system); }
327
337
  async find(identity) {
328
338
  try {
329
- const snapshot = await this.system.transport.control({ capability: "process", operation: "inspect", input: { process: identity } });
330
- return this.system.processHandle(snapshot);
339
+ const snapshot = await transport(this.system).control({ capability: "process", operation: "inspect", input: { process: identity } });
340
+ return processHandle(this.system, snapshot);
331
341
  }
332
342
  catch (error) {
333
343
  if (unknown(error, "Process"))
@@ -348,7 +358,7 @@ class ProcessHandle extends ProcessBase {
348
358
  super();
349
359
  this.system = system;
350
360
  this.snapshot = snapshot;
351
- bindEvents(this, new Events(["endpointStart", "endpointStop", "exit"], (event, signal, timeout) => system.transport.control({
361
+ bindEvents(this, new Events(["endpointStart", "endpointStop", "exit"], (event, signal, timeout) => transport(system).control({
352
362
  capability: "process", operation: "wait", input: { process: snapshot.identity, event, timeout }
353
363
  }, signal).then(value => processEvent(system, value))));
354
364
  this.identity = snapshot.identity;
@@ -357,9 +367,9 @@ class ProcessHandle extends ProcessBase {
357
367
  this.server = new ServerEndpoint(system, this);
358
368
  this.client = new ClientEndpoint(system, this);
359
369
  }
360
- program() { return this.system.programHandle(required(this.snapshot.programSnapshot, this.snapshot.program)); }
370
+ program() { return programHandle(this.system, required(this.snapshot.programSnapshot, this.snapshot.program)); }
361
371
  async exit() {
362
- await this.system.transport.control({ capability: "process", operation: "exit", input: { process: this.identity } });
372
+ await transport(this.system).control({ capability: "process", operation: "exit", input: { process: this.identity } });
363
373
  }
364
374
  async exited() { return await this.system.process.find(this.identity) === null; }
365
375
  }
@@ -369,8 +379,8 @@ class EndpointOperations extends Events {
369
379
  endpoint;
370
380
  constructor(system, owner, endpoint) {
371
381
  super([], (event, signal, timeout) => event === null
372
- ? system.transport.api({ capability: "endpoint", operation: "wait", process: owner.identity, endpoint, event, timeout }, signal)
373
- : system.transport.control({
382
+ ? transport(system).api({ capability: "endpoint", operation: "wait", process: owner.identity, endpoint, event, timeout }, signal)
383
+ : transport(system).control({
374
384
  capability: "endpoint", operation: "wait", input: { process: owner.identity, endpoint, event, timeout }
375
385
  }, signal).then(value => value.payload));
376
386
  this.system = system;
@@ -385,21 +395,21 @@ class EndpointOperations extends Events {
385
395
  async start(client) { await this.operation("start", client); }
386
396
  async stop() { await this.operation("stop"); }
387
397
  async service() {
388
- const key = await this.system.transport.api({ capability: "endpoint", operation: "service", process: this.owner.identity, endpoint: this.endpoint });
398
+ const key = await transport(this.system).api({ capability: "endpoint", operation: "service", process: this.owner.identity, endpoint: this.endpoint });
389
399
  return key ? this.system.service(key) : null;
390
400
  }
391
401
  publish(event, payload) {
392
- void this.system.transport.control({ capability: "endpoint", operation: "publish", input: {
402
+ void transport(this.system).control({ capability: "endpoint", operation: "publish", input: {
393
403
  process: this.owner.identity, endpoint: this.endpoint, event, payload
394
404
  } });
395
405
  }
396
406
  inspect() {
397
- return this.system.transport.control({ capability: "endpoint", operation: "inspect", input: {
407
+ return transport(this.system).control({ capability: "endpoint", operation: "inspect", input: {
398
408
  process: this.owner.identity, endpoint: this.endpoint
399
409
  } });
400
410
  }
401
411
  async operation(operation, client) {
402
- await this.system.transport.control({ capability: "endpoint", operation, input: {
412
+ await transport(this.system).control({ capability: "endpoint", operation, input: {
403
413
  process: this.owner.identity, endpoint: this.endpoint, ...(client ? { client } : {})
404
414
  } });
405
415
  }
@@ -422,17 +432,17 @@ class ServerEndpoint extends ServerBase {
422
432
  stop() { return this.base.stop(); }
423
433
  publish(event, payload) { return this.base.publish(event, payload); }
424
434
  async ask(event, payload) {
425
- return await this.system.transport.control({ capability: "endpoint", operation: "ask", input: {
435
+ return await transport(this.system).control({ capability: "endpoint", operation: "ask", input: {
426
436
  process: this.owner.identity, endpoint: "server", event, payload
427
437
  } });
428
438
  }
429
439
  timeout(milliseconds) {
430
- return { ask: (event, payload) => this.system.transport.control({
440
+ return { ask: (event, payload) => transport(this.system).control({
431
441
  capability: "endpoint", operation: "ask", input: { process: this.owner.identity, endpoint: "server", event, payload, timeout: milliseconds }
432
442
  }) };
433
443
  }
434
444
  async waitReady(timeout) {
435
- await this.system.transport.control({ capability: "endpoint", operation: "waitReady", input: { process: this.owner.identity, endpoint: "server", timeout } });
445
+ await transport(this.system).control({ capability: "endpoint", operation: "waitReady", input: { process: this.owner.identity, endpoint: "server", timeout } });
436
446
  }
437
447
  async service() {
438
448
  return await this.base.service();
@@ -461,7 +471,7 @@ class SystemWindow extends Events {
461
471
  system;
462
472
  process;
463
473
  constructor(system, process) {
464
- super(["move", "resize", "geometry", "minimize", "changeTitle", "front"], (event, signal, timeout) => system.transport.control({
474
+ super(["move", "resize", "geometry", "minimize", "changeTitle", "front"], (event, signal, timeout) => transport(system).control({
465
475
  capability: "window", operation: "wait", input: { process: process.identity, event, timeout }
466
476
  }, signal).then(value => value.payload));
467
477
  this.system = system;
@@ -481,10 +491,10 @@ class SystemWindow extends Events {
481
491
  async changeTitle(title) { await this.change("changeTitle", { title }); }
482
492
  async raise() { await this.change("raise", {}); }
483
493
  snapshot() {
484
- return this.system.transport.control({ capability: "window", operation: "inspect", input: { process: this.process.identity } });
494
+ return transport(this.system).control({ capability: "window", operation: "inspect", input: { process: this.process.identity } });
485
495
  }
486
496
  async change(operation, input) {
487
- await this.system.transport.control({ capability: "window", operation, input: { process: this.process.identity, ...input } });
497
+ await transport(this.system).control({ capability: "window", operation, input: { process: this.process.identity, ...input } });
488
498
  }
489
499
  }
490
500
  class ServiceBase extends Events {
@@ -492,17 +502,21 @@ class ServiceBase extends Events {
492
502
  key;
493
503
  name;
494
504
  constructor(system, key) {
495
- super(["enable", "disable"], (event, signal, timeout) => system.transport.api({
505
+ super(["enable", "disable"], (event, signal, timeout) => transport(system).api({
496
506
  capability: "service", operation: "wait", scope: "lifecycle", key, event, timeout
497
507
  }, signal));
498
508
  this.system = system;
499
509
  this.key = key;
500
510
  this.name = key.name;
501
511
  }
502
- async enabled() { return await this.system.transport.api({ capability: "service", operation: "enabled", key: this.key }); }
503
- async waitReady(timeout) { await this.system.transport.api({ capability: "service", operation: "waitReady", key: this.key, timeout }); }
512
+ async enabled() { return await transport(this.system).api({ capability: "service", operation: "enabled", key: this.key }); }
513
+ async waitReady(timeout) { await transport(this.system).api({ capability: "service", operation: "waitReady", key: this.key, timeout }); }
514
+ }
515
+ /** Node-SDK handle for a Service provided by a Server Endpoint. */
516
+ export class ServerService extends CoreServerService {
517
+ constructor() { super(); }
504
518
  }
505
- class ServerService extends CoreServerServiceHandler {
519
+ class ServerServiceHandle extends ServerService {
506
520
  name;
507
521
  channel;
508
522
  base;
@@ -516,7 +530,11 @@ class ServerService extends CoreServerServiceHandler {
516
530
  enabled() { return this.base.enabled(); }
517
531
  waitReady(timeout) { return this.base.waitReady(timeout); }
518
532
  }
519
- class ClientService extends CoreClientServiceHandler {
533
+ /** Node-SDK handle for a Service provided by a Client Endpoint. */
534
+ export class ClientService extends CoreClientService {
535
+ constructor() { super(); }
536
+ }
537
+ class ClientServiceHandle extends ClientService {
520
538
  name;
521
539
  channel;
522
540
  base;
@@ -534,37 +552,37 @@ class ClientServiceChannelHandle extends Events {
534
552
  system;
535
553
  key;
536
554
  constructor(system, key) {
537
- super([], (event, signal, timeout) => system.transport.api({ capability: "service", operation: "wait", scope: "channel", key, event, timeout }, signal));
555
+ super([], (event, signal, timeout) => transport(system).api({ capability: "service", operation: "wait", scope: "channel", key, event, timeout }, signal));
538
556
  this.system = system;
539
557
  this.key = key;
540
558
  }
541
559
  }
542
560
  class ServerServiceChannelHandle extends ClientServiceChannelHandle {
543
561
  async ask(event, payload) {
544
- return await this.system.transport.api({ capability: "service", operation: "ask", key: this.key, event, payload });
562
+ return await transport(this.system).api({ capability: "service", operation: "ask", key: this.key, event, payload });
545
563
  }
546
564
  timeout(milliseconds) {
547
- return { ask: (event, payload) => this.system.transport.api({
565
+ return { ask: (event, payload) => transport(this.system).api({
548
566
  capability: "service", operation: "ask", key: this.key, event, payload, timeout: milliseconds
549
567
  }) };
550
568
  }
551
569
  publish(event, payload) {
552
- void this.system.transport.api({ capability: "service", operation: "publish", key: this.key, event, payload });
570
+ void transport(this.system).api({ capability: "service", operation: "publish", key: this.key, event, payload });
553
571
  }
554
572
  }
555
573
  async function listProcesses(system, program) {
556
574
  const processes = [];
557
575
  let offset = 0;
558
576
  while (true) {
559
- const page = await system.transport.control({ capability: "process", operation: "list", input: { program, limit: 100, offset } });
560
- processes.push(...page.data.map(snapshot => system.processHandle(snapshot)));
577
+ const page = await transport(system).control({ capability: "process", operation: "list", input: { program, limit: 100, offset } });
578
+ processes.push(...page.data.map(snapshot => processHandle(system, snapshot)));
561
579
  offset += page.data.length;
562
580
  if (!page.truncated || !page.data.length)
563
581
  return processes;
564
582
  }
565
583
  }
566
584
  async function* command(system, request) {
567
- for await (const event of system.transport.lifecycle(request)) {
585
+ for await (const event of transport(system).lifecycle(request)) {
568
586
  if (event.event === "output")
569
587
  yield {
570
588
  stream: event.stream === "stderr" ? "stderr" : "stdout",
@@ -577,17 +595,17 @@ function processEvent(system, value) {
577
595
  const payload = waited.payload;
578
596
  if (waited.event === "exit" && payload)
579
597
  return {
580
- process: system.processHandle(required(payload.processSnapshot, String(payload.process ?? ""))),
598
+ process: processHandle(system, required(payload.processSnapshot, String(payload.process ?? ""))),
581
599
  status: payload.status,
582
600
  code: payload.code,
583
601
  signal: payload.signal
584
602
  };
585
603
  if ((waited.event === "endpointStart" || waited.event === "endpointStop") && payload?.processSnapshot) {
586
- const process = system.processHandle(payload.processSnapshot);
604
+ const process = processHandle(system, payload.processSnapshot);
587
605
  return payload.endpoint === "client" ? process.client : process.server;
588
606
  }
589
607
  if (payload && typeof payload.identity === "string")
590
- return system.processHandle(payload);
608
+ return processHandle(system, payload);
591
609
  return payload;
592
610
  }
593
611
  function bindEvents(target, events) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phreshos/node",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Node.js access to PhreshOS and Program projects.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -32,7 +32,7 @@
32
32
  "prepack": "node --run build"
33
33
  },
34
34
  "dependencies": {
35
- "@phreshos/core": "^0.1.23",
35
+ "@phreshos/core": "^0.1.25",
36
36
  "adm-zip": "^0.6.0",
37
37
  "jiti": "^2.7.0"
38
38
  },