@phreshos/client 0.1.33 → 0.1.35
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 +31 -55
- package/dist/domain.d.ts +2 -2
- package/dist/domain.js +2 -2
- package/dist/main.d.ts +2 -2
- package/dist/main.js +1 -1
- package/dist/permissions.js +5 -5
- package/dist/system.js +4 -0
- package/dist/websocket.d.ts +2 -0
- package/dist/websocket.js +13 -0
- package/dist/wire.js +1 -1
- package/package.json +4 -4
- package/dist/messagepack.d.ts +0 -3
- package/dist/messagepack.js +0 -130
package/README.md
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
# `@phreshos/client`
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The runtime adapter for a PhreshOS Program's Client Endpoint.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
[Documentation](https://docs.phreshos.com/sdks/client) ·
|
|
6
|
+
[Client Context](https://docs.phreshos.com/runtime/context) ·
|
|
7
|
+
[Desktop](https://docs.phreshos.com/system/desktop) ·
|
|
8
|
+
[Source](https://github.com/PhreshOS/client)
|
|
9
|
+
|
|
10
|
+
## Role
|
|
11
|
+
|
|
12
|
+
The Client SDK exposes three separate Core contracts inside a Client Endpoint:
|
|
13
|
+
the global `system`, the current Client `context`, and the containing `desktop`.
|
|
14
|
+
It adapts the Desktop boundary without defining client-specific versions of the
|
|
15
|
+
shared Program, Process, Endpoint, or Service domains.
|
|
16
|
+
|
|
17
|
+
The System enforces Client authority. The SDK carries requests and preserves
|
|
18
|
+
canonical handles; it does not own authoritative state or visual components.
|
|
8
19
|
|
|
9
20
|
## Installation
|
|
10
21
|
|
|
@@ -17,55 +28,16 @@ current Client `context`, and the Client's `desktop` environment.
|
|
|
17
28
|
|
|
18
29
|
`@phreshos/core` is a peer dependency.
|
|
19
30
|
|
|
20
|
-
## Context
|
|
21
|
-
|
|
22
31
|
```ts
|
|
23
|
-
import { context } from "@phreshos/client"
|
|
24
|
-
|
|
25
|
-
context.subscribe("changed", message => {
|
|
26
|
-
console.log(message)
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
context.publish("changed", { value: 1 })
|
|
32
|
+
import { context, desktop, system } from "@phreshos/client"
|
|
30
33
|
|
|
31
34
|
const program = await context.program()
|
|
32
|
-
const process = await context.process()
|
|
33
|
-
const server = context.server
|
|
34
|
-
const position = await context.window.position()
|
|
35
|
-
await context.localWindow.move({ x: 20, y: 20 })
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
`context` belongs to the executing Client. It provides communication,
|
|
39
|
-
navigation to its Program and Process, its paired Server, the authoritative
|
|
40
|
-
current Window through `window`, and command-only control of the current
|
|
41
|
-
Desktop representation through `localWindow`.
|
|
42
|
-
|
|
43
|
-
## System
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import { system } from "@phreshos/client"
|
|
47
|
-
|
|
48
|
-
const appearance = await system.appearance.snapshot()
|
|
49
|
-
const programs = await system.program.list()
|
|
50
|
-
const processes = await system.process.list()
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
`system` is the complete global System contract sourced from Core.
|
|
54
|
-
|
|
55
|
-
## Desktop
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
import { desktop } from "@phreshos/client"
|
|
59
|
-
|
|
60
|
-
const surface = await desktop.surface.snapshot()
|
|
61
35
|
const preferences = await desktop.preferences.snapshot()
|
|
36
|
+
const appearance = await system.appearance.snapshot()
|
|
62
37
|
```
|
|
63
38
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Requests read current state. Subscriptions observe future publications and do
|
|
68
|
-
not replay an initial value. Importing the SDK performs neither operation.
|
|
39
|
+
See [Client SDK](https://docs.phreshos.com/sdks/client) for the complete entry
|
|
40
|
+
points and authority boundary.
|
|
69
41
|
|
|
70
42
|
## Development
|
|
71
43
|
|
|
@@ -74,17 +46,21 @@ bun install --frozen-lockfile
|
|
|
74
46
|
bun run verify
|
|
75
47
|
```
|
|
76
48
|
|
|
77
|
-
`verify` checks the
|
|
78
|
-
shape.
|
|
49
|
+
`verify` checks the types and completions, builds the package, and validates its
|
|
50
|
+
published shape.
|
|
79
51
|
|
|
80
|
-
|
|
81
|
-
for the shared model and authority boundary.
|
|
52
|
+
## Related repositories
|
|
82
53
|
|
|
83
|
-
|
|
54
|
+
- [`@phreshos/core`](https://github.com/PhreshOS/core) owns every shared
|
|
55
|
+
contract and domain class exposed here.
|
|
56
|
+
- [`@phreshos/server`](https://github.com/PhreshOS/server) adapts the paired
|
|
57
|
+
Server Endpoint boundary.
|
|
58
|
+
- [`@phreshos/react`](https://github.com/PhreshOS/react) adapts the Client
|
|
59
|
+
sources to React without depending on this package.
|
|
60
|
+
- [PhreshOS System](https://github.com/PhreshOS/system) owns enforcement,
|
|
61
|
+
routing, and the Desktop host.
|
|
84
62
|
|
|
85
|
-
|
|
86
|
-
System owns enforcement and forwarding, React owns framework adaptation, and
|
|
87
|
-
React UI owns visual interpretation.
|
|
63
|
+
## Contributing
|
|
88
64
|
|
|
89
65
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for the repository workflow and
|
|
90
66
|
[SECURITY.md](SECURITY.md) for private vulnerability reporting.
|
package/dist/domain.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type 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 LocalWindow, type
|
|
1
|
+
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type AnswerOutcome, type AnswerSubscriber as CoreAnswerSubscriber, type AskCapture as CoreAskCapture, type AskMessage as CoreAskMessage, type AskSubscriber as CoreAskSubscriber, type Cleanup, type ClientTraffic as CoreClientTraffic, type ClientDeclaration, type EndpointTraffic as CoreEndpointTraffic, type Exit, type EventOptions, type LocalWindow, type Position, type ProgramProcess as CoreProgramProcess, type ProgramProcessRunEvent as CoreProgramProcessRunEvent, type ProgramProcessRunOptions as CoreProgramProcessRunOptions, 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;
|
|
@@ -101,7 +101,7 @@ export declare class ServerTrafficHandle extends TrafficHandle {
|
|
|
101
101
|
questionId: string;
|
|
102
102
|
message: Readonly<{
|
|
103
103
|
to: Endpoint<{}, unknown> | null;
|
|
104
|
-
outcome:
|
|
104
|
+
outcome: AnswerOutcome<unknown>;
|
|
105
105
|
}>;
|
|
106
106
|
}>>;
|
|
107
107
|
private followAnswers;
|
package/dist/domain.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint } from "@phreshos/core";
|
|
1
|
+
import { ClientEndpoint as CoreClientEndpoint, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, ServerEndpoint as CoreServerEndpoint, parseClientPermissions } 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";
|
|
@@ -106,7 +106,7 @@ function clientDeclaration(record) {
|
|
|
106
106
|
position: record.position,
|
|
107
107
|
layer: record.layer,
|
|
108
108
|
minimize: record.minimize,
|
|
109
|
-
permissions:
|
|
109
|
+
permissions: parseClientPermissions(record.permissions)
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
class ProgramProcessHandle {
|
package/dist/main.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { system } from "./system.js";
|
|
2
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
|
-
export { ClientService, ServerService, Service, type ServiceKey, } from "@phreshos/core";
|
|
4
|
+
export { ClientService, ServerService, Service, clientPermissionCatalog, isPermissionName, type ServiceKey, } from "@phreshos/core";
|
|
5
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,
|
|
6
|
+
export type { Askable, AnswerOutcome, 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, Permission, PermissionChange, PermissionDefinition, PermissionDefinitions, PermissionInput, PermissionName, PermissionRequest, PermissionValue, PermissionValueDomain, 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
2
|
export { desktop } from "./desktop/desktop.js";
|
|
3
3
|
export { context } from "./context.js";
|
|
4
|
-
export { ClientService, ServerService, Service, } from "@phreshos/core";
|
|
4
|
+
export { ClientService, ServerService, Service, clientPermissionCatalog, isPermissionName, } from "@phreshos/core";
|
|
5
5
|
export { ClientEndpoint, Endpoint, Process, Program, ServerEndpoint } from "./domain.js";
|
package/dist/permissions.js
CHANGED
|
@@ -5,10 +5,10 @@ export const defaultPermissionTimeout = 120_000;
|
|
|
5
5
|
export function programPermissions(program) {
|
|
6
6
|
const operate = (operation, name, permission) => (wire.request(["program-permissions", program, operation, name, permission]));
|
|
7
7
|
return {
|
|
8
|
-
async get(name) { return parsePermission((await operate("get", name))[0]); },
|
|
8
|
+
async get(name) { return parsePermission(name, (await operate("get", name))[0]); },
|
|
9
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]); }
|
|
10
|
+
async set(name, permission) { return parsePermissionChange(name, (await operate("set", name, permission))[0]); },
|
|
11
|
+
async delete(name) { return parsePermissionChange(name, (await operate("delete", name))[0]); }
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
/** Stored grants and owner requests belonging to the current Client Endpoint. */
|
|
@@ -19,12 +19,12 @@ export function contextPermissions() {
|
|
|
19
19
|
const result = await wire.requestOrNull(["context-permission-request", identity, name, permission], timeout);
|
|
20
20
|
return result === null
|
|
21
21
|
? Object.freeze({ permission: null, needReload: false })
|
|
22
|
-
: parsePermissionChange(result[0]);
|
|
22
|
+
: parsePermissionChange(name, result[0]);
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
return {
|
|
26
26
|
async get(name) {
|
|
27
|
-
return parsePermission((await wire.request(["context-permission-get", name]))[0]);
|
|
27
|
+
return parsePermission(name, (await wire.request(["context-permission-get", name]))[0]);
|
|
28
28
|
},
|
|
29
29
|
request: timed(defaultPermissionTimeout).request,
|
|
30
30
|
timeout(milliseconds) {
|
package/dist/system.js
CHANGED
|
@@ -7,6 +7,7 @@ import controlledStream from "./controlled-stream.js";
|
|
|
7
7
|
import Events from "./events.js";
|
|
8
8
|
import { exit, process, program } from "./domain.js";
|
|
9
9
|
import { systemStorage } from "./storage.js";
|
|
10
|
+
import websocket from "./websocket.js";
|
|
10
11
|
class ClientSystem {
|
|
11
12
|
storage = systemStorage();
|
|
12
13
|
appearance = new ClientAppearance();
|
|
@@ -73,6 +74,9 @@ class ClientSystem {
|
|
|
73
74
|
});
|
|
74
75
|
return response;
|
|
75
76
|
}
|
|
77
|
+
websocket(url, protocols) {
|
|
78
|
+
return websocket(url, protocols);
|
|
79
|
+
}
|
|
76
80
|
async *shell(command, options = {}) {
|
|
77
81
|
const { signal, ...settings } = options;
|
|
78
82
|
for await (const event of wire.stream(["shell", command, settings], undefined, signal))
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import wire from "./wire.js";
|
|
2
|
+
/** Acquire permission, then open the browser's native WebSocket. */
|
|
3
|
+
export default async function websocket(url, protocols) {
|
|
4
|
+
const address = new URL(String(url), document.baseURI);
|
|
5
|
+
if (address.protocol === "http:")
|
|
6
|
+
address.protocol = "ws:";
|
|
7
|
+
if (address.protocol === "https:")
|
|
8
|
+
address.protocol = "wss:";
|
|
9
|
+
await wire.request(["websocket", address.href, protocols]);
|
|
10
|
+
return protocols === undefined
|
|
11
|
+
? new WebSocket(address.href)
|
|
12
|
+
: new WebSocket(address.href, protocols);
|
|
13
|
+
}
|
package/dist/wire.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Deadline from "./deadline.js";
|
|
2
2
|
import { defaultTimeout } from "./events.js";
|
|
3
3
|
import captureClientOutput from "./log.js";
|
|
4
|
-
import { deserialize, serialize } from "
|
|
4
|
+
import { deserialize, serialize } from "@the-link/messagepack";
|
|
5
5
|
/** The client endpoint's sole postMessage adapter. */
|
|
6
6
|
class Wire {
|
|
7
7
|
parent = window.parent === window ? null : window.parent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
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.39"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@
|
|
53
|
+
"@the-link/messagepack": "^0.1.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@phreshos/core": "^0.1.
|
|
56
|
+
"@phreshos/core": "^0.1.39",
|
|
57
57
|
"typescript": "^6.0.3"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/dist/messagepack.d.ts
DELETED
package/dist/messagepack.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { decode, encode, ExtensionCodec } from "@msgpack/msgpack";
|
|
2
|
-
class Attachment {
|
|
3
|
-
index;
|
|
4
|
-
constructor(index) {
|
|
5
|
-
this.index = index;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
class BigInteger {
|
|
9
|
-
value;
|
|
10
|
-
constructor(value) {
|
|
11
|
-
this.value = value;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
class Undefined {
|
|
15
|
-
}
|
|
16
|
-
const textEncoder = new TextEncoder();
|
|
17
|
-
const textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
18
|
-
const extensions = new ExtensionCodec();
|
|
19
|
-
const serializePrepared = (value, context) => encode(value, { context, extensionCodec: extensions });
|
|
20
|
-
const deserializePrepared = (bytes, context) => decode(bytes, { context, extensionCodec: extensions });
|
|
21
|
-
extensions.register({
|
|
22
|
-
type: 0,
|
|
23
|
-
encode: value => value instanceof Attachment ? uint32(value.index) : null,
|
|
24
|
-
decode: (bytes, _type, context) => {
|
|
25
|
-
const attachment = context.incoming?.[readUint32(bytes)];
|
|
26
|
-
if (attachment === undefined)
|
|
27
|
-
throw new Error("The MessagePack attachment is absent");
|
|
28
|
-
return attachment;
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
extensions.register({
|
|
32
|
-
type: 1,
|
|
33
|
-
encode: (value, context) => value instanceof Map ? serializePrepared([...value], context) : null,
|
|
34
|
-
decode: (bytes, _type, context) => new Map(deserializePrepared(bytes, context))
|
|
35
|
-
});
|
|
36
|
-
extensions.register({
|
|
37
|
-
type: 2,
|
|
38
|
-
encode: (value, context) => value instanceof Set ? serializePrepared([...value], context) : null,
|
|
39
|
-
decode: (bytes, _type, context) => new Set(deserializePrepared(bytes, context))
|
|
40
|
-
});
|
|
41
|
-
extensions.register({
|
|
42
|
-
type: 3,
|
|
43
|
-
encode: (value, context) => value instanceof RegExp ? serializePrepared([value.source, value.flags, value.lastIndex], context) : null,
|
|
44
|
-
decode: (bytes, _type, context) => {
|
|
45
|
-
const [source, flags, lastIndex] = deserializePrepared(bytes, context);
|
|
46
|
-
const expression = new RegExp(source, flags);
|
|
47
|
-
expression.lastIndex = lastIndex;
|
|
48
|
-
return expression;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
extensions.register({
|
|
52
|
-
type: 4,
|
|
53
|
-
encode: value => value instanceof URL ? textEncoder.encode(value.href) : null,
|
|
54
|
-
decode: bytes => new URL(textDecoder.decode(bytes))
|
|
55
|
-
});
|
|
56
|
-
extensions.register({
|
|
57
|
-
type: 5,
|
|
58
|
-
encode: (value, context) => value instanceof Error ? serializePrepared(prepare({
|
|
59
|
-
cause: value.cause,
|
|
60
|
-
message: value.message,
|
|
61
|
-
name: value.name,
|
|
62
|
-
stack: value.stack
|
|
63
|
-
}, context), context) : null,
|
|
64
|
-
decode: (bytes, _type, context) => {
|
|
65
|
-
const value = deserializePrepared(bytes, context);
|
|
66
|
-
const error = new Error(value.message, { cause: value.cause });
|
|
67
|
-
error.name = value.name;
|
|
68
|
-
if (value.stack !== undefined)
|
|
69
|
-
error.stack = value.stack;
|
|
70
|
-
return error;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
extensions.register({
|
|
74
|
-
type: 6,
|
|
75
|
-
encode: value => value instanceof BigInteger ? textEncoder.encode(value.value.toString()) : null,
|
|
76
|
-
decode: bytes => BigInt(textDecoder.decode(bytes))
|
|
77
|
-
});
|
|
78
|
-
extensions.register({
|
|
79
|
-
type: 7,
|
|
80
|
-
encode: value => value instanceof Undefined ? new Uint8Array() : null,
|
|
81
|
-
decode: () => undefined
|
|
82
|
-
});
|
|
83
|
-
export const serialize = (value, attachments = []) => {
|
|
84
|
-
const outgoing = new Map(attachments.map((attachment, index) => [attachment, index]));
|
|
85
|
-
const context = { outgoing };
|
|
86
|
-
return serializePrepared(prepare(value, context), context);
|
|
87
|
-
};
|
|
88
|
-
export const deserialize = (bytes, attachments = []) => {
|
|
89
|
-
return deserializePrepared(bytes, { incoming: attachments });
|
|
90
|
-
};
|
|
91
|
-
const prepare = (value, context) => {
|
|
92
|
-
if (value === undefined)
|
|
93
|
-
return new Undefined();
|
|
94
|
-
if (typeof value === "bigint")
|
|
95
|
-
return new BigInteger(value);
|
|
96
|
-
if (typeof value === "function" || typeof value === "symbol")
|
|
97
|
-
return null;
|
|
98
|
-
if (value === null || typeof value !== "object")
|
|
99
|
-
return value;
|
|
100
|
-
const attachment = context.outgoing?.get(value);
|
|
101
|
-
if (attachment !== undefined)
|
|
102
|
-
return new Attachment(attachment);
|
|
103
|
-
if (value instanceof Date || value instanceof RegExp || value instanceof URL || value instanceof Error)
|
|
104
|
-
return value;
|
|
105
|
-
if (value instanceof ArrayBuffer)
|
|
106
|
-
return new Uint8Array(value);
|
|
107
|
-
if (ArrayBuffer.isView(value))
|
|
108
|
-
return Uint8Array.from(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
109
|
-
if (value instanceof Map)
|
|
110
|
-
return new Map([...value].map(([key, entry]) => [prepare(key, context), prepare(entry, context)]));
|
|
111
|
-
if (value instanceof Set)
|
|
112
|
-
return new Set([...value].map(entry => prepare(entry, context)));
|
|
113
|
-
if (Array.isArray(value))
|
|
114
|
-
return value.map(entry => prepare(entry, context));
|
|
115
|
-
if ("toJSON" in value && typeof value.toJSON === "function")
|
|
116
|
-
return prepare(value.toJSON(), context);
|
|
117
|
-
return Object.fromEntries(Object.entries(value)
|
|
118
|
-
.filter(([, entry]) => typeof entry !== "function")
|
|
119
|
-
.map(([key, entry]) => [key, prepare(entry, context)]));
|
|
120
|
-
};
|
|
121
|
-
const uint32 = (value) => {
|
|
122
|
-
const bytes = new Uint8Array(4);
|
|
123
|
-
new DataView(bytes.buffer).setUint32(0, value);
|
|
124
|
-
return bytes;
|
|
125
|
-
};
|
|
126
|
-
const readUint32 = (bytes) => {
|
|
127
|
-
if (bytes.byteLength !== 4)
|
|
128
|
-
throw new Error("The MessagePack attachment reference is invalid");
|
|
129
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);
|
|
130
|
-
};
|