@phreshos/client 0.1.32 → 0.1.33
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 +23 -13
- package/dist/appearance.d.ts +3 -1
- package/dist/appearance.js +3 -0
- package/dist/context.d.ts +8 -28
- package/dist/context.js +9 -8
- package/dist/desktop/desktop.d.ts +3 -13
- package/dist/desktop/desktop.js +4 -4
- package/dist/desktop/preferences.d.ts +3 -3
- package/dist/desktop/preferences.js +1 -1
- package/dist/desktop/surface.d.ts +3 -2
- package/dist/desktop/surface.js +1 -1
- package/dist/domain.d.ts +37 -88
- package/dist/domain.js +90 -64
- package/dist/events.d.ts +5 -7
- package/dist/events.js +6 -6
- package/dist/main.d.ts +4 -4
- package/dist/main.js +2 -2
- package/dist/permissions.d.ts +7 -10
- package/dist/permissions.js +34 -21
- package/dist/service.js +3 -3
- package/dist/startup.d.ts +4 -0
- package/dist/startup.js +16 -0
- package/dist/storage.d.ts +9 -5
- package/dist/storage.js +59 -8
- package/dist/system.d.ts +3 -27
- package/dist/system.js +67 -3
- package/dist/uploads.d.ts +1 -0
- package/dist/uploads.js +6 -0
- package/dist/wire.d.ts +2 -3
- package/dist/wire.js +16 -6
- package/package.json +3 -3
- package/dist/desktop/pointer.d.ts +0 -11
- package/dist/desktop/pointer.js +0 -59
package/dist/domain.js
CHANGED
|
@@ -1,35 +1,45 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint } 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";
|
|
5
5
|
import { area, sql, store } from "./storage.js";
|
|
6
|
+
import startup from "./startup.js";
|
|
7
|
+
import { programPermissions } from "./permissions.js";
|
|
6
8
|
import wire from "./wire.js";
|
|
7
|
-
import { currentProgramPermission } from "./permissions.js";
|
|
8
9
|
const handles = new HandleRegistry();
|
|
9
10
|
const ProgramBase = CoreProgram;
|
|
10
11
|
const ProcessBase = CoreProcess;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
12
|
+
const ServerEndpointBase = CoreServerEndpoint;
|
|
13
|
+
const ClientEndpointBase = CoreClientEndpoint;
|
|
13
14
|
class ProgramHandle extends ProgramBase {
|
|
14
15
|
identity;
|
|
15
16
|
reference;
|
|
16
|
-
data
|
|
17
|
-
cache
|
|
18
|
-
store
|
|
19
|
-
logs
|
|
20
|
-
database
|
|
21
|
-
|
|
17
|
+
data;
|
|
18
|
+
cache;
|
|
19
|
+
store;
|
|
20
|
+
logs;
|
|
21
|
+
database;
|
|
22
|
+
startup;
|
|
22
23
|
process;
|
|
24
|
+
permissions;
|
|
23
25
|
record;
|
|
24
26
|
constructor(record) {
|
|
25
27
|
super();
|
|
26
28
|
this.identity = record.identity;
|
|
27
29
|
this.reference = record.reference;
|
|
28
30
|
this.record = record;
|
|
29
|
-
this.
|
|
31
|
+
this.data = area(this.address, "data");
|
|
32
|
+
this.cache = area(this.address, "cache");
|
|
33
|
+
this.store = store(this.address);
|
|
34
|
+
this.logs = sql("logs", this.address);
|
|
35
|
+
this.database = sql("database", this.address);
|
|
36
|
+
this.startup = startup(this.address);
|
|
37
|
+
this.permissions = programPermissions(this.address);
|
|
38
|
+
this.process = new ProgramProcessHandle(this.address, record.reference);
|
|
30
39
|
bindEvents(this, scoped("program-host", record.reference, programEvent));
|
|
31
40
|
}
|
|
32
41
|
get name() { return this.record.name; }
|
|
42
|
+
get assetId() { return this.record.assetId; }
|
|
33
43
|
get version() { return this.record.version; }
|
|
34
44
|
get description() { return this.record.description; }
|
|
35
45
|
get hasAgent() { return this.record.hasAgent; }
|
|
@@ -39,31 +49,41 @@ class ProgramHandle extends ProgramBase {
|
|
|
39
49
|
get client() {
|
|
40
50
|
return this.record.client ? clientDeclaration(this.record.client) : null;
|
|
41
51
|
}
|
|
52
|
+
get address() { return { identity: this.identity, reference: this.reference }; }
|
|
42
53
|
update(record) {
|
|
43
54
|
if (record.reference !== this.reference)
|
|
44
55
|
throw new Error("A Program handle cannot become another Program");
|
|
45
56
|
this.record = record;
|
|
46
57
|
}
|
|
47
58
|
async icon(size = "medium") {
|
|
48
|
-
const answer = await wire.request(["icon", size]);
|
|
59
|
+
const answer = await wire.request(["icon", this.address, size]);
|
|
49
60
|
return new Blob([Uint8Array.from(answer[0])], { type: "image/png" });
|
|
50
61
|
}
|
|
51
62
|
async agent() {
|
|
52
63
|
if (!this.hasAgent)
|
|
53
64
|
return null;
|
|
54
|
-
const answer = await wire.request(["program-agent"]);
|
|
65
|
+
const answer = await wire.request(["program-agent", this.address]);
|
|
55
66
|
return answer[0];
|
|
56
67
|
}
|
|
57
68
|
async installed() {
|
|
58
|
-
const answer = await wire.request(["installed"]);
|
|
69
|
+
const answer = await wire.request(["installed", this.address]);
|
|
59
70
|
return answer[0];
|
|
60
71
|
}
|
|
72
|
+
async *install() {
|
|
73
|
+
for await (const value of wire.stream(["install", this.address])) {
|
|
74
|
+
yield programCommandChunk(value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async fork(identity) {
|
|
78
|
+
const answer = await wire.request(["fork", this.address, identity]);
|
|
79
|
+
return program(answer[0]);
|
|
80
|
+
}
|
|
61
81
|
async *uninstall(everything = false) {
|
|
62
|
-
for await (const value of wire.stream(["uninstall",
|
|
82
|
+
for await (const value of wire.stream(["uninstall", this.address, everything])) {
|
|
63
83
|
yield programCommandChunk(value);
|
|
64
84
|
}
|
|
65
85
|
}
|
|
66
|
-
async forget() { await wire.request(["forget"]); }
|
|
86
|
+
async forget() { await wire.request(["forget", this.address]); }
|
|
67
87
|
}
|
|
68
88
|
function programCommandChunk(value) {
|
|
69
89
|
const chunk = value;
|
|
@@ -85,15 +105,18 @@ function clientDeclaration(record) {
|
|
|
85
105
|
size: record.size,
|
|
86
106
|
position: record.position,
|
|
87
107
|
layer: record.layer,
|
|
88
|
-
minimize: record.minimize
|
|
108
|
+
minimize: record.minimize,
|
|
109
|
+
permissions: Object.freeze(Object.fromEntries(Object.entries(record.permissions).map(([name, values]) => [name, Object.freeze([...values])])))
|
|
89
110
|
});
|
|
90
111
|
}
|
|
91
112
|
class ProgramProcessHandle {
|
|
92
|
-
|
|
93
|
-
|
|
113
|
+
address;
|
|
114
|
+
constructor(address, reference) {
|
|
115
|
+
this.address = address;
|
|
116
|
+
bindEvents(this, scoped("program-process", reference, programProcessEvent));
|
|
94
117
|
}
|
|
95
118
|
async list() {
|
|
96
|
-
const answer = await wire.request(["program-process-list"]);
|
|
119
|
+
const answer = await wire.request(["program-process-list", this.address]);
|
|
97
120
|
return answer[0].map(record => process(record));
|
|
98
121
|
}
|
|
99
122
|
async first() {
|
|
@@ -103,22 +126,42 @@ class ProgramProcessHandle {
|
|
|
103
126
|
return chronological(await this.list()).at(-1) ?? null;
|
|
104
127
|
}
|
|
105
128
|
async find(identityOrName) {
|
|
106
|
-
const answer = await wire.request(["program-process-find", identityOrName]);
|
|
129
|
+
const answer = await wire.request(["program-process-find", this.address, identityOrName]);
|
|
107
130
|
return answer[0] ? process(answer[0]) : null;
|
|
108
131
|
}
|
|
109
132
|
async create(launch = {}) {
|
|
110
|
-
const answer = await wire.request(["program-process-create", launch]);
|
|
133
|
+
const answer = await wire.request(["program-process-create", this.address, launch]);
|
|
111
134
|
return process(answer[0]);
|
|
112
135
|
}
|
|
136
|
+
async *run(launch = {}, options = {}) {
|
|
137
|
+
for await (const value of wire.stream(["run", this.address, launch], undefined, options.signal)) {
|
|
138
|
+
yield processRunEvent(value);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
113
141
|
async findOrCreate(launch) {
|
|
114
|
-
const answer = await wire.request(["program-process-find-or-create", launch]);
|
|
142
|
+
const answer = await wire.request(["program-process-find-or-create", this.address, launch]);
|
|
115
143
|
return process(answer[0]);
|
|
116
144
|
}
|
|
117
145
|
async exitAll() {
|
|
118
|
-
const answer = await wire.request(["program-process-exit-all"]);
|
|
146
|
+
const answer = await wire.request(["program-process-exit-all", this.address]);
|
|
119
147
|
return answer[0];
|
|
120
148
|
}
|
|
121
149
|
}
|
|
150
|
+
function processRunEvent(value) {
|
|
151
|
+
const event = value;
|
|
152
|
+
if (event?.event === "started" && event.process) {
|
|
153
|
+
return Object.freeze({ event: "started", process: process(event.process) });
|
|
154
|
+
}
|
|
155
|
+
if (event?.event === "output" && (event.stream === "stdout" || event.stream === "stderr") && typeof event.text === "string") {
|
|
156
|
+
return Object.freeze({ event: "output", stream: event.stream, text: event.text });
|
|
157
|
+
}
|
|
158
|
+
if (event?.event === "exited" && event.process) {
|
|
159
|
+
const code = typeof event.exit?.code === "number" ? event.exit.code : null;
|
|
160
|
+
const signal = typeof event.exit?.signal === "string" ? event.exit.signal : null;
|
|
161
|
+
return Object.freeze({ event: "exited", process: process(event.process), exit: exit(code, signal) });
|
|
162
|
+
}
|
|
163
|
+
throw new Error("The System returned an invalid Process run event");
|
|
164
|
+
}
|
|
122
165
|
function chronological(processes) {
|
|
123
166
|
return processes.sort((left, right) => left.startedAt.getTime() - right.startedAt.getTime());
|
|
124
167
|
}
|
|
@@ -202,7 +245,7 @@ export class ServerTrafficHandle extends TrafficHandle {
|
|
|
202
245
|
}, impossible);
|
|
203
246
|
}
|
|
204
247
|
}
|
|
205
|
-
class
|
|
248
|
+
class ServerEndpointHandle extends ServerEndpointBase {
|
|
206
249
|
owner;
|
|
207
250
|
traffic;
|
|
208
251
|
lifecycle;
|
|
@@ -245,7 +288,7 @@ class ServerHandle extends ServerBase {
|
|
|
245
288
|
}
|
|
246
289
|
}
|
|
247
290
|
}
|
|
248
|
-
class
|
|
291
|
+
class ClientEndpointHandle extends ClientEndpointBase {
|
|
249
292
|
owner;
|
|
250
293
|
traffic;
|
|
251
294
|
lifecycle;
|
|
@@ -271,11 +314,9 @@ class ClientHandle extends ClientBase {
|
|
|
271
314
|
}
|
|
272
315
|
class WindowHandle extends Events {
|
|
273
316
|
target;
|
|
274
|
-
local;
|
|
275
317
|
constructor(target) {
|
|
276
318
|
super(...deferredScoped("host-end", target, (_event, values) => values[0]));
|
|
277
319
|
this.target = target;
|
|
278
|
-
this.local = new LocalWindowHandle(target);
|
|
279
320
|
}
|
|
280
321
|
async state() {
|
|
281
322
|
const answer = await wire.request(["window", await this.target()]);
|
|
@@ -297,39 +338,21 @@ class WindowHandle extends Events {
|
|
|
297
338
|
}
|
|
298
339
|
class LocalWindowHandle {
|
|
299
340
|
target;
|
|
300
|
-
|
|
301
|
-
constructor(target) {
|
|
341
|
+
selected;
|
|
342
|
+
constructor(target, selected) {
|
|
302
343
|
this.target = target;
|
|
303
|
-
this.
|
|
344
|
+
this.selected = selected;
|
|
304
345
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return answer[0];
|
|
346
|
+
transaction(transaction) {
|
|
347
|
+
return new LocalWindowHandle(this.target, transaction);
|
|
308
348
|
}
|
|
309
|
-
async
|
|
310
|
-
async
|
|
311
|
-
async
|
|
312
|
-
async
|
|
313
|
-
async
|
|
314
|
-
async
|
|
315
|
-
|
|
316
|
-
async move(position, transaction) { await wire.request(["windowLocalMove", await this.target(), position, transaction]); }
|
|
317
|
-
async resize(size, transaction) { await wire.request(["windowLocalResize", await this.target(), size, transaction]); }
|
|
318
|
-
async setGeometry(geometry, transaction) { await wire.request(["windowLocalGeometry", await this.target(), geometry, transaction]); }
|
|
319
|
-
async minimize(minimized = true) { await wire.request(["windowLocalMinimize", await this.target(), minimized]); }
|
|
320
|
-
async changeTitle(title) { await wire.request(["windowLocalTitle", await this.target(), title]); }
|
|
321
|
-
async raise() { await wire.request(["windowLocalRaise", await this.target()]); }
|
|
322
|
-
}
|
|
323
|
-
class LocalWindowSurfaceHandle {
|
|
324
|
-
target;
|
|
325
|
-
constructor(target) {
|
|
326
|
-
this.target = target;
|
|
327
|
-
}
|
|
328
|
-
async set(transition) {
|
|
329
|
-
await wire.request(["windowLocalSurfaceSet", await this.target(), transition]);
|
|
330
|
-
}
|
|
331
|
-
async remove(transition) {
|
|
332
|
-
await wire.request(["windowLocalSurfaceRemove", await this.target(), transition]);
|
|
349
|
+
async addSurface() { await this.change("windowLocalSurfaceAdd"); }
|
|
350
|
+
async removeSurface() { await this.change("windowLocalSurfaceRemove"); }
|
|
351
|
+
async move(position) { await this.change("windowLocalMove", position); }
|
|
352
|
+
async resize(size) { await this.change("windowLocalResize", size); }
|
|
353
|
+
async setGeometry(geometry) { await this.change("windowLocalGeometry", geometry); }
|
|
354
|
+
async change(operation, value) {
|
|
355
|
+
await wire.request([operation, await this.target(), value, this.selected]);
|
|
333
356
|
}
|
|
334
357
|
}
|
|
335
358
|
function deferredScoped(route, target, convert) {
|
|
@@ -473,12 +496,15 @@ export function claimEndpoint(reference, kind, endpoint) {
|
|
|
473
496
|
return handles.adopt(`endpoint:${reference}:${kind}`, endpoint);
|
|
474
497
|
}
|
|
475
498
|
function endpointHandle(owner, kind, preferred) {
|
|
476
|
-
return handles.obtain(`endpoint:${owner.reference}:${kind}`, () => preferred ?? (kind === "server" ? new
|
|
499
|
+
return handles.obtain(`endpoint:${owner.reference}:${kind}`, () => preferred ?? (kind === "server" ? new ServerEndpointHandle(owner) : new ClientEndpointHandle(owner)));
|
|
477
500
|
}
|
|
478
501
|
export function window(target) {
|
|
479
502
|
return new WindowHandle(target);
|
|
480
503
|
}
|
|
481
|
-
|
|
504
|
+
export function localWindow(target) {
|
|
505
|
+
return new LocalWindowHandle(target);
|
|
506
|
+
}
|
|
507
|
+
/** Resolves an Endpoint reference through the Client Endpoint's global handle registry. */
|
|
482
508
|
export function visibleEndpoint(reference) {
|
|
483
509
|
if (reference === null)
|
|
484
510
|
return null;
|
|
@@ -490,7 +516,7 @@ export const Program = CoreProgram;
|
|
|
490
516
|
export const Process = CoreProcess;
|
|
491
517
|
/** Runtime constructor shared by all client-visible Endpoint handles. */
|
|
492
518
|
export const Endpoint = CoreEndpoint;
|
|
493
|
-
/** Runtime constructor shared by all client-visible Server handles. */
|
|
494
|
-
export const
|
|
495
|
-
/** Runtime constructor shared by all client-visible Client handles. */
|
|
496
|
-
export const
|
|
519
|
+
/** Runtime constructor shared by all client-visible Server Endpoint handles. */
|
|
520
|
+
export const ServerEndpoint = CoreServerEndpoint;
|
|
521
|
+
/** Runtime constructor shared by all client-visible Client Endpoint handles. */
|
|
522
|
+
export const ClientEndpoint = CoreClientEndpoint;
|
package/dist/events.d.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Cleanup, EventOptions, Subscribable } 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
5
|
type EveryListener = (event: string, message: unknown) => unknown;
|
|
6
6
|
type Register<Message> = (listener: (message: Message) => unknown, impossible?: Failure) => Cleanup;
|
|
7
7
|
/** SDK-owned waits, queues and callbacks over boundary forwarding state. */
|
|
8
|
-
export default class Events {
|
|
8
|
+
export default class Events<Vocabulary extends object = {}, Fallback = unknown> implements Subscribable<Vocabulary, Fallback> {
|
|
9
9
|
private readonly listen;
|
|
10
10
|
private readonly listenAll;
|
|
11
11
|
constructor(listen: (event: string, listener: Listener, impossible?: Failure) => Cleanup, listenAll: (listener: EveryListener, impossible?: Failure) => Cleanup);
|
|
12
|
-
subscribe
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
events(event: string, options?: EventOptions): AsyncIterableIterator<unknown>;
|
|
16
|
-
events(options?: EventOptions): AsyncIterableIterator<Capture<string, unknown>>;
|
|
12
|
+
readonly subscribe: Subscribable<Vocabulary, Fallback>["subscribe"];
|
|
13
|
+
readonly waitFor: Subscribable<Vocabulary, Fallback>["waitFor"];
|
|
14
|
+
readonly events: Subscribable<Vocabulary, Fallback>["events"];
|
|
17
15
|
}
|
|
18
16
|
/** Converts one persistent registration into a bounded asynchronous iterator. */
|
|
19
17
|
export declare function stream<Message>(register: Register<Message>, options?: EventOptions): AsyncIterableIterator<Message>;
|
package/dist/events.js
CHANGED
|
@@ -7,12 +7,12 @@ export default class Events {
|
|
|
7
7
|
this.listen = listen;
|
|
8
8
|
this.listenAll = listenAll;
|
|
9
9
|
}
|
|
10
|
-
subscribe(eventOrSubscriber, subscriber) {
|
|
10
|
+
subscribe = ((eventOrSubscriber, subscriber) => {
|
|
11
11
|
if (typeof eventOrSubscriber === "string")
|
|
12
12
|
return this.listen(eventOrSubscriber, subscriber);
|
|
13
13
|
return this.listenAll((event, message) => eventOrSubscriber({ event, message }));
|
|
14
|
-
}
|
|
15
|
-
waitFor(event, timeout = defaultTimeout) {
|
|
14
|
+
});
|
|
15
|
+
waitFor = ((event, timeout = defaultTimeout) => {
|
|
16
16
|
return new Promise((resolve, reject) => {
|
|
17
17
|
let settled = false;
|
|
18
18
|
let stop = () => undefined;
|
|
@@ -27,13 +27,13 @@ export default class Events {
|
|
|
27
27
|
const timer = setTimeout(() => finish(() => reject(new Error(`Event promise timeout ${timeout}ms`))), timeout);
|
|
28
28
|
stop = this.listen(event, message => finish(() => resolve(message)), error => finish(() => reject(error)));
|
|
29
29
|
});
|
|
30
|
-
}
|
|
31
|
-
events(eventOrOptions = {}, namedOptions = {}) {
|
|
30
|
+
});
|
|
31
|
+
events = ((eventOrOptions = {}, namedOptions = {}) => {
|
|
32
32
|
if (typeof eventOrOptions === "string") {
|
|
33
33
|
return stream((listener, impossible) => this.listen(eventOrOptions, listener, impossible), namedOptions);
|
|
34
34
|
}
|
|
35
35
|
return stream((listener, impossible) => this.listenAll((event, message) => listener({ event, message }), impossible), eventOrOptions);
|
|
36
|
-
}
|
|
36
|
+
});
|
|
37
37
|
}
|
|
38
38
|
/** Converts one persistent registration into a bounded asynchronous iterator. */
|
|
39
39
|
export function stream(register, options = {}) {
|
package/dist/main.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { system
|
|
2
|
-
export {
|
|
1
|
+
export { system } from "./system.js";
|
|
2
|
+
export { desktop } from "./desktop/desktop.js";
|
|
3
3
|
export { context, type Context, type ContextCapture, type ContextEvents, type ContextMessage, type ContextServer } from "./context.js";
|
|
4
4
|
export { ClientService, ServerService, Service, type ServiceKey, } from "@phreshos/core";
|
|
5
|
-
export {
|
|
6
|
-
export type { Askable, Capture, Captures, CaptureSubscriber, ClientLaunch, ClientDeclaration, Cleanup, DirectoryStat, EndpointDeclaration, EndpointLifecycle, EndpointLifecycleEvents, EntryStat, EventMessage, EventName, EventOptions, EventSubscriber, Exit, FileStat, Launch, ServerLaunch, Layer, LogKind, LogRecord, LogSource, Message, OtherStat, Outcome,
|
|
5
|
+
export { ClientEndpoint, Endpoint, Process, Program, ServerEndpoint, type Window, type ProgramProcess, type ProgramProcessRunEvent, type ProgramProcessRunOptions, 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";
|
|
6
|
+
export type { Askable, ClientContext, Capture, Captures, CaptureSubscriber, ClientLaunch, ClientDeclaration, Cleanup, DirectoryStat, EndpointDeclaration, EndpointLifecycle, EndpointLifecycleEvents, EntryStat, EventMessage, EventName, EventOptions, EventSubscriber, Exit, FileStat, Launch, ServerLaunch, ShellEvent, ShellOptions, Layer, LogKind, LogRecord, LogSource, Message, OtherStat, Outcome, Permission, PermissionChange, PermissionInput, PermissionRequest, Permissions, ClientPermissionDeclarations, ClientPermissions, ContextPermissions, ProgramPermissions, TimedContextPermissions, Position, Storage, ProgramEvents, ProgramProcessEvents, ProgramProcessExit, ProgramStartup, ProgramSql, ProgramStore, ProcessEvents, Publishable, System, SystemUploads, Upload, Size, Subscribable, SubscribableEvents, SubscribableFallback, TimedAskable, Timeoutable, Appearance, AppearanceEvents, AppearanceSource, AppearanceSurface, AnimationsPreference, DesktopPreferences, DesktopPreferencesEvents, DesktopPreferencesSource, DesktopPreferencesUpdate, Desktop, DesktopSize, DesktopSurfaceEvents, DesktopSurfaceSnapshot, DesktopSurfaceSource, WritableDesktopPreferencesSource, ThemedValue, Theme, ThemePreference, Value, WindowEvents, WindowGeometry, WindowLayer, WindowState, Easing, LocalWindow, LocalWindowOperations, Transaction } from "@phreshos/core";
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { system } from "./system.js";
|
|
2
|
-
export {} from "./desktop/desktop.js";
|
|
2
|
+
export { desktop } from "./desktop/desktop.js";
|
|
3
3
|
export { context } from "./context.js";
|
|
4
4
|
export { ClientService, ServerService, Service, } from "@phreshos/core";
|
|
5
|
-
export {
|
|
5
|
+
export { ClientEndpoint, Endpoint, Process, Program, ServerEndpoint } from "./domain.js";
|
package/dist/permissions.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
/** The one Program-owned permission capability visible in this isolated Client. */
|
|
10
|
-
export declare const currentProgramPermission: ClientPermission;
|
|
1
|
+
import type { ContextPermissions, ProgramPermissions } from "@phreshos/core";
|
|
2
|
+
import type { HandleAddress } from "./domain.js";
|
|
3
|
+
export declare const defaultPermissionTimeout = 120000;
|
|
4
|
+
/** Bind authoritative stored grants to one exact Program handle. */
|
|
5
|
+
export declare function programPermissions(program: HandleAddress): ProgramPermissions;
|
|
6
|
+
/** Stored grants and owner requests belonging to the current Client Endpoint. */
|
|
7
|
+
export declare function contextPermissions(): ContextPermissions;
|
package/dist/permissions.js
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
+
import { parsePermission, parsePermissionChange, parsePermissions } from "@phreshos/core";
|
|
1
2
|
import wire from "./wire.js";
|
|
2
|
-
const defaultPermissionTimeout =
|
|
3
|
-
/**
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
export const defaultPermissionTimeout = 120_000;
|
|
4
|
+
/** Bind authoritative stored grants to one exact Program handle. */
|
|
5
|
+
export function programPermissions(program) {
|
|
6
|
+
const operate = (operation, name, permission) => (wire.request(["program-permissions", program, operation, name, permission]));
|
|
7
|
+
return {
|
|
8
|
+
async get(name) { return parsePermission((await operate("get", name))[0]); },
|
|
9
|
+
async all() { return parsePermissions((await operate("all"))[0]); },
|
|
10
|
+
async set(name, permission) { return parsePermissionChange((await operate("set", name, permission))[0]); },
|
|
11
|
+
async delete(name) { return parsePermissionChange((await operate("delete", name))[0]); }
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Stored grants and owner requests belonging to the current Client Endpoint. */
|
|
15
|
+
export function contextPermissions() {
|
|
16
|
+
const timed = (timeout) => ({
|
|
17
|
+
async request(name, permission = true) {
|
|
18
|
+
const identity = crypto.randomUUID();
|
|
19
|
+
const result = await wire.requestOrNull(["context-permission-request", identity, name, permission], timeout);
|
|
20
|
+
return result === null
|
|
21
|
+
? Object.freeze({ permission: null, needReload: false })
|
|
22
|
+
: parsePermissionChange(result[0]);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
async get(name) {
|
|
27
|
+
return parsePermission((await wire.request(["context-permission-get", name]))[0]);
|
|
28
|
+
},
|
|
29
|
+
request: timed(defaultPermissionTimeout).request,
|
|
30
|
+
timeout(milliseconds) {
|
|
31
|
+
if (!Number.isFinite(milliseconds) || milliseconds < 0)
|
|
32
|
+
throw new Error("A permission timeout must be a non-negative finite number");
|
|
33
|
+
return timed(milliseconds);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
21
36
|
}
|
|
22
|
-
/** The one Program-owned permission capability visible in this isolated Client. */
|
|
23
|
-
export const currentProgramPermission = new ClientPermission();
|
package/dist/service.js
CHANGED
|
@@ -86,11 +86,11 @@ export function prepareService(key) {
|
|
|
86
86
|
}
|
|
87
87
|
function serviceEvents(key, scope) {
|
|
88
88
|
return [
|
|
89
|
-
(event, listener) => wire.followService(key, scope, event, listener),
|
|
90
|
-
(listener) => wire.followService(key, scope, null, (event, payload) => {
|
|
89
|
+
(event, listener, impossible) => wire.followService(key, scope, event, listener, impossible),
|
|
90
|
+
(listener, impossible) => wire.followService(key, scope, null, (event, payload) => {
|
|
91
91
|
if (typeof event === "string")
|
|
92
92
|
listener(event, payload);
|
|
93
|
-
})
|
|
93
|
+
}, impossible)
|
|
94
94
|
];
|
|
95
95
|
}
|
|
96
96
|
function bindEvents(target, events) {
|
package/dist/startup.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import wire from "./wire.js";
|
|
2
|
+
/** Bind persistent startup operations to one Program handle. */
|
|
3
|
+
export default function startup(program) {
|
|
4
|
+
return {
|
|
5
|
+
async get() {
|
|
6
|
+
const answer = await wire.request(["startup", program, "get"]);
|
|
7
|
+
return answer[0];
|
|
8
|
+
},
|
|
9
|
+
async enable(launch = {}) {
|
|
10
|
+
await wire.request(["startup", program, "enable", launch]);
|
|
11
|
+
},
|
|
12
|
+
async disable() {
|
|
13
|
+
await wire.request(["startup", program, "disable"]);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type { ProgramSql, ProgramStore, Storage } from "@phreshos/core";
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
1
|
+
import type { ProgramSql, ProgramStore, Storage as CoreStorage } from "@phreshos/core";
|
|
2
|
+
import type { HandleAddress } from "./domain.js";
|
|
3
|
+
export type Storage = CoreStorage;
|
|
4
|
+
/** Client-side access to one exact Program storage area. */
|
|
5
|
+
export declare function area(program: HandleAddress, which: "data" | "cache"): Storage;
|
|
6
|
+
export declare function store(program: HandleAddress): ProgramStore;
|
|
7
|
+
export declare function sql(kind: "database" | "logs", program: HandleAddress): ProgramSql;
|
|
8
|
+
/** Access to the System's native storage through the Client boundary. */
|
|
9
|
+
export declare function systemStorage(): Storage;
|
package/dist/storage.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { content } from "./content.js";
|
|
2
2
|
import controlledStream from "./controlled-stream.js";
|
|
3
3
|
import wire from "./wire.js";
|
|
4
|
-
/** Client-side
|
|
5
|
-
export function area(which) {
|
|
4
|
+
/** Client-side access to one exact Program storage area. */
|
|
5
|
+
export function area(program, which) {
|
|
6
6
|
async function ask(operation, ...values) {
|
|
7
|
-
const answer = await wire.request([which,
|
|
7
|
+
const answer = await wire.request([which, program, operation, ...values]);
|
|
8
8
|
return answer[0];
|
|
9
9
|
}
|
|
10
10
|
async function transfer(operation, path, body = null) {
|
|
@@ -12,7 +12,7 @@ export function area(which) {
|
|
|
12
12
|
const abort = () => channel.port1.postMessage("abort");
|
|
13
13
|
const close = () => channel.port1.close();
|
|
14
14
|
try {
|
|
15
|
-
const answer = await wire.request([which,
|
|
15
|
+
const answer = await wire.request([which, program, operation, path, body, channel.port2], undefined, body instanceof ReadableStream ? [body, channel.port2] : [channel.port2]);
|
|
16
16
|
if (operation === "write") {
|
|
17
17
|
close();
|
|
18
18
|
return null;
|
|
@@ -34,6 +34,8 @@ export function area(which) {
|
|
|
34
34
|
return body;
|
|
35
35
|
}
|
|
36
36
|
return {
|
|
37
|
+
path: () => ask("path"),
|
|
38
|
+
resolve: (...path) => ask("resolve", ...path),
|
|
37
39
|
stream,
|
|
38
40
|
async bytes(...path) { return new Uint8Array(await new Response(await stream(...path)).arrayBuffer()); },
|
|
39
41
|
async text(...path) { return new Response(await stream(...path)).text(); },
|
|
@@ -47,9 +49,9 @@ export function area(which) {
|
|
|
47
49
|
clear: (...path) => ask("clear", ...path)
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
|
-
export function store() {
|
|
52
|
+
export function store(program) {
|
|
51
53
|
async function ask(operation, ...values) {
|
|
52
|
-
const answer = await wire.request(["store",
|
|
54
|
+
const answer = await wire.request(["store", program, operation, ...values]);
|
|
53
55
|
return answer[0];
|
|
54
56
|
}
|
|
55
57
|
return {
|
|
@@ -60,13 +62,62 @@ export function store() {
|
|
|
60
62
|
clear: () => ask("clear")
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
|
-
export function sql(kind) {
|
|
65
|
+
export function sql(kind, program) {
|
|
64
66
|
return {
|
|
65
67
|
async query(statement, ...rest) {
|
|
66
68
|
const text = typeof statement === "string" ? statement : statement.raw.join("?");
|
|
67
69
|
const values = typeof statement === "string" ? (Array.isArray(rest[0]) ? rest[0] : []) : rest;
|
|
68
|
-
const answer = await wire.request([kind,
|
|
70
|
+
const answer = await wire.request([kind, program, text, values]);
|
|
69
71
|
return answer[0];
|
|
70
72
|
}
|
|
71
73
|
};
|
|
72
74
|
}
|
|
75
|
+
/** Access to the System's native storage through the Client boundary. */
|
|
76
|
+
export function systemStorage() {
|
|
77
|
+
async function ask(operation, ...values) {
|
|
78
|
+
const answer = await wire.request(["host-storage", operation, ...values]);
|
|
79
|
+
return answer[0];
|
|
80
|
+
}
|
|
81
|
+
async function transfer(operation, path, body = null) {
|
|
82
|
+
const channel = new MessageChannel();
|
|
83
|
+
const abort = () => channel.port1.postMessage("abort");
|
|
84
|
+
const close = () => channel.port1.close();
|
|
85
|
+
try {
|
|
86
|
+
const answer = await wire.request([`host-storage-${operation}`, path, body, channel.port2], undefined, body instanceof ReadableStream ? [body, channel.port2] : [channel.port2]);
|
|
87
|
+
if (operation === "write") {
|
|
88
|
+
close();
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (!(answer[0] instanceof ReadableStream))
|
|
92
|
+
throw new Error("The storage response has no byte stream");
|
|
93
|
+
return controlledStream(answer[0], abort, close);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
abort();
|
|
97
|
+
close();
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function stream(...path) {
|
|
102
|
+
const body = await transfer("stream", path);
|
|
103
|
+
if (!body)
|
|
104
|
+
throw new Error("The storage response has no body");
|
|
105
|
+
return body;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
path: () => ask("path"),
|
|
109
|
+
resolve: (...path) => ask("resolve", ...path),
|
|
110
|
+
stream,
|
|
111
|
+
async bytes(...path) { return new Uint8Array(await new Response(await stream(...path)).arrayBuffer()); },
|
|
112
|
+
async text(...path) { return new Response(await stream(...path)).text(); },
|
|
113
|
+
async json(...path) { return JSON.parse(await new Response(await stream(...path)).text()); },
|
|
114
|
+
async write(...args) {
|
|
115
|
+
const path = args.slice(0, -1);
|
|
116
|
+
await transfer("write", path, content(args.at(-1)).body);
|
|
117
|
+
},
|
|
118
|
+
stat: (...path) => ask("stat", ...path),
|
|
119
|
+
list: (...path) => ask("list", ...path),
|
|
120
|
+
delete: (...path) => ask("delete", ...path),
|
|
121
|
+
clear: (...path) => ask("clear", ...path)
|
|
122
|
+
};
|
|
123
|
+
}
|
package/dist/system.d.ts
CHANGED
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type ServiceAddress<Endpoint extends ServiceEndpoint> = Omit<ServiceKey, "endpoint"> & Readonly<{
|
|
5
|
-
endpoint: Endpoint;
|
|
6
|
-
}>;
|
|
7
|
-
type ServiceHandle<Endpoint extends ServiceEndpoint, Events extends object, Fallback = unknown> = Endpoint extends "server" ? ServerService<Events, Fallback> : ClientService<Events, Fallback>;
|
|
8
|
-
/** Desktop capabilities structurally available to a Client endpoint. */
|
|
9
|
-
export interface System {
|
|
10
|
-
/** Complete unresolved Appearance read from the System authority. */
|
|
11
|
-
readonly appearance: AppearanceSource;
|
|
12
|
-
/** Capabilities owned by the Desktop containing this Client. */
|
|
13
|
-
readonly desktop: SystemDesktop;
|
|
14
|
-
/** Flat System-owned public uploads capability. */
|
|
15
|
-
readonly uploads: SystemUploads;
|
|
16
|
-
/** Performs an unrestricted server-side fetch on behalf of this Client. */
|
|
17
|
-
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
18
|
-
/** Returns a precisely typed stable handle for either service endpoint. */
|
|
19
|
-
service<Endpoint extends ServiceEndpoint>(key: ServiceAddress<Endpoint>): ServiceHandle<Endpoint, {}>;
|
|
20
|
-
/** Returns a typed stable handle for one exact Server service identity. */
|
|
21
|
-
service<ServiceEvents extends object, Fallback = unknown>(key: ServiceAddress<"server">): ServerService<ServiceEvents, Fallback>;
|
|
22
|
-
/** Returns a typed stable handle for one exact Client service identity. */
|
|
23
|
-
service<ServiceEvents extends object, Fallback = unknown>(key: ServiceAddress<"client">): ClientService<ServiceEvents, Fallback>;
|
|
24
|
-
}
|
|
25
|
-
/** Desktop capabilities available to this Client. */
|
|
26
|
-
export declare const system: System;
|
|
27
|
-
export {};
|
|
1
|
+
import { type System as CoreSystem } from "@phreshos/core";
|
|
2
|
+
/** The global System represented through this Client runtime. */
|
|
3
|
+
export declare const system: CoreSystem;
|