opentray 0.5.2 → 0.7.0

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.
@@ -0,0 +1,102 @@
1
+ import { ClientFrame, ClientRequestFrame, ExtensionEnvelope, Icon, Menu, RequestId, ServerFrame, SpaceOptions, SpaceRef, Tooltip, TrayBoundsResult, TrayEvent, TrayId, TrayOptions } from "@opentray/spec";
2
+
3
+ //#region src/client.d.ts
4
+ interface OpenTrayTransport {
5
+ request(frame: ClientRequestFrame): Promise<ServerFrame>;
6
+ }
7
+ type BrokerEventFrame = Extract<ServerFrame, {
8
+ type: "event" | "ext-event";
9
+ }>;
10
+ interface OpenTrayEventSource {
11
+ onEvent(listener: (frame: BrokerEventFrame) => void): () => void;
12
+ }
13
+ interface OpenTrayConnection extends OpenTrayTransport, OpenTrayEventSource {}
14
+ interface OpenTrayClient {
15
+ createSpace(options: SpaceOptions): Promise<SpaceHandle>;
16
+ resolveDefaultSpace(): Promise<SpaceHandle>;
17
+ /** @deprecated Use `createSpace`. */
18
+ createSurface(options: SpaceOptions): Promise<SpaceHandle>;
19
+ }
20
+ interface SpaceHandle {
21
+ space: SpaceRef;
22
+ createTray(options: TrayOptions): Promise<TrayHandle>;
23
+ }
24
+ interface EventfulSpaceHandle extends Omit<SpaceHandle, "createTray"> {
25
+ createTray(options: TrayOptions): Promise<EventfulTrayHandle>;
26
+ }
27
+ /** @deprecated Use `SpaceHandle`. */
28
+ type SurfaceHandle = SpaceHandle;
29
+ interface TrayHandle {
30
+ space: SpaceRef;
31
+ trayId: TrayId;
32
+ getBounds(): Promise<TrayBoundsResult>;
33
+ setMenu(menu: Menu): Promise<void>;
34
+ setTooltip(tooltip: Tooltip): Promise<void>;
35
+ setIcon(icon: Icon): Promise<void>;
36
+ setTitle(title: string): Promise<void>;
37
+ loadExtension(options: ExtensionLoadOptions): Promise<void>;
38
+ commandExtension(ext: string, data: unknown): Promise<void>;
39
+ requestExtension(ext: string, data: unknown): Promise<ExtensionEnvelope[]>;
40
+ extend<TCapability extends object, TOptions = undefined>(extension: TrayExtension<TCapability, TOptions>, options?: TOptions): TrayHandle & TCapability;
41
+ destroy(): Promise<void>;
42
+ }
43
+ type TrayScopedEvent = Exclude<TrayEvent, {
44
+ type: "ready";
45
+ }>;
46
+ type TrayEventType = TrayScopedEvent["type"];
47
+ type TrayEventByType<TEvent extends TrayEventType> = Extract<TrayScopedEvent, {
48
+ type: TEvent;
49
+ }>;
50
+ interface EventfulTrayHandle extends TrayHandle {
51
+ extend<TCapability extends object, TOptions = undefined>(extension: TrayExtension<TCapability, TOptions>, options?: TOptions): EventfulTrayHandle & TCapability;
52
+ listenExtension<TData = unknown>(ext: string, handler: (event: ExtensionEnvelope<TData>) => void): () => void;
53
+ listen<TEvent extends TrayEventType>(event: TEvent, handler: (event: TrayEventByType<TEvent>) => void): () => void;
54
+ onMenuClick(handler: (event: TrayEventByType<"menuClick">) => void): () => void;
55
+ onTrayClick(handler: (event: TrayEventByType<"trayClick">) => void): () => void;
56
+ onTrayDoubleClick(handler: (event: TrayEventByType<"trayDoubleClick">) => void): () => void;
57
+ }
58
+ interface ExtensionLoadOptions {
59
+ name: string;
60
+ path: string;
61
+ mountId?: string;
62
+ }
63
+ interface TrayExtensionMountSpec {
64
+ name?: string;
65
+ path?: string;
66
+ mountId?: string;
67
+ }
68
+ interface TrayExtensionContext {
69
+ readonly name: string;
70
+ readonly path: string;
71
+ readonly mountId: string;
72
+ ensureLoaded(): Promise<void>;
73
+ command(data: unknown): Promise<void>;
74
+ request(data: unknown): Promise<ExtensionEnvelope[]>;
75
+ }
76
+ interface TrayExtension<TCapability extends object, TOptions = undefined> {
77
+ readonly name: string;
78
+ readonly path: string;
79
+ resolveMount?(options: TOptions | undefined): TrayExtensionMountSpec;
80
+ extend(tray: TrayHandle, context: TrayExtensionContext, options: TOptions | undefined): TCapability;
81
+ }
82
+ declare const createInitFrame: (clientVersion: string) => ClientFrame;
83
+ interface CreateClientOptions {
84
+ requestIdPrefix?: string;
85
+ }
86
+ interface OpenTrayEventfulClient extends Omit<OpenTrayClient, "createSpace" | "resolveDefaultSpace" | "createSurface"> {
87
+ createSpace(options: SpaceOptions): Promise<EventfulSpaceHandle>;
88
+ resolveDefaultSpace(): Promise<EventfulSpaceHandle>;
89
+ /** @deprecated Use `createSpace`. */
90
+ createSurface(options: SpaceOptions): Promise<EventfulSpaceHandle>;
91
+ }
92
+ declare function createClient(transport: OpenTrayConnection, options?: CreateClientOptions): OpenTrayEventfulClient;
93
+ declare function createClient(transport: OpenTrayTransport, options?: CreateClientOptions): OpenTrayClient;
94
+ declare function createSpaceHandle(transport: OpenTrayConnection, space: SpaceRef, nextRequestId?: () => RequestId): EventfulSpaceHandle;
95
+ declare function createSpaceHandle(transport: OpenTrayTransport, space: SpaceRef, nextRequestId?: () => RequestId): SpaceHandle;
96
+ /** @deprecated Use `createSpaceHandle`. */
97
+ declare const createSurfaceHandle: typeof createSpaceHandle;
98
+ declare function createTrayHandle(transport: OpenTrayConnection, space: SpaceRef, trayId: TrayId, nextRequestId?: () => RequestId): EventfulTrayHandle;
99
+ declare function createTrayHandle(transport: OpenTrayTransport, space: SpaceRef, trayId: TrayId, nextRequestId?: () => RequestId): TrayHandle;
100
+ //#endregion
101
+ export { createTrayHandle as C, createSurfaceHandle as S, TrayExtensionMountSpec as _, ExtensionLoadOptions as a, createInitFrame as b, OpenTrayEventSource as c, SpaceHandle as d, SurfaceHandle as f, TrayExtensionContext as g, TrayExtension as h, EventfulTrayHandle as i, OpenTrayEventfulClient as l, TrayEventType as m, CreateClientOptions as n, OpenTrayClient as o, TrayEventByType as p, EventfulSpaceHandle as r, OpenTrayConnection as s, BrokerEventFrame as t, OpenTrayTransport as u, TrayHandle as v, createSpaceHandle as x, createClient as y };
102
+ //# sourceMappingURL=client-C27qmRfr.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-C27qmRfr.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;UAkBiB,iBAAA;EACf,OAAA,CAAQ,KAAA,EAAO,kBAAA,GAAqB,OAAA,CAAQ,WAAA;AAAA;AAAA,KAGlC,gBAAA,GAAmB,OAAO,CAAC,WAAA;EAAe,IAAA;AAAA;AAAA,UAErC,mBAAA;EACf,OAAA,CAAQ,QAAA,GAAW,KAAA,EAAO,gBAAgB;AAAA;AAAA,UAG3B,kBAAA,SAA2B,iBAAA,EAAmB,mBAAmB;AAAA,UAEjE,cAAA;EACf,WAAA,CAAY,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,WAAA;EAC5C,mBAAA,IAAuB,OAAA,CAAQ,WAAA;EAba;EAe5C,aAAA,CAAc,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,WAAA;AAAA;AAAA,UAG/B,WAAA;EACf,KAAA,EAAO,QAAA;EACP,UAAA,CAAW,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,UAAA;AAAA;AAAA,UAG3B,mBAAA,SAA4B,IAAA,CAAK,WAAA;EAChD,UAAA,CAAW,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,kBAAA;AAAA;;KAIhC,aAAA,GAAgB,WAAW;AAAA,UAEtB,UAAA;EACf,KAAA,EAAO,QAAA;EACP,MAAA,EAAQ,MAAA;EACR,SAAA,IAAa,OAAA,CAAQ,gBAAA;EACrB,OAAA,CAAQ,IAAA,EAAM,IAAA,GAAO,OAAA;EACrB,UAAA,CAAW,OAAA,EAAS,OAAA,GAAU,OAAA;EAC9B,OAAA,CAAQ,IAAA,EAAM,IAAA,GAAO,OAAA;EACrB,QAAA,CAAS,KAAA,WAAgB,OAAA;EACzB,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA;EAC9C,gBAAA,CAAiB,GAAA,UAAa,IAAA,YAAgB,OAAA;EAC9C,gBAAA,CAAiB,GAAA,UAAa,IAAA,YAAgB,OAAA,CAAQ,iBAAA;EACtD,MAAA,mDACE,SAAA,EAAW,aAAA,CAAc,WAAA,EAAa,QAAA,GACtC,OAAA,GAAU,QAAA,GACT,UAAA,GAAa,WAAA;EAChB,OAAA,IAAW,OAAA;AAAA;AAAA,KAGD,eAAA,GAAkB,OAAO,CAAC,SAAA;EAAa,IAAA;AAAA;AAAA,KACvC,aAAA,GAAgB,eAAe;AAAA,KAC/B,eAAA,gBAA+B,aAAA,IAAiB,OAAA,CAAQ,eAAA;EAAmB,IAAA,EAAM,MAAA;AAAA;AAAA,UAE5E,kBAAA,SAA2B,UAAA;EAC1C,MAAA,mDACE,SAAA,EAAW,aAAA,CAAc,WAAA,EAAa,QAAA,GACtC,OAAA,GAAU,QAAA,GACT,kBAAA,GAAqB,WAAA;EACxB,eAAA,kBACE,GAAA,UACA,OAAA,GAAU,KAAA,EAAO,iBAAA,CAAkB,KAAA;EAErC,MAAA,gBAAsB,aAAA,EACpB,KAAA,EAAO,MAAA,EACP,OAAA,GAAU,KAAA,EAAO,eAAA,CAAgB,MAAA;EAEnC,WAAA,CAAY,OAAA,GAAU,KAAA,EAAO,eAAA;EAC7B,WAAA,CAAY,OAAA,GAAU,KAAA,EAAO,eAAA;EAC7B,iBAAA,CAAkB,OAAA,GAAU,KAAA,EAAO,eAAA;AAAA;AAAA,UAGpB,oBAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,sBAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,oBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA;EACT,YAAA,IAAgB,OAAA;EAChB,OAAA,CAAQ,IAAA,YAAgB,OAAA;EACxB,OAAA,CAAQ,IAAA,YAAgB,OAAA,CAAQ,iBAAA;AAAA;AAAA,UAGjB,aAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EACT,YAAA,EAAc,OAAA,EAAS,QAAA,eAAuB,sBAAA;EAC9C,MAAA,CAAO,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,oBAAA,EAAsB,OAAA,EAAS,QAAA,eAAuB,WAAA;AAAA;AAAA,cAG7E,eAAA,GAAmB,aAAA,aAAwB,WAItD;AAAA,UAEe,mBAAA;EACf,eAAe;AAAA;AAAA,UAGA,sBAAA,SAA+B,IAAA,CAAK,cAAA;EACnD,WAAA,CAAY,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,mBAAA;EAC5C,mBAAA,IAAuB,OAAA,CAAQ,mBAAA;EA1FqB;EA4FpD,aAAA,CAAc,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,mBAAA;AAAA;AAAA,iBAGhC,YAAA,CACd,SAAA,EAAW,kBAAA,EACX,OAAA,GAAU,mBAAA,GACT,sBAAA;AAAA,iBACa,YAAA,CAAa,SAAA,EAAW,iBAAA,EAAmB,OAAA,GAAU,mBAAA,GAAsB,cAAA;AAAA,iBAiC3E,iBAAA,CACd,SAAA,EAAW,kBAAA,EACX,KAAA,EAAO,QAAA,EACP,aAAA,SAAsB,SAAA,GACrB,mBAAA;AAAA,iBACa,iBAAA,CACd,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,aAAA,SAAsB,SAAA,GACrB,WAAA;;cAuBU,mBAAA,SAAmB,iBAAoB;AAAA,iBAEpC,gBAAA,CACd,SAAA,EAAW,kBAAA,EACX,KAAA,EAAO,QAAA,EACP,MAAA,EAAQ,MAAA,EACR,aAAA,SAAsB,SAAA,GACrB,kBAAA;AAAA,iBACa,gBAAA,CACd,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,MAAA,EAAQ,MAAA,EACR,aAAA,SAAsB,SAAA,GACrB,UAAA"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SpaceHandle, c as TrayExtensionContext, d as createClient, f as createInitFrame, h as createTrayHandle, i as OpenTrayTransport, l as TrayExtensionMountSpec, m as createSurfaceHandle, n as ExtensionLoadOptions, o as SurfaceHandle, p as createSpaceHandle, r as OpenTrayClient, s as TrayExtension, t as CreateClientOptions, u as TrayHandle } from "./client-DQn3DLZw.mjs";
1
+ import { C as createTrayHandle, S as createSurfaceHandle, _ as TrayExtensionMountSpec, a as ExtensionLoadOptions, b as createInitFrame, c as OpenTrayEventSource, d as SpaceHandle, f as SurfaceHandle, g as TrayExtensionContext, h as TrayExtension, i as EventfulTrayHandle, l as OpenTrayEventfulClient, m as TrayEventType, n as CreateClientOptions, o as OpenTrayClient, p as TrayEventByType, r as EventfulSpaceHandle, s as OpenTrayConnection, t as BrokerEventFrame, u as OpenTrayTransport, v as TrayHandle, x as createSpaceHandle, y as createClient } from "./client-C27qmRfr.mjs";
2
2
  import { BrokerEndpointIdentity, BrokerEndpointIdentityOptions, PROTOCOL_VERSION, SpaceOptions, SpaceRef, TrayOptions, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
3
3
 
4
4
  //#region src/sdk.d.ts
@@ -13,11 +13,11 @@ interface BrokerConnectOptions {
13
13
  interface CreateTrayOptions extends BrokerConnectOptions {
14
14
  space?: SpaceRef;
15
15
  }
16
- declare const createSpace: (options: SpaceOptions, brokerOptions?: BrokerConnectOptions) => Promise<SpaceHandle>;
16
+ declare const createSpace: (options: SpaceOptions, brokerOptions?: BrokerConnectOptions) => Promise<EventfulSpaceHandle>;
17
17
  /** @deprecated Use `createSpace`. */
18
18
  declare const createSurface: (options: SpaceOptions, brokerOptions?: BrokerConnectOptions) => Promise<SurfaceHandle>;
19
- declare const resolveDefaultSpace: (brokerOptions?: BrokerConnectOptions) => Promise<SpaceHandle>;
20
- declare const createTray: (options: TrayOptions, brokerOptions?: CreateTrayOptions) => Promise<TrayHandle>;
19
+ declare const resolveDefaultSpace: (brokerOptions?: BrokerConnectOptions) => Promise<EventfulSpaceHandle>;
20
+ declare const createTray: (options: TrayOptions, brokerOptions?: CreateTrayOptions) => Promise<EventfulTrayHandle>;
21
21
  //#endregion
22
- export { type BrokerConnectOptions, type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type CreateClientOptions, type CreateTrayOptions, type ExtensionLoadOptions, type OpenTrayClient, type OpenTrayTransport, PROTOCOL_VERSION, type SpaceHandle, type SurfaceHandle, type TrayExtension, type TrayExtensionContext, type TrayExtensionMountSpec, type TrayHandle, createBrokerEndpointIdentity, createClient, createInitFrame, createSpace, createSpaceHandle, createSurface, createSurfaceHandle, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveDefaultSpace };
22
+ export { type BrokerConnectOptions, type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type BrokerEventFrame, type CreateClientOptions, type CreateTrayOptions, type EventfulSpaceHandle, type EventfulTrayHandle, type ExtensionLoadOptions, type OpenTrayClient, type OpenTrayConnection, type OpenTrayEventSource, type OpenTrayEventfulClient, type OpenTrayTransport, PROTOCOL_VERSION, type SpaceHandle, type SurfaceHandle, type TrayEventByType, type TrayEventType, type TrayExtension, type TrayExtensionContext, type TrayExtensionMountSpec, type TrayHandle, createBrokerEndpointIdentity, createClient, createInitFrame, createSpace, createSpaceHandle, createSurface, createSurfaceHandle, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveDefaultSpace };
23
23
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/sdk.ts"],"mappings":";;;;UAKiB,oBAAA;EACf,QAAA;EACA,OAAA;EACA,cAAA;EACA,eAAA;EACA,aAAA;EACA,SAAA;AAAA;AAAA,UAGe,iBAAA,SAA0B,oBAAoB;EAC7D,KAAA,GAAQ,QAAA;AAAA;AAAA,cAGG,WAAA,GACX,OAAA,EAAS,YAAA,EACT,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,WAAA;;cAME,aAAA,GACX,OAAA,EAAS,YAAA,EACT,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,aAAA;AAAA,cAEE,mBAAA,GACX,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,WAAA;AAAA,cAKE,UAAA,GACX,OAAA,EAAS,WAAA,EACT,aAAA,GAAe,iBAAA,KACd,OAAA,CAAQ,UAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/sdk.ts"],"mappings":";;;;UAWiB,oBAAA;EACf,QAAA;EACA,OAAA;EACA,cAAA;EACA,eAAA;EACA,aAAA;EACA,SAAA;AAAA;AAAA,UAGe,iBAAA,SAA0B,oBAAoB;EAC7D,KAAA,GAAQ,QAAA;AAAA;AAAA,cAGG,WAAA,GACX,OAAA,EAAS,YAAA,EACT,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,mBAAA;;cAME,aAAA,GACX,OAAA,EAAS,YAAA,EACT,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,aAAA;AAAA,cAEE,mBAAA,GACX,aAAA,GAAe,oBAAA,KACd,OAAA,CAAQ,mBAAA;AAAA,cAKE,UAAA,GACX,OAAA,EAAS,WAAA,EACT,aAAA,GAAe,iBAAA,KACd,OAAA,CAAQ,kBAAA"}
package/dist/index.mjs CHANGED
@@ -1,6 +1,267 @@
1
- import { a as createTrayHandle, i as createSurfaceHandle, n as createInitFrame, r as createSpaceHandle, t as createClient } from "./client-DzcHIH-f.mjs";
2
- import { t as connectLocalBroker } from "./local-broker-CEIHPBcK.mjs";
3
- import { PROTOCOL_VERSION, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
1
+ import { t as connectLocalBroker } from "./local-broker-DOIkewF4.mjs";
2
+ import { PROTOCOL_VERSION, PROTOCOL_VERSION as PROTOCOL_VERSION$1, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
3
+ //#region src/client.ts
4
+ const createInitFrame = (clientVersion) => ({
5
+ type: "init",
6
+ protocolVersion: PROTOCOL_VERSION$1,
7
+ clientVersion
8
+ });
9
+ function createClient(transport, options = {}) {
10
+ const nextRequestId = createRequestIdFactory(options.requestIdPrefix ?? "opentray");
11
+ return {
12
+ async createSpace(spaceOptions) {
13
+ const requestId = nextRequestId();
14
+ const space = expectResponse(await transport.request({
15
+ type: "create-space",
16
+ requestId,
17
+ ...spaceOptions
18
+ }), requestId, "space-created").space;
19
+ return createSpaceHandle(transport, space, nextRequestId);
20
+ },
21
+ async resolveDefaultSpace() {
22
+ const requestId = nextRequestId();
23
+ const space = expectResponse(await transport.request({
24
+ type: "resolve-default-space",
25
+ requestId
26
+ }), requestId, "default-space").space;
27
+ return createSpaceHandle(transport, space, nextRequestId);
28
+ },
29
+ async createSurface(spaceOptions) {
30
+ return this.createSpace(spaceOptions);
31
+ }
32
+ };
33
+ }
34
+ function createSpaceHandle(transport, space, nextRequestId = createRequestIdFactory("opentray")) {
35
+ return {
36
+ space,
37
+ async createTray(options) {
38
+ const requestId = nextRequestId();
39
+ return createTrayHandle(transport, space, expectResponse(await transport.request({
40
+ type: "create-tray",
41
+ requestId,
42
+ space,
43
+ tray: options
44
+ }), requestId, "tray-created").trayId, nextRequestId);
45
+ }
46
+ };
47
+ }
48
+ /** @deprecated Use `createSpaceHandle`. */
49
+ const createSurfaceHandle = createSpaceHandle;
50
+ function createTrayHandle(transport, space, trayId, nextRequestId = createRequestIdFactory("opentray")) {
51
+ let nextMountOrdinal = 1;
52
+ const nextMountId = (extensionName) => {
53
+ const mountId = `${formatMountIdComponent(extensionName)}.${formatMountIdComponent(trayId)}.${nextMountOrdinal}`;
54
+ nextMountOrdinal += 1;
55
+ return mountId;
56
+ };
57
+ const handle = {
58
+ space,
59
+ trayId,
60
+ async getBounds() {
61
+ const requestId = nextRequestId();
62
+ return expectResponse(await transport.request({
63
+ type: "get-tray-bounds",
64
+ requestId,
65
+ spaceId: space.spaceId,
66
+ trayId
67
+ }), requestId, "tray-bounds").bounds;
68
+ },
69
+ async setMenu(menu) {
70
+ const requestId = nextRequestId();
71
+ expectResponse(await transport.request({
72
+ type: "set-tray-menu",
73
+ requestId,
74
+ spaceId: space.spaceId,
75
+ trayId,
76
+ menu
77
+ }), requestId, "ack");
78
+ },
79
+ async setTooltip(tooltip) {
80
+ const requestId = nextRequestId();
81
+ expectResponse(await transport.request({
82
+ type: "set-tray-tooltip",
83
+ requestId,
84
+ spaceId: space.spaceId,
85
+ trayId,
86
+ tooltip
87
+ }), requestId, "ack");
88
+ },
89
+ async setIcon(icon) {
90
+ const requestId = nextRequestId();
91
+ expectResponse(await transport.request({
92
+ type: "set-tray-icon",
93
+ requestId,
94
+ spaceId: space.spaceId,
95
+ trayId,
96
+ icon
97
+ }), requestId, "ack");
98
+ },
99
+ async setTitle(title) {
100
+ const requestId = nextRequestId();
101
+ expectResponse(await transport.request({
102
+ type: "set-tray-title",
103
+ requestId,
104
+ spaceId: space.spaceId,
105
+ trayId,
106
+ title
107
+ }), requestId, "ack");
108
+ },
109
+ async loadExtension(options) {
110
+ const requestId = nextRequestId();
111
+ expectResponse(await transport.request({
112
+ type: "load-ext",
113
+ requestId,
114
+ spaceId: space.spaceId,
115
+ name: options.name,
116
+ path: options.path,
117
+ ...options.mountId === void 0 ? {} : { mountId: options.mountId }
118
+ }), requestId, "ack");
119
+ },
120
+ async commandExtension(ext, data) {
121
+ await this.requestExtension(ext, data);
122
+ },
123
+ async requestExtension(ext, data) {
124
+ const requestId = nextRequestId();
125
+ const response = await transport.request({
126
+ type: "ext-command",
127
+ requestId,
128
+ spaceId: space.spaceId,
129
+ trayId,
130
+ ext,
131
+ data
132
+ });
133
+ if (response.type === "ack") {
134
+ expectResponse(response, requestId, "ack");
135
+ return [];
136
+ }
137
+ return expectResponse(response, requestId, "ext-command-result").events;
138
+ },
139
+ extend(extension, options) {
140
+ const context = createTrayExtensionContext(handle, extension, options, nextMountId);
141
+ const capability = extension.extend(handle, context, options);
142
+ return Object.assign({}, handle, capability);
143
+ },
144
+ async destroy() {
145
+ const requestId = nextRequestId();
146
+ expectResponse(await transport.request({
147
+ type: "destroy-tray",
148
+ requestId,
149
+ spaceId: space.spaceId,
150
+ trayId
151
+ }), requestId, "ack");
152
+ }
153
+ };
154
+ if (!isOpenTrayEventSource(transport)) return handle;
155
+ return attachEventfulTrayHandle(handle, transport, nextMountId);
156
+ }
157
+ const attachEventfulTrayHandle = (handle, source, nextMountId) => {
158
+ const listen = (event, handler) => source.onEvent((frame) => {
159
+ if (frame.type !== "event" || frame.event.type !== event) return;
160
+ if (!isOwnedTrayEvent(frame.event, handle.space.spaceId, handle.trayId)) return;
161
+ handler(frame.event);
162
+ });
163
+ const eventful = {
164
+ ...handle,
165
+ listenExtension(ext, handler) {
166
+ return source.onEvent((frame) => {
167
+ if (frame.type !== "ext-event" || frame.ext !== ext) return;
168
+ if (frame.spaceId !== handle.space.spaceId || frame.trayId !== handle.trayId) return;
169
+ handler({
170
+ scope: {
171
+ spaceId: frame.spaceId,
172
+ trayId: frame.trayId,
173
+ ext: frame.ext
174
+ },
175
+ data: frame.data
176
+ });
177
+ });
178
+ },
179
+ listen,
180
+ onMenuClick(handler) {
181
+ return listen("menuClick", handler);
182
+ },
183
+ onTrayClick(handler) {
184
+ return listen("trayClick", handler);
185
+ },
186
+ onTrayDoubleClick(handler) {
187
+ return listen("trayDoubleClick", handler);
188
+ },
189
+ extend(extension, options) {
190
+ const context = createTrayExtensionContext(eventful, extension, options, nextMountId);
191
+ const capability = extension.extend(eventful, context, options);
192
+ return Object.assign({}, eventful, capability);
193
+ }
194
+ };
195
+ return eventful;
196
+ };
197
+ const isOwnedTrayEvent = (event, spaceId, trayId) => event.type !== "ready" && event.spaceId === spaceId && event.trayId === trayId;
198
+ const isOpenTrayEventSource = (transport) => "onEvent" in transport && typeof transport.onEvent === "function";
199
+ const createTrayExtensionContext = (tray, extension, options, nextMountId) => {
200
+ const mount = extension.resolveMount?.(options) ?? {};
201
+ const name = mount.name ?? extension.name;
202
+ const path = mount.path ?? extension.path;
203
+ const mountId = mount.mountId ?? nextMountId(name);
204
+ let loadPromise;
205
+ const ensureLoaded = async () => {
206
+ if (loadPromise === void 0) loadPromise = tray.loadExtension({
207
+ name,
208
+ path,
209
+ mountId
210
+ }).catch((error) => {
211
+ loadPromise = void 0;
212
+ throw error;
213
+ });
214
+ await loadPromise;
215
+ };
216
+ return {
217
+ name,
218
+ path,
219
+ mountId,
220
+ ensureLoaded,
221
+ async command(data) {
222
+ await ensureLoaded();
223
+ await tray.commandExtension(mountId, data);
224
+ },
225
+ async request(data) {
226
+ await ensureLoaded();
227
+ return tray.requestExtension(mountId, data);
228
+ }
229
+ };
230
+ };
231
+ const formatMountIdComponent = (value) => {
232
+ const formatted = value.replaceAll(/[^a-zA-Z0-9._+-]/g, "_");
233
+ return formatted.length > 0 ? formatted : "ext";
234
+ };
235
+ const createRequestIdFactory = (prefix) => {
236
+ let next = 1;
237
+ return () => {
238
+ const requestId = `${prefix}-${next}`;
239
+ next += 1;
240
+ return requestId;
241
+ };
242
+ };
243
+ const expectResponse = (frame, requestId, type) => {
244
+ if (frame.type === "error") throw new Error(`${frame.code}: ${frame.message}`);
245
+ if (frame.type !== type) throw new Error(`expected ${type} for ${requestId}, received ${frame.type}`);
246
+ if (requestIdOf(frame) !== requestId) throw new Error(`expected response for ${requestId}, received ${requestIdOf(frame) ?? "none"}`);
247
+ return frame;
248
+ };
249
+ const requestIdOf = (frame) => {
250
+ switch (frame.type) {
251
+ case "space-created":
252
+ case "default-space":
253
+ case "tray-created":
254
+ case "tray-bounds":
255
+ case "ack":
256
+ case "ext-command-result":
257
+ case "daemon-health": return frame.requestId;
258
+ case "error": return frame.requestId;
259
+ case "ready":
260
+ case "event":
261
+ case "ext-event": return;
262
+ }
263
+ };
264
+ //#endregion
4
265
  //#region src/sdk.ts
5
266
  const createSpace = async (options, brokerOptions = {}) => {
6
267
  return createClient(await connectLocalBroker(brokerOptions)).createSpace(options);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/sdk.ts"],"sourcesContent":["import type { SpaceOptions, SpaceRef, TrayOptions } from \"@opentray/spec\";\n\nimport { createClient, createSpaceHandle, type SpaceHandle, type SurfaceHandle, type TrayHandle } from \"./client\";\nimport { connectLocalBroker } from \"./local-broker\";\n\nexport interface BrokerConnectOptions {\n endpoint?: string;\n homeDir?: string;\n packageVersion?: string;\n protocolVersion?: number;\n clientVersion?: string;\n autoStart?: boolean;\n}\n\nexport interface CreateTrayOptions extends BrokerConnectOptions {\n space?: SpaceRef;\n}\n\nexport const createSpace = async (\n options: SpaceOptions,\n brokerOptions: BrokerConnectOptions = {},\n): Promise<SpaceHandle> => {\n const connection = await connectLocalBroker(brokerOptions);\n return createClient(connection).createSpace(options);\n};\n\n/** @deprecated Use `createSpace`. */\nexport const createSurface = async (\n options: SpaceOptions,\n brokerOptions: BrokerConnectOptions = {},\n): Promise<SurfaceHandle> => createSpace(options, brokerOptions);\n\nexport const resolveDefaultSpace = async (\n brokerOptions: BrokerConnectOptions = {},\n): Promise<SpaceHandle> => {\n const connection = await connectLocalBroker(brokerOptions);\n return createClient(connection).resolveDefaultSpace();\n};\n\nexport const createTray = async (\n options: TrayOptions,\n brokerOptions: CreateTrayOptions = {},\n): Promise<TrayHandle> => {\n const { space, ...connectOptions } = brokerOptions;\n const connection = await connectLocalBroker(connectOptions);\n const spaceHandle = space ? createSpaceHandle(connection, space) : await createClient(connection).resolveDefaultSpace();\n return spaceHandle.createTray(options);\n};\n"],"mappings":";;;;AAkBA,MAAa,cAAc,OACzB,SACA,gBAAsC,CAAC,MACd;CAEzB,OAAO,aAAa,MADK,mBAAmB,aAAa,CAC3B,EAAE,YAAY,OAAO;AACrD;;AAGA,MAAa,gBAAgB,OAC3B,SACA,gBAAsC,CAAC,MACZ,YAAY,SAAS,aAAa;AAE/D,MAAa,sBAAsB,OACjC,gBAAsC,CAAC,MACd;CAEzB,OAAO,aAAa,MADK,mBAAmB,aAAa,CAC3B,EAAE,oBAAoB;AACtD;AAEA,MAAa,aAAa,OACxB,SACA,gBAAmC,CAAC,MACZ;CACxB,MAAM,EAAE,OAAO,GAAG,mBAAmB;CACrC,MAAM,aAAa,MAAM,mBAAmB,cAAc;CAE1D,QADoB,QAAQ,kBAAkB,YAAY,KAAK,IAAI,MAAM,aAAa,UAAU,EAAE,oBAAoB,GACnG,WAAW,OAAO;AACvC"}
1
+ {"version":3,"file":"index.mjs","names":["PROTOCOL_VERSION"],"sources":["../src/client.ts","../src/sdk.ts"],"sourcesContent":["import {\n PROTOCOL_VERSION,\n type ClientFrame,\n type ClientRequestFrame,\n type ExtensionEnvelope,\n type Icon,\n type Menu,\n type RequestId,\n type ServerFrame,\n type SpaceOptions,\n type SpaceRef,\n type Tooltip,\n type TrayBoundsResult,\n type TrayEvent,\n type TrayId,\n type TrayOptions,\n} from \"@opentray/spec\";\n\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame): Promise<ServerFrame>;\n}\n\nexport type BrokerEventFrame = Extract<ServerFrame, { type: \"event\" | \"ext-event\" }>;\n\nexport interface OpenTrayEventSource {\n onEvent(listener: (frame: BrokerEventFrame) => void): () => void;\n}\n\nexport interface OpenTrayConnection extends OpenTrayTransport, OpenTrayEventSource {}\n\nexport interface OpenTrayClient {\n createSpace(options: SpaceOptions): Promise<SpaceHandle>;\n resolveDefaultSpace(): Promise<SpaceHandle>;\n /** @deprecated Use `createSpace`. */\n createSurface(options: SpaceOptions): Promise<SpaceHandle>;\n}\n\nexport interface SpaceHandle {\n space: SpaceRef;\n createTray(options: TrayOptions): Promise<TrayHandle>;\n}\n\nexport interface EventfulSpaceHandle extends Omit<SpaceHandle, \"createTray\"> {\n createTray(options: TrayOptions): Promise<EventfulTrayHandle>;\n}\n\n/** @deprecated Use `SpaceHandle`. */\nexport type SurfaceHandle = SpaceHandle;\n\nexport interface TrayHandle {\n space: SpaceRef;\n trayId: TrayId;\n getBounds(): Promise<TrayBoundsResult>;\n setMenu(menu: Menu): Promise<void>;\n setTooltip(tooltip: Tooltip): Promise<void>;\n setIcon(icon: Icon): Promise<void>;\n setTitle(title: string): Promise<void>;\n loadExtension(options: ExtensionLoadOptions): Promise<void>;\n commandExtension(ext: string, data: unknown): Promise<void>;\n requestExtension(ext: string, data: unknown): Promise<ExtensionEnvelope[]>;\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions,\n ): TrayHandle & TCapability;\n destroy(): Promise<void>;\n}\n\nexport type TrayScopedEvent = Exclude<TrayEvent, { type: \"ready\" }>;\nexport type TrayEventType = TrayScopedEvent[\"type\"];\nexport type TrayEventByType<TEvent extends TrayEventType> = Extract<TrayScopedEvent, { type: TEvent }>;\n\nexport interface EventfulTrayHandle extends TrayHandle {\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions,\n ): EventfulTrayHandle & TCapability;\n listenExtension<TData = unknown>(\n ext: string,\n handler: (event: ExtensionEnvelope<TData>) => void,\n ): () => void;\n listen<TEvent extends TrayEventType>(\n event: TEvent,\n handler: (event: TrayEventByType<TEvent>) => void,\n ): () => void;\n onMenuClick(handler: (event: TrayEventByType<\"menuClick\">) => void): () => void;\n onTrayClick(handler: (event: TrayEventByType<\"trayClick\">) => void): () => void;\n onTrayDoubleClick(handler: (event: TrayEventByType<\"trayDoubleClick\">) => void): () => void;\n}\n\nexport interface ExtensionLoadOptions {\n name: string;\n path: string;\n mountId?: string;\n}\n\nexport interface TrayExtensionMountSpec {\n name?: string;\n path?: string;\n mountId?: string;\n}\n\nexport interface TrayExtensionContext {\n readonly name: string;\n readonly path: string;\n readonly mountId: string;\n ensureLoaded(): Promise<void>;\n command(data: unknown): Promise<void>;\n request(data: unknown): Promise<ExtensionEnvelope[]>;\n}\n\nexport interface TrayExtension<TCapability extends object, TOptions = undefined> {\n readonly name: string;\n readonly path: string;\n resolveMount?(options: TOptions | undefined): TrayExtensionMountSpec;\n extend(tray: TrayHandle, context: TrayExtensionContext, options: TOptions | undefined): TCapability;\n}\n\nexport const createInitFrame = (clientVersion: string): ClientFrame => ({\n type: \"init\",\n protocolVersion: PROTOCOL_VERSION,\n clientVersion,\n});\n\nexport interface CreateClientOptions {\n requestIdPrefix?: string;\n}\n\nexport interface OpenTrayEventfulClient extends Omit<OpenTrayClient, \"createSpace\" | \"resolveDefaultSpace\" | \"createSurface\"> {\n createSpace(options: SpaceOptions): Promise<EventfulSpaceHandle>;\n resolveDefaultSpace(): Promise<EventfulSpaceHandle>;\n /** @deprecated Use `createSpace`. */\n createSurface(options: SpaceOptions): Promise<EventfulSpaceHandle>;\n}\n\nexport function createClient(\n transport: OpenTrayConnection,\n options?: CreateClientOptions,\n): OpenTrayEventfulClient;\nexport function createClient(transport: OpenTrayTransport, options?: CreateClientOptions): OpenTrayClient;\nexport function createClient(\n transport: OpenTrayTransport,\n options: CreateClientOptions = {},\n): OpenTrayClient | OpenTrayEventfulClient {\n const nextRequestId = createRequestIdFactory(options.requestIdPrefix ?? \"opentray\");\n\n return {\n async createSpace(spaceOptions): Promise<SpaceHandle> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"create-space\",\n requestId,\n ...spaceOptions,\n });\n const space = expectResponse(response, requestId, \"space-created\").space;\n return createSpaceHandle(transport, space, nextRequestId);\n },\n async resolveDefaultSpace(): Promise<SpaceHandle> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"resolve-default-space\",\n requestId,\n });\n const space = expectResponse(response, requestId, \"default-space\").space;\n return createSpaceHandle(transport, space, nextRequestId);\n },\n async createSurface(spaceOptions): Promise<SpaceHandle> {\n return this.createSpace(spaceOptions);\n },\n };\n};\n\nexport function createSpaceHandle(\n transport: OpenTrayConnection,\n space: SpaceRef,\n nextRequestId?: () => RequestId,\n): EventfulSpaceHandle;\nexport function createSpaceHandle(\n transport: OpenTrayTransport,\n space: SpaceRef,\n nextRequestId?: () => RequestId,\n): SpaceHandle;\nexport function createSpaceHandle(\n transport: OpenTrayTransport,\n space: SpaceRef,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): SpaceHandle | EventfulSpaceHandle {\n return {\n space,\n async createTray(options: TrayOptions): Promise<TrayHandle | EventfulTrayHandle> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"create-tray\",\n requestId,\n space,\n tray: options,\n });\n const frame = expectResponse(response, requestId, \"tray-created\");\n return createTrayHandle(transport, space, frame.trayId, nextRequestId);\n },\n };\n}\n\n/** @deprecated Use `createSpaceHandle`. */\nexport const createSurfaceHandle = createSpaceHandle;\n\nexport function createTrayHandle(\n transport: OpenTrayConnection,\n space: SpaceRef,\n trayId: TrayId,\n nextRequestId?: () => RequestId,\n): EventfulTrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n space: SpaceRef,\n trayId: TrayId,\n nextRequestId?: () => RequestId,\n): TrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n space: SpaceRef,\n trayId: TrayId,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): TrayHandle | EventfulTrayHandle {\n let nextMountOrdinal = 1;\n const nextMountId = (extensionName: string): string => {\n const mountId = `${formatMountIdComponent(extensionName)}.${formatMountIdComponent(trayId)}.${nextMountOrdinal}`;\n nextMountOrdinal += 1;\n return mountId;\n };\n const handle: TrayHandle = {\n space,\n trayId,\n async getBounds(): Promise<TrayBoundsResult> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"get-tray-bounds\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n });\n return expectResponse(response, requestId, \"tray-bounds\").bounds;\n },\n async setMenu(menu: Menu): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-menu\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n menu,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setTooltip(tooltip: Tooltip): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-tooltip\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n tooltip,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setIcon(icon: Icon): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-icon\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n icon,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setTitle(title: string): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-title\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n title,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async loadExtension(options): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"load-ext\",\n requestId,\n spaceId: space.spaceId,\n name: options.name,\n path: options.path,\n ...(options.mountId === undefined ? {} : { mountId: options.mountId }),\n });\n expectResponse(response, requestId, \"ack\");\n },\n async commandExtension(ext: string, data: unknown): Promise<void> {\n await this.requestExtension(ext, data);\n },\n async requestExtension(ext: string, data: unknown): Promise<ExtensionEnvelope[]> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"ext-command\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n ext,\n data,\n });\n if (response.type === \"ack\") {\n expectResponse(response, requestId, \"ack\");\n return [];\n }\n return expectResponse(response, requestId, \"ext-command-result\").events;\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions,\n ): TrayHandle & TCapability {\n const context = createTrayExtensionContext(handle, extension, options, nextMountId);\n const capability = extension.extend(handle, context, options);\n return Object.assign({}, handle, capability);\n },\n async destroy(): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"destroy-tray\",\n requestId,\n spaceId: space.spaceId,\n trayId,\n });\n expectResponse(response, requestId, \"ack\");\n },\n };\n if (!isOpenTrayEventSource(transport)) {\n return handle;\n }\n return attachEventfulTrayHandle(handle, transport, nextMountId);\n}\n\nconst attachEventfulTrayHandle = (\n handle: TrayHandle,\n source: OpenTrayEventSource,\n nextMountId: (extensionName: string) => string,\n): EventfulTrayHandle => {\n const listen: EventfulTrayHandle[\"listen\"] = (event, handler) =>\n source.onEvent((frame) => {\n if (frame.type !== \"event\" || frame.event.type !== event) {\n return;\n }\n if (!isOwnedTrayEvent(frame.event, handle.space.spaceId, handle.trayId)) {\n return;\n }\n handler(frame.event as TrayEventByType<typeof event>);\n });\n\n const eventful: EventfulTrayHandle = {\n ...handle,\n listenExtension<TData = unknown>(ext: string, handler: (event: ExtensionEnvelope<TData>) => void) {\n return source.onEvent((frame) => {\n if (frame.type !== \"ext-event\" || frame.ext !== ext) {\n return;\n }\n if (frame.spaceId !== handle.space.spaceId || frame.trayId !== handle.trayId) {\n return;\n }\n handler({\n scope: { spaceId: frame.spaceId, trayId: frame.trayId, ext: frame.ext },\n data: frame.data as TData,\n });\n });\n },\n listen,\n onMenuClick(handler) {\n return listen(\"menuClick\", handler);\n },\n onTrayClick(handler) {\n return listen(\"trayClick\", handler);\n },\n onTrayDoubleClick(handler) {\n return listen(\"trayDoubleClick\", handler);\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions,\n ): EventfulTrayHandle & TCapability {\n const context = createTrayExtensionContext(eventful, extension, options, nextMountId);\n const capability = extension.extend(eventful, context, options);\n return Object.assign({}, eventful, capability);\n },\n };\n return eventful;\n};\n\nconst isOwnedTrayEvent = (event: TrayEvent, spaceId: string, trayId: string): event is TrayScopedEvent =>\n event.type !== \"ready\" && event.spaceId === spaceId && event.trayId === trayId;\n\nconst isOpenTrayEventSource = (transport: OpenTrayTransport): transport is OpenTrayConnection =>\n \"onEvent\" in transport && typeof transport.onEvent === \"function\";\n\nconst createTrayExtensionContext = <TCapability extends object, TOptions>(\n tray: TrayHandle,\n extension: TrayExtension<TCapability, TOptions>,\n options: TOptions | undefined,\n nextMountId: (extensionName: string) => string,\n): TrayExtensionContext => {\n const mount = extension.resolveMount?.(options) ?? {};\n const name = mount.name ?? extension.name;\n const path = mount.path ?? extension.path;\n const mountId = mount.mountId ?? nextMountId(name);\n let loadPromise: Promise<void> | undefined;\n\n const ensureLoaded = async (): Promise<void> => {\n if (loadPromise === undefined) {\n loadPromise = tray.loadExtension({ name, path, mountId }).catch((error: unknown) => {\n loadPromise = undefined;\n throw error;\n });\n }\n await loadPromise;\n };\n\n return {\n name,\n path,\n mountId,\n ensureLoaded,\n async command(data: unknown): Promise<void> {\n await ensureLoaded();\n await tray.commandExtension(mountId, data);\n },\n async request(data: unknown): Promise<ExtensionEnvelope[]> {\n await ensureLoaded();\n return tray.requestExtension(mountId, data);\n },\n };\n};\n\nconst formatMountIdComponent = (value: string): string => {\n const formatted = value.replaceAll(/[^a-zA-Z0-9._+-]/g, \"_\");\n return formatted.length > 0 ? formatted : \"ext\";\n};\n\nconst createRequestIdFactory = (prefix: string): (() => RequestId) => {\n let next = 1;\n return () => {\n const requestId = `${prefix}-${next}`;\n next += 1;\n return requestId;\n };\n};\n\nconst expectResponse = <TType extends ServerFrame[\"type\"]>(\n frame: ServerFrame,\n requestId: RequestId,\n type: TType,\n): Extract<ServerFrame, { type: TType }> => {\n if (frame.type === \"error\") {\n throw new Error(`${frame.code}: ${frame.message}`);\n }\n if (frame.type !== type) {\n throw new Error(`expected ${type} for ${requestId}, received ${frame.type}`);\n }\n if (requestIdOf(frame) !== requestId) {\n throw new Error(`expected response for ${requestId}, received ${requestIdOf(frame) ?? \"none\"}`);\n }\n return frame as Extract<ServerFrame, { type: TType }>;\n};\n\nconst requestIdOf = (frame: ServerFrame): RequestId | undefined => {\n switch (frame.type) {\n case \"space-created\":\n case \"default-space\":\n case \"tray-created\":\n case \"tray-bounds\":\n case \"ack\":\n case \"ext-command-result\":\n case \"daemon-health\":\n return frame.requestId;\n case \"error\":\n return frame.requestId;\n case \"ready\":\n case \"event\":\n case \"ext-event\":\n return undefined;\n }\n};\n","import type { SpaceOptions, SpaceRef, TrayOptions } from \"@opentray/spec\";\n\nimport {\n createClient,\n createSpaceHandle,\n type EventfulSpaceHandle,\n type EventfulTrayHandle,\n type SurfaceHandle,\n} from \"./client\";\nimport { connectLocalBroker } from \"./local-broker\";\n\nexport interface BrokerConnectOptions {\n endpoint?: string;\n homeDir?: string;\n packageVersion?: string;\n protocolVersion?: number;\n clientVersion?: string;\n autoStart?: boolean;\n}\n\nexport interface CreateTrayOptions extends BrokerConnectOptions {\n space?: SpaceRef;\n}\n\nexport const createSpace = async (\n options: SpaceOptions,\n brokerOptions: BrokerConnectOptions = {},\n): Promise<EventfulSpaceHandle> => {\n const connection = await connectLocalBroker(brokerOptions);\n return createClient(connection).createSpace(options);\n};\n\n/** @deprecated Use `createSpace`. */\nexport const createSurface = async (\n options: SpaceOptions,\n brokerOptions: BrokerConnectOptions = {},\n): Promise<SurfaceHandle> => createSpace(options, brokerOptions);\n\nexport const resolveDefaultSpace = async (\n brokerOptions: BrokerConnectOptions = {},\n): Promise<EventfulSpaceHandle> => {\n const connection = await connectLocalBroker(brokerOptions);\n return createClient(connection).resolveDefaultSpace();\n};\n\nexport const createTray = async (\n options: TrayOptions,\n brokerOptions: CreateTrayOptions = {},\n): Promise<EventfulTrayHandle> => {\n const { space, ...connectOptions } = brokerOptions;\n const connection = await connectLocalBroker(connectOptions);\n const spaceHandle = space ? createSpaceHandle(connection, space) : await createClient(connection).resolveDefaultSpace();\n return spaceHandle.createTray(options);\n};\n"],"mappings":"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"}
@@ -115,8 +115,14 @@ const findWorkspaceRoot = async (start) => {
115
115
  current = parent;
116
116
  }
117
117
  };
118
+ const resolveDevBrokerBinaryPath = (workspaceRoot, platform = process.platform) => join(workspaceRoot, "target", "debug", platform === "win32" ? "opentray.exe" : "opentray");
119
+ const terminateWorkspaceDevBrokerProcess = async (workspaceRoot, platform = process.platform) => {
120
+ if (platform !== "win32") return;
121
+ await terminateWindowsProcessByExecutable(resolveDevBrokerBinaryPath(workspaceRoot, platform));
122
+ };
118
123
  const ensureDevBrokerBinary = async (workspaceRoot) => {
119
- const binary = join(workspaceRoot, "target", "debug", process.platform === "win32" ? "opentray.exe" : "opentray");
124
+ const binary = resolveDevBrokerBinaryPath(workspaceRoot);
125
+ await terminateWorkspaceDevBrokerProcess(workspaceRoot);
120
126
  await runCargoBuild(workspaceRoot);
121
127
  return binary;
122
128
  };
@@ -146,6 +152,45 @@ const exists = async (path) => {
146
152
  return false;
147
153
  }
148
154
  };
155
+ const terminateWindowsProcessByExecutable = (binary) => new Promise((resolve, reject) => {
156
+ const child = spawn("powershell.exe", [
157
+ "-NoProfile",
158
+ "-NonInteractive",
159
+ "-ExecutionPolicy",
160
+ "Bypass",
161
+ "-Command",
162
+ String.raw`
163
+ $ErrorActionPreference = 'Stop'
164
+ $target = [System.IO.Path]::GetFullPath(${powerShellString(binary)})
165
+ $processes = @(Get-CimInstance Win32_Process -Filter "Name = 'opentray.exe'" | Where-Object {
166
+ $_.ExecutablePath -and ([System.IO.Path]::GetFullPath($_.ExecutablePath) -ieq $target)
167
+ })
168
+ foreach ($process in $processes) {
169
+ Stop-Process -Id $process.ProcessId -Force -ErrorAction Stop
170
+ }
171
+ foreach ($process in $processes) {
172
+ Wait-Process -Id $process.ProcessId -Timeout 5 -ErrorAction SilentlyContinue
173
+ }
174
+ `
175
+ ], { stdio: [
176
+ "ignore",
177
+ "ignore",
178
+ "pipe"
179
+ ] });
180
+ let stderr = "";
181
+ child.stderr?.on("data", (chunk) => {
182
+ stderr += String(chunk);
183
+ });
184
+ child.once("error", reject);
185
+ child.once("exit", (code) => {
186
+ if (code === 0) {
187
+ resolve();
188
+ return;
189
+ }
190
+ reject(/* @__PURE__ */ new Error(`failed to stop running dev broker before cargo build: ${stderr.trim() || code}`));
191
+ });
192
+ });
193
+ const powerShellString = (value) => `'${value.replace(/'/g, "''")}'`;
149
194
  const isNodeError$1 = (error) => error instanceof Error && "code" in error;
150
195
  //#endregion
151
196
  //#region src/daemon/lifecycle.ts
@@ -191,7 +236,7 @@ const startDaemon = async ({ paths, driver, lockTimeoutMs = 1e3 }) => {
191
236
  const pid = await driver.spawnBroker(paths);
192
237
  if (!Number.isInteger(pid) || pid <= 0) throw new Error("daemon broker process did not expose a valid pid");
193
238
  await writeFile(paths.pidFile, `${pid}\n`, "utf8");
194
- await waitForReadyFile(paths.readyFile);
239
+ await waitForReadyFile(paths.readyFile, driver, pid);
195
240
  return {
196
241
  status: "started",
197
242
  pid,
@@ -264,12 +309,13 @@ const waitUntilStopped = async (driver, pid) => {
264
309
  await sleep(50);
265
310
  }
266
311
  };
267
- const waitForReadyFile = async (readyFile) => {
312
+ const waitForReadyFile = async (readyFile, driver, pid) => {
268
313
  for (let attempt = 0; attempt < 40; attempt += 1) try {
269
314
  await readFile(readyFile, "utf8");
270
315
  return;
271
316
  } catch (error) {
272
317
  if (!isNodeError(error) || error.code !== "ENOENT") throw error;
318
+ if (!await driver.isAlive(pid)) throw new Error(`daemon broker exited before readiness: pid=${pid}; readyFile=${readyFile}; set ${DAEMON_STDIO_ENV}=inherit to inspect broker stderr`);
273
319
  await sleep(50);
274
320
  }
275
321
  throw new Error(`timed out waiting for daemon readiness: ${readyFile}`);
@@ -432,7 +478,7 @@ var LocalBrokerConnection = class {
432
478
  dispatchLine(line) {
433
479
  const parsed = parseServerFrame(line);
434
480
  if (!parsed.ok || parsed.frame === void 0) {
435
- this.rejectAll(new Error(parsed.error ?? "invalid server frame"));
481
+ this.rejectAll(/* @__PURE__ */ new Error(`${parsed.error ?? "invalid server frame"}: ${line}`));
436
482
  return;
437
483
  }
438
484
  this.dispatchFrame(parsed.frame);
@@ -487,6 +533,7 @@ const responseRequestId = (frame) => {
487
533
  case "tray-created":
488
534
  case "tray-bounds":
489
535
  case "ack":
536
+ case "ext-command-result":
490
537
  case "daemon-health": return frame.requestId;
491
538
  case "ready":
492
539
  case "event":
@@ -501,4 +548,4 @@ const resolveCliEntrypoint = () => {
501
548
  //#endregion
502
549
  export { inspectDaemon as a, stopDaemon as c, createNodeDaemonDriver as i, resolveDaemonPaths as n, restartDaemon as o, readPackageVersion as r, startDaemon as s, connectLocalBroker as t };
503
550
 
504
- //# sourceMappingURL=local-broker-CEIHPBcK.mjs.map
551
+ //# sourceMappingURL=local-broker-DOIkewF4.mjs.map