opentray 0.5.1 → 0.6.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.
@@ -20,9 +20,34 @@ interface TrayHandle {
20
20
  space: SpaceRef;
21
21
  trayId: TrayId;
22
22
  getBounds(): Promise<TrayBoundsResult>;
23
+ loadExtension(options: ExtensionLoadOptions): Promise<void>;
23
24
  commandExtension(ext: string, data: unknown): Promise<void>;
25
+ extend<TCapability extends object, TOptions = undefined>(extension: TrayExtension<TCapability, TOptions>, options?: TOptions): TrayHandle & TCapability;
24
26
  destroy(): Promise<void>;
25
27
  }
28
+ interface ExtensionLoadOptions {
29
+ name: string;
30
+ path: string;
31
+ mountId?: string;
32
+ }
33
+ interface TrayExtensionMountSpec {
34
+ name?: string;
35
+ path?: string;
36
+ mountId?: string;
37
+ }
38
+ interface TrayExtensionContext {
39
+ readonly name: string;
40
+ readonly path: string;
41
+ readonly mountId: string;
42
+ ensureLoaded(): Promise<void>;
43
+ command(data: unknown): Promise<void>;
44
+ }
45
+ interface TrayExtension<TCapability extends object, TOptions = undefined> {
46
+ readonly name: string;
47
+ readonly path: string;
48
+ resolveMount?(options: TOptions | undefined): TrayExtensionMountSpec;
49
+ extend(tray: TrayHandle, context: TrayExtensionContext, options: TOptions | undefined): TCapability;
50
+ }
26
51
  declare const createInitFrame: (clientVersion: string) => ClientFrame;
27
52
  interface CreateClientOptions {
28
53
  requestIdPrefix?: string;
@@ -33,5 +58,5 @@ declare const createSpaceHandle: (transport: OpenTrayTransport, space: SpaceRef,
33
58
  declare const createSurfaceHandle: (transport: OpenTrayTransport, space: SpaceRef, nextRequestId?: () => RequestId) => SpaceHandle;
34
59
  declare const createTrayHandle: (transport: OpenTrayTransport, space: SpaceRef, trayId: TrayId, nextRequestId?: () => RequestId) => TrayHandle;
35
60
  //#endregion
36
- export { SurfaceHandle as a, createInitFrame as c, createTrayHandle as d, SpaceHandle as i, createSpaceHandle as l, OpenTrayClient as n, TrayHandle as o, OpenTrayTransport as r, createClient as s, CreateClientOptions as t, createSurfaceHandle as u };
37
- //# sourceMappingURL=client-h6gZdeOk.d.mts.map
61
+ export { SpaceHandle as a, TrayExtensionContext as c, createClient as d, createInitFrame as f, createTrayHandle as h, OpenTrayTransport as i, TrayExtensionMountSpec as l, createSurfaceHandle as m, ExtensionLoadOptions as n, SurfaceHandle as o, createSpaceHandle as p, OpenTrayClient as r, TrayExtension as s, CreateClientOptions as t, TrayHandle as u };
62
+ //# sourceMappingURL=client-DQn3DLZw.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-DQn3DLZw.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;UAaiB,iBAAA;EACf,OAAA,CAAQ,KAAA,EAAO,kBAAA,GAAqB,OAAA,CAAQ,WAAA;AAAA;AAAA,UAG7B,cAAA;EACf,WAAA,CAAY,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,WAAA;EAC5C,mBAAA,IAAuB,OAAA,CAAQ,WAAA;EALa;EAO5C,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;;KAIhC,aAAA,GAAgB,WAAW;AAAA,UAEtB,UAAA;EACf,KAAA,EAAO,QAAA;EACP,MAAA,EAAQ,MAAA;EACR,SAAA,IAAa,OAAA,CAAQ,gBAAA;EACrB,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,OAAA;EAC9C,gBAAA,CAAiB,GAAA,UAAa,IAAA,YAAgB,OAAA;EAC9C,MAAA,mDACE,SAAA,EAAW,aAAA,CAAc,WAAA,EAAa,QAAA,GACtC,OAAA,GAAU,QAAA,GACT,UAAA,GAAa,WAAA;EAChB,OAAA,IAAW,OAAA;AAAA;AAAA,UAGI,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,OAAO;AAAA;AAAA,UAGhB,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,cAGJ,YAAA,GACX,SAAA,EAAW,iBAAA,EACX,OAAA,GAAS,mBAAA,KACR,cAAA;AAAA,cA6BU,iBAAA,GACX,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,aAAA,SAAqB,SAAA,KACpB,WAAA;;cAgBU,mBAAA,GAAmB,SAAA,EAnBnB,iBAAA,EAAiB,KAAA,EACrB,QAAA,EAAQ,aAAA,SACM,SAAA,KACpB,WAAA;AAAA,cAkBU,gBAAA,GACX,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,MAAA,EAAQ,MAAA,EACR,aAAA,SAAqB,SAAA,KACpB,UAAA"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SurfaceHandle, c as createInitFrame, d as createTrayHandle, i as SpaceHandle, l as createSpaceHandle, n as OpenTrayClient, o as TrayHandle, r as OpenTrayTransport, s as createClient, t as CreateClientOptions, u as createSurfaceHandle } from "./client-h6gZdeOk.mjs";
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";
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
@@ -19,5 +19,5 @@ declare const createSurface: (options: SpaceOptions, brokerOptions?: BrokerConne
19
19
  declare const resolveDefaultSpace: (brokerOptions?: BrokerConnectOptions) => Promise<SpaceHandle>;
20
20
  declare const createTray: (options: TrayOptions, brokerOptions?: CreateTrayOptions) => Promise<TrayHandle>;
21
21
  //#endregion
22
- export { type BrokerConnectOptions, type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type CreateClientOptions, type CreateTrayOptions, type OpenTrayClient, type OpenTrayTransport, PROTOCOL_VERSION, type SpaceHandle, type SurfaceHandle, 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 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 };
23
23
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,6 +1,169 @@
1
- import { a as createTrayHandle, i as createSurfaceHandle, n as createInitFrame, r as createSpaceHandle, t as createClient } from "./client-B_zxQOo5.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-C9siWyRh.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
+ const 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
+ const createSpaceHandle = (transport, space, nextRequestId = createRequestIdFactory("opentray")) => ({
35
+ space,
36
+ async createTray(options) {
37
+ const requestId = nextRequestId();
38
+ return createTrayHandle(transport, space, expectResponse(await transport.request({
39
+ type: "create-tray",
40
+ requestId,
41
+ space,
42
+ tray: options
43
+ }), requestId, "tray-created").trayId, nextRequestId);
44
+ }
45
+ });
46
+ /** @deprecated Use `createSpaceHandle`. */
47
+ const createSurfaceHandle = createSpaceHandle;
48
+ const createTrayHandle = (transport, space, trayId, nextRequestId = createRequestIdFactory("opentray")) => {
49
+ let nextMountOrdinal = 1;
50
+ const nextMountId = (extensionName) => {
51
+ const mountId = `${formatMountIdComponent(extensionName)}.${formatMountIdComponent(trayId)}.${nextMountOrdinal}`;
52
+ nextMountOrdinal += 1;
53
+ return mountId;
54
+ };
55
+ const handle = {
56
+ space,
57
+ trayId,
58
+ async getBounds() {
59
+ const requestId = nextRequestId();
60
+ return expectResponse(await transport.request({
61
+ type: "get-tray-bounds",
62
+ requestId,
63
+ spaceId: space.spaceId,
64
+ trayId
65
+ }), requestId, "tray-bounds").bounds;
66
+ },
67
+ async loadExtension(options) {
68
+ const requestId = nextRequestId();
69
+ expectResponse(await transport.request({
70
+ type: "load-ext",
71
+ requestId,
72
+ spaceId: space.spaceId,
73
+ name: options.name,
74
+ path: options.path,
75
+ ...options.mountId === void 0 ? {} : { mountId: options.mountId }
76
+ }), requestId, "ack");
77
+ },
78
+ async commandExtension(ext, data) {
79
+ const requestId = nextRequestId();
80
+ expectResponse(await transport.request({
81
+ type: "ext-command",
82
+ requestId,
83
+ spaceId: space.spaceId,
84
+ trayId,
85
+ ext,
86
+ data
87
+ }), requestId, "ack");
88
+ },
89
+ extend(extension, options) {
90
+ const context = createTrayExtensionContext(handle, extension, options, nextMountId);
91
+ const capability = extension.extend(handle, context, options);
92
+ return Object.assign({}, handle, capability);
93
+ },
94
+ async destroy() {
95
+ const requestId = nextRequestId();
96
+ expectResponse(await transport.request({
97
+ type: "destroy-tray",
98
+ requestId,
99
+ spaceId: space.spaceId,
100
+ trayId
101
+ }), requestId, "ack");
102
+ }
103
+ };
104
+ return handle;
105
+ };
106
+ const createTrayExtensionContext = (tray, extension, options, nextMountId) => {
107
+ const mount = extension.resolveMount?.(options) ?? {};
108
+ const name = mount.name ?? extension.name;
109
+ const path = mount.path ?? extension.path;
110
+ const mountId = mount.mountId ?? nextMountId(name);
111
+ let loadPromise;
112
+ const ensureLoaded = async () => {
113
+ if (loadPromise === void 0) loadPromise = tray.loadExtension({
114
+ name,
115
+ path,
116
+ mountId
117
+ }).catch((error) => {
118
+ loadPromise = void 0;
119
+ throw error;
120
+ });
121
+ await loadPromise;
122
+ };
123
+ return {
124
+ name,
125
+ path,
126
+ mountId,
127
+ ensureLoaded,
128
+ async command(data) {
129
+ await ensureLoaded();
130
+ await tray.commandExtension(mountId, data);
131
+ }
132
+ };
133
+ };
134
+ const formatMountIdComponent = (value) => {
135
+ const formatted = value.replaceAll(/[^a-zA-Z0-9._+-]/g, "_");
136
+ return formatted.length > 0 ? formatted : "ext";
137
+ };
138
+ const createRequestIdFactory = (prefix) => {
139
+ let next = 1;
140
+ return () => {
141
+ const requestId = `${prefix}-${next}`;
142
+ next += 1;
143
+ return requestId;
144
+ };
145
+ };
146
+ const expectResponse = (frame, requestId, type) => {
147
+ if (frame.type === "error") throw new Error(`${frame.code}: ${frame.message}`);
148
+ if (frame.type !== type) throw new Error(`expected ${type} for ${requestId}, received ${frame.type}`);
149
+ if (requestIdOf(frame) !== requestId) throw new Error(`expected response for ${requestId}, received ${requestIdOf(frame) ?? "none"}`);
150
+ return frame;
151
+ };
152
+ const requestIdOf = (frame) => {
153
+ switch (frame.type) {
154
+ case "space-created":
155
+ case "default-space":
156
+ case "tray-created":
157
+ case "tray-bounds":
158
+ case "ack":
159
+ case "daemon-health": return frame.requestId;
160
+ case "error": return frame.requestId;
161
+ case "ready":
162
+ case "event":
163
+ case "ext-event": return;
164
+ }
165
+ };
166
+ //#endregion
4
167
  //#region src/sdk.ts
5
168
  const createSpace = async (options, brokerOptions = {}) => {
6
169
  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 RequestId,\n type ServerFrame,\n type SpaceOptions,\n type SpaceRef,\n type TrayBoundsResult,\n type TrayId,\n type TrayOptions,\n} from \"@opentray/spec\";\n\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame): Promise<ServerFrame>;\n}\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\n/** @deprecated Use `SpaceHandle`. */\nexport type SurfaceHandle = SpaceHandle;\n\nexport interface TrayHandle {\n space: SpaceRef;\n trayId: TrayId;\n getBounds(): Promise<TrayBoundsResult>;\n loadExtension(options: ExtensionLoadOptions): Promise<void>;\n commandExtension(ext: string, data: unknown): Promise<void>;\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 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}\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 const createClient = (\n transport: OpenTrayTransport,\n options: CreateClientOptions = {},\n): OpenTrayClient => {\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 const createSpaceHandle = (\n transport: OpenTrayTransport,\n space: SpaceRef,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): SpaceHandle => ({\n space,\n async createTray(options: TrayOptions): Promise<TrayHandle> {\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/** @deprecated Use `createSpaceHandle`. */\nexport const createSurfaceHandle = createSpaceHandle;\n\nexport const createTrayHandle = (\n transport: OpenTrayTransport,\n space: SpaceRef,\n trayId: TrayId,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): TrayHandle => {\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 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 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 expectResponse(response, requestId, \"ack\");\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 return handle;\n};\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 };\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 \"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 { 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":";;;AAwEA,MAAa,mBAAmB,mBAAwC;CACtE,MAAM;CACN,iBAAiBA;CACjB;AACF;AAMA,MAAa,gBACX,WACA,UAA+B,CAAC,MACb;CACnB,MAAM,gBAAgB,uBAAuB,QAAQ,mBAAmB,UAAU;CAElF,OAAO;EACL,MAAM,YAAY,cAAoC;GACpD,MAAM,YAAY,cAAc;GAMhC,MAAM,QAAQ,eAAe,MALN,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,GAAG;GACL,CAAC,GACsC,WAAW,eAAe,EAAE;GACnE,OAAO,kBAAkB,WAAW,OAAO,aAAa;EAC1D;EACA,MAAM,sBAA4C;GAChD,MAAM,YAAY,cAAc;GAKhC,MAAM,QAAQ,eAAe,MAJN,UAAU,QAAQ;IACvC,MAAM;IACN;GACF,CAAC,GACsC,WAAW,eAAe,EAAE;GACnE,OAAO,kBAAkB,WAAW,OAAO,aAAa;EAC1D;EACA,MAAM,cAAc,cAAoC;GACtD,OAAO,KAAK,YAAY,YAAY;EACtC;CACF;AACF;AAEA,MAAa,qBACX,WACA,OACA,gBAAiC,uBAAuB,UAAU,OACjD;CACjB;CACA,MAAM,WAAW,SAA2C;EAC1D,MAAM,YAAY,cAAc;EAQhC,OAAO,iBAAiB,WAAW,OADrB,eAAe,MANN,UAAU,QAAQ;GACvC,MAAM;GACN;GACA;GACA,MAAM;EACR,CAAC,GACsC,WAAW,cACJ,EAAE,QAAQ,aAAa;CACvE;AACF;;AAGA,MAAa,sBAAsB;AAEnC,MAAa,oBACX,WACA,OACA,QACA,gBAAiC,uBAAuB,UAAU,MACnD;CACf,IAAI,mBAAmB;CACvB,MAAM,eAAe,kBAAkC;EACrD,MAAM,UAAU,GAAG,uBAAuB,aAAa,EAAE,GAAG,uBAAuB,MAAM,EAAE,GAAG;EAC9F,oBAAoB;EACpB,OAAO;CACT;CACA,MAAM,SAAqB;EACzB;EACA;EACA,MAAM,YAAuC;GAC3C,MAAM,YAAY,cAAc;GAOhC,OAAO,eAAe,MANC,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,SAAS,MAAM;IACf;GACF,CAAC,GAC+B,WAAW,aAAa,EAAE;EAC5D;EACA,MAAM,cAAc,SAAwB;GAC1C,MAAM,YAAY,cAAc;GAShC,eAAe,MARQ,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,SAAS,MAAM;IACf,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;GACtE,CAAC,GACwB,WAAW,KAAK;EAC3C;EACA,MAAM,iBAAiB,KAAa,MAA8B;GAChE,MAAM,YAAY,cAAc;GAShC,eAAe,MARQ,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,SAAS,MAAM;IACf;IACA;IACA;GACF,CAAC,GACwB,WAAW,KAAK;EAC3C;EACA,OACE,WACA,SAC0B;GAC1B,MAAM,UAAU,2BAA2B,QAAQ,WAAW,SAAS,WAAW;GAClF,MAAM,aAAa,UAAU,OAAO,QAAQ,SAAS,OAAO;GAC5D,OAAO,OAAO,OAAO,CAAC,GAAG,QAAQ,UAAU;EAC7C;EACA,MAAM,UAAyB;GAC7B,MAAM,YAAY,cAAc;GAOhC,eAAe,MANQ,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,SAAS,MAAM;IACf;GACF,CAAC,GACwB,WAAW,KAAK;EAC3C;CACF;CACA,OAAO;AACT;AAEA,MAAM,8BACJ,MACA,WACA,SACA,gBACyB;CACzB,MAAM,QAAQ,UAAU,eAAe,OAAO,KAAK,CAAC;CACpD,MAAM,OAAO,MAAM,QAAQ,UAAU;CACrC,MAAM,OAAO,MAAM,QAAQ,UAAU;CACrC,MAAM,UAAU,MAAM,WAAW,YAAY,IAAI;CACjD,IAAI;CAEJ,MAAM,eAAe,YAA2B;EAC9C,IAAI,gBAAgB,KAAA,GAClB,cAAc,KAAK,cAAc;GAAE;GAAM;GAAM;EAAQ,CAAC,EAAE,OAAO,UAAmB;GAClF,cAAc,KAAA;GACd,MAAM;EACR,CAAC;EAEH,MAAM;CACR;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA,MAAM,QAAQ,MAA8B;GAC1C,MAAM,aAAa;GACnB,MAAM,KAAK,iBAAiB,SAAS,IAAI;EAC3C;CACF;AACF;AAEA,MAAM,0BAA0B,UAA0B;CACxD,MAAM,YAAY,MAAM,WAAW,qBAAqB,GAAG;CAC3D,OAAO,UAAU,SAAS,IAAI,YAAY;AAC5C;AAEA,MAAM,0BAA0B,WAAsC;CACpE,IAAI,OAAO;CACX,aAAa;EACX,MAAM,YAAY,GAAG,OAAO,GAAG;EAC/B,QAAQ;EACR,OAAO;CACT;AACF;AAEA,MAAM,kBACJ,OACA,WACA,SAC0C;CAC1C,IAAI,MAAM,SAAS,SACjB,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,IAAI,MAAM,SAAS;CAEnD,IAAI,MAAM,SAAS,MACjB,MAAM,IAAI,MAAM,YAAY,KAAK,OAAO,UAAU,aAAa,MAAM,MAAM;CAE7E,IAAI,YAAY,KAAK,MAAM,WACzB,MAAM,IAAI,MAAM,yBAAyB,UAAU,aAAa,YAAY,KAAK,KAAK,QAAQ;CAEhG,OAAO;AACT;AAEA,MAAM,eAAe,UAA8C;CACjE,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,iBACH,OAAO,MAAM;EACf,KAAK,SACH,OAAO,MAAM;EACf,KAAK;EACL,KAAK;EACL,KAAK,aACH;CACJ;AACF;;;AC9QA,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"}
@@ -191,7 +191,7 @@ const startDaemon = async ({ paths, driver, lockTimeoutMs = 1e3 }) => {
191
191
  const pid = await driver.spawnBroker(paths);
192
192
  if (!Number.isInteger(pid) || pid <= 0) throw new Error("daemon broker process did not expose a valid pid");
193
193
  await writeFile(paths.pidFile, `${pid}\n`, "utf8");
194
- await waitForReadyFile(paths.readyFile);
194
+ await waitForReadyFile(paths.readyFile, driver, pid);
195
195
  return {
196
196
  status: "started",
197
197
  pid,
@@ -264,12 +264,13 @@ const waitUntilStopped = async (driver, pid) => {
264
264
  await sleep(50);
265
265
  }
266
266
  };
267
- const waitForReadyFile = async (readyFile) => {
267
+ const waitForReadyFile = async (readyFile, driver, pid) => {
268
268
  for (let attempt = 0; attempt < 40; attempt += 1) try {
269
269
  await readFile(readyFile, "utf8");
270
270
  return;
271
271
  } catch (error) {
272
272
  if (!isNodeError(error) || error.code !== "ENOENT") throw error;
273
+ 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
274
  await sleep(50);
274
275
  }
275
276
  throw new Error(`timed out waiting for daemon readiness: ${readyFile}`);
@@ -501,4 +502,4 @@ const resolveCliEntrypoint = () => {
501
502
  //#endregion
502
503
  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
504
 
504
- //# sourceMappingURL=local-broker-CEIHPBcK.mjs.map
505
+ //# sourceMappingURL=local-broker-C9siWyRh.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-broker-C9siWyRh.mjs","names":["isNodeError"],"sources":["../src/daemon/native-target.ts","../src/daemon/broker-command.ts","../src/daemon/lifecycle.ts","../src/daemon/package-version.ts","../src/daemon/paths.ts","../src/local-broker.ts"],"sourcesContent":["export type BrokerPackageOs = \"darwin\" | \"linux\" | \"windows\";\nexport type BrokerArch = \"arm64\" | \"x64\";\n\nexport interface BrokerNativeTarget {\n packageName: string;\n binaryRelativePath: string;\n}\n\nexport const resolveBrokerNativeTarget = (\n platform: string = process.platform,\n arch: string = process.arch,\n): BrokerNativeTarget => {\n const packageOs = platformToPackageOs(platform);\n const nativeArch = normalizeArch(arch);\n return {\n packageName: `@opentray/${packageOs}-${nativeArch}`,\n binaryRelativePath: `bin/${packageOs === \"windows\" ? \"opentray.exe\" : \"opentray\"}`,\n };\n};\n\nconst platformToPackageOs = (platform: string): BrokerPackageOs => {\n switch (platform) {\n case \"darwin\":\n case \"linux\":\n return platform;\n case \"win32\":\n return \"windows\";\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker platform: ${platform}`,\n platform,\n process.arch,\n );\n }\n};\n\nconst normalizeArch = (arch: string): BrokerArch => {\n switch (arch) {\n case \"arm64\":\n case \"x64\":\n return arch;\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker architecture: ${arch}`,\n process.platform,\n arch,\n );\n }\n};\n\nexport class MissingPlatformBrokerBinaryError extends Error {\n readonly code = \"OPENTRAY_MISSING_PLATFORM_BROKER_BINARY\";\n readonly platform: string;\n readonly arch: string;\n readonly packageName: string | undefined;\n readonly binaryPath: string | undefined;\n\n constructor(\n message: string,\n platform: string,\n arch: string,\n options: {\n packageName?: string;\n binaryPath?: string;\n cause?: unknown;\n } = {},\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"MissingPlatformBrokerBinaryError\";\n this.platform = platform;\n this.arch = arch;\n this.packageName = options.packageName;\n this.binaryPath = options.binaryPath;\n }\n}\n","import { access, chmod } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawn } from \"node:child_process\";\n\nimport type { DaemonPaths } from \"./paths\";\nimport { MissingPlatformBrokerBinaryError, resolveBrokerNativeTarget } from \"./native-target\";\n\nexport interface BrokerCommand {\n command: string;\n args: string[];\n cwd?: string;\n}\n\nconst sourceUrl = import.meta.url;\nconst requireFromSource = createRequire(sourceUrl);\n\nexport interface ResolveBrokerCommandOptions {\n env?: NodeJS.ProcessEnv;\n platform?: NodeJS.Platform;\n arch?: string;\n sourceDir?: string;\n resolvePackageJson?: (packageName: string) => string | undefined;\n findWorkspaceRoot?: (start: string) => Promise<string | undefined>;\n ensureDevBrokerBinary?: (workspaceRoot: string) => Promise<string>;\n}\n\nexport const resolveBrokerCommand = async (\n paths: DaemonPaths,\n options: ResolveBrokerCommandOptions = {},\n): Promise<BrokerCommand> => {\n const env = options.env ?? process.env;\n const explicit = env.OPENTRAY_BROKER_BIN;\n if (explicit !== undefined && explicit.length > 0) {\n return commandForBinary(explicit, paths);\n }\n\n const sourceDir = options.sourceDir ?? dirname(fileURLToPath(sourceUrl));\n const workspaceRoot = await (options.findWorkspaceRoot ?? findWorkspaceRoot)(sourceDir);\n if (workspaceRoot !== undefined) {\n const binary = await (options.ensureDevBrokerBinary ?? ensureDevBrokerBinary)(workspaceRoot);\n return commandForBinary(binary, paths, workspaceRoot);\n }\n\n const platform = options.platform ?? process.platform;\n const arch = options.arch ?? process.arch;\n const installedBinary = await resolveInstalledBrokerBinary({\n platform,\n arch,\n resolvePackageJson: options.resolvePackageJson ?? resolvePackageJson,\n });\n if (installedBinary !== undefined) {\n return commandForBinary(installedBinary, paths);\n }\n\n const target = resolveBrokerNativeTarget(platform, arch);\n throw new MissingPlatformBrokerBinaryError(\n `unable to resolve OpenTray broker binary for ${platform}/${arch}; install ${target.packageName} or set OPENTRAY_BROKER_BIN`,\n platform,\n arch,\n { packageName: target.packageName },\n );\n};\n\nconst commandForBinary = (binary: string, paths: DaemonPaths, cwd?: string): BrokerCommand => {\n const command: BrokerCommand = {\n command: binary,\n args: [\n \"broker\",\n \"--endpoint\",\n paths.endpoint,\n \"--ready-file\",\n paths.readyFile,\n \"--package-version\",\n paths.packageVersion,\n \"--protocol-version\",\n `${paths.protocolVersion}`,\n ],\n };\n if (cwd !== undefined) {\n command.cwd = cwd;\n }\n return command;\n};\n\ninterface ResolveInstalledBrokerBinaryOptions {\n platform: NodeJS.Platform;\n arch: string;\n resolvePackageJson: (packageName: string) => string | undefined;\n}\n\nexport const resolveInstalledBrokerBinary = async ({\n platform,\n arch,\n resolvePackageJson,\n}: ResolveInstalledBrokerBinaryOptions): Promise<string | undefined> => {\n const target = resolveBrokerNativeTarget(platform, arch);\n const packageJsonPath = resolvePackageJson(target.packageName);\n if (packageJsonPath === undefined) {\n return undefined;\n }\n\n const binary = join(dirname(packageJsonPath), target.binaryRelativePath);\n if (!(await exists(binary))) {\n throw new MissingPlatformBrokerBinaryError(\n `OpenTray broker package ${target.packageName} is installed but missing ${target.binaryRelativePath}`,\n platform,\n arch,\n {\n packageName: target.packageName,\n binaryPath: binary,\n },\n );\n }\n\n if (platform !== \"win32\") {\n await chmod(binary, 0o755);\n }\n\n return binary;\n};\n\nconst resolvePackageJson = (packageName: string): string | undefined => {\n try {\n return requireFromSource.resolve(`${packageName}/package.json`);\n } catch (error) {\n if (isNodeError(error) && error.code === \"MODULE_NOT_FOUND\") {\n return undefined;\n }\n throw error;\n }\n};\n\nconst findWorkspaceRoot = async (start: string): Promise<string | undefined> => {\n let current = start;\n while (true) {\n if (await exists(join(current, \"Cargo.toml\"))) {\n if (await exists(join(current, \"crates\", \"opentray-bin\", \"Cargo.toml\"))) {\n return current;\n }\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n};\n\nconst ensureDevBrokerBinary = async (workspaceRoot: string): Promise<string> => {\n const binary = join(\n workspaceRoot,\n \"target\",\n \"debug\",\n process.platform === \"win32\" ? \"opentray.exe\" : \"opentray\",\n );\n await runCargoBuild(workspaceRoot);\n return binary;\n};\n\nconst runCargoBuild = (workspaceRoot: string): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn(\"cargo\", [\"build\", \"-p\", \"opentray-bin\"], {\n cwd: workspaceRoot,\n stdio: process.env.OPENTRAY_BROKER_BUILD_LOGS === \"1\" ? \"inherit\" : \"ignore\",\n });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(new Error(`cargo build -p opentray-bin failed with code ${code ?? \"unknown\"}`));\n });\n });\n\nconst exists = async (path: string): Promise<boolean> => {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n};\n\nconst isNodeError = (error: unknown): error is NodeJS.ErrnoException =>\n error instanceof Error && \"code\" in error;\n","import { constants } from \"node:fs\";\nimport { mkdir, open, readFile, rm, unlink, writeFile } from \"node:fs/promises\";\nimport { spawn } from \"node:child_process\";\n\nimport { resolveBrokerCommand } from \"./broker-command\";\nimport type { DaemonPaths } from \"./paths\";\n\nconst DAEMON_STDIO_ENV = \"OPENTRAY_DAEMON_STDIO\";\n\nexport type DaemonStartResult =\n | { status: \"started\"; pid: number; paths: DaemonPaths }\n | { status: \"already-running\"; pid: number; paths: DaemonPaths };\n\nexport type DaemonStopResult =\n | { status: \"stopped\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths };\n\nexport type DaemonInspectResult =\n | { status: \"running\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths; stalePid?: number };\n\nexport interface DaemonDriver {\n isAlive(pid: number): Promise<boolean>;\n spawnBroker(paths: DaemonPaths): Promise<number>;\n stop(pid: number): Promise<void>;\n}\n\nexport interface StartDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n lockTimeoutMs?: number;\n}\n\nexport interface StopDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport interface InspectDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport const createNodeDaemonDriver = (cliEntrypoint: string): DaemonDriver => ({\n async isAlive(pid) {\n return isProcessAlive(pid);\n },\n async spawnBroker(paths) {\n const broker = await resolveBrokerCommand(paths);\n const child = spawn(broker.command, broker.args, {\n cwd: broker.cwd,\n detached: true,\n env: {\n ...process.env,\n OPENTRAY_DAEMON_HOME: paths.homeDir,\n OPENTRAY_DAEMON_PACKAGE_VERSION: paths.packageVersion,\n OPENTRAY_DAEMON_CLI_ENTRYPOINT: cliEntrypoint,\n },\n stdio: resolveBrokerStdio(process.env[DAEMON_STDIO_ENV]),\n });\n\n child.unref();\n return child.pid ?? 0;\n },\n async stop(pid) {\n process.kill(pid, \"SIGTERM\");\n },\n});\n\nexport const resolveBrokerStdio = (\n value: string | undefined,\n): \"ignore\" | \"inherit\" => {\n return value === \"inherit\" ? \"inherit\" : \"ignore\";\n};\n\nexport const startDaemon = async ({\n paths,\n driver,\n lockTimeoutMs = 1_000,\n}: StartDaemonOptions): Promise<DaemonStartResult> => {\n await mkdir(paths.runtimeDir, { recursive: true });\n\n const lock = await acquireLock(paths.lockFile, lockTimeoutMs);\n try {\n const existingPid = await readPid(paths.pidFile);\n if (existingPid !== undefined && (await driver.isAlive(existingPid))) {\n return { status: \"already-running\", pid: existingPid, paths };\n }\n\n await cleanupRuntimeFiles(paths);\n const pid = await driver.spawnBroker(paths);\n if (!Number.isInteger(pid) || pid <= 0) {\n throw new Error(\"daemon broker process did not expose a valid pid\");\n }\n await writeFile(paths.pidFile, `${pid}\\n`, \"utf8\");\n await waitForReadyFile(paths.readyFile, driver, pid);\n return { status: \"started\", pid, paths };\n } finally {\n await lock.release();\n }\n};\n\nexport const stopDaemon = async ({ paths, driver }: StopDaemonOptions): Promise<DaemonStopResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid === undefined || !(await driver.isAlive(pid))) {\n await cleanupRuntimeFiles(paths);\n return { status: \"not-running\", paths };\n }\n\n await driver.stop(pid);\n await waitUntilStopped(driver, pid);\n await cleanupRuntimeFiles(paths);\n return { status: \"stopped\", pid, paths };\n};\n\nexport const restartDaemon = async (options: StartDaemonOptions): Promise<DaemonStartResult> => {\n await stopDaemon({ paths: options.paths, driver: options.driver });\n return startDaemon(options);\n};\n\nexport const inspectDaemon = async ({ paths, driver }: InspectDaemonOptions): Promise<DaemonInspectResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid !== undefined && (await driver.isAlive(pid))) {\n return { status: \"running\", pid, paths };\n }\n\n await cleanupRuntimeFiles(paths);\n return pid === undefined\n ? { status: \"not-running\", paths }\n : { status: \"not-running\", paths, stalePid: pid };\n};\n\nconst readPid = async (pidFile: string): Promise<number | undefined> => {\n try {\n const content = await readFile(pidFile, \"utf8\");\n const pid = Number.parseInt(content.trim(), 10);\n return Number.isInteger(pid) && pid > 0 ? pid : undefined;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n};\n\nconst cleanupRuntimeFiles = async (paths: DaemonPaths): Promise<void> => {\n await rm(paths.readyFile, { force: true });\n await rm(paths.pidFile, { force: true });\n if (process.platform !== \"win32\") {\n await rm(paths.endpoint, { force: true });\n }\n};\n\nconst waitUntilStopped = async (driver: DaemonDriver, pid: number): Promise<void> => {\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (!(await driver.isAlive(pid))) {\n return;\n }\n await sleep(50);\n }\n};\n\nconst waitForReadyFile = async (\n readyFile: string,\n driver: DaemonDriver,\n pid: number,\n): Promise<void> => {\n for (let attempt = 0; attempt < 40; attempt += 1) {\n try {\n await readFile(readyFile, \"utf8\");\n return;\n } catch (error) {\n if (!isNodeError(error) || error.code !== \"ENOENT\") {\n throw error;\n }\n if (!(await driver.isAlive(pid))) {\n throw new Error(\n `daemon broker exited before readiness: pid=${pid}; readyFile=${readyFile}; set ${DAEMON_STDIO_ENV}=inherit to inspect broker stderr`,\n );\n }\n await sleep(50);\n }\n }\n\n throw new Error(`timed out waiting for daemon readiness: ${readyFile}`);\n};\n\nconst acquireLock = async (\n lockFile: string,\n timeoutMs: number,\n): Promise<{\n release(): Promise<void>;\n}> => {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() <= deadline) {\n try {\n const handle = await open(lockFile, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);\n await handle.writeFile(`${process.pid}\\n`, \"utf8\");\n return {\n async release() {\n await handle.close();\n await unlink(lockFile).catch((error: unknown) => {\n if (!isNodeError(error) || error.code !== \"ENOENT\") {\n throw error;\n }\n });\n },\n };\n } catch (error) {\n if (isNodeError(error) && error.code === \"EEXIST\") {\n await sleep(25);\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(`timed out acquiring daemon lock: ${lockFile}`);\n};\n\nconst isProcessAlive = (pid: number): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst isNodeError = (error: unknown): error is NodeJS.ErrnoException =>\n error instanceof Error && \"code\" in error;\n","import { readFile } from \"node:fs/promises\";\n\nexport const readPackageVersion = async (packageJsonUrl: URL): Promise<string> => {\n const value: unknown = JSON.parse(await readFile(packageJsonUrl, \"utf8\"));\n if (!isPackageJsonWithVersion(value)) {\n throw new Error(`package.json is missing a string version: ${packageJsonUrl.href}`);\n }\n\n return value.version;\n};\n\nconst isPackageJsonWithVersion = (value: unknown): value is { version: string } =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n \"version\" in value &&\n typeof value.version === \"string\";\n","import { createBrokerEndpointIdentity, formatUnixSocketPath, formatWindowsPipeName } from \"@opentray/spec\";\n\nexport interface DaemonPathOptions {\n homeDir: string;\n packageVersion: string;\n platform?: NodeJS.Platform;\n}\n\nexport interface DaemonPaths {\n homeDir: string;\n packageVersion: string;\n protocolVersion: number;\n stateRoot: string;\n runtimeDir: string;\n endpoint: string;\n pidFile: string;\n lockFile: string;\n readyFile: string;\n}\n\nexport const resolveDaemonPaths = ({\n homeDir,\n packageVersion,\n platform = process.platform,\n}: DaemonPathOptions): DaemonPaths => {\n const identity = createBrokerEndpointIdentity({ packageVersion });\n const normalizedHome = homeDir.replace(/[\\\\/]+$/u, \"\");\n const stateRoot = `${normalizedHome}/.opentray/${identity.packageVersion}`;\n const runtimeDir = `${stateRoot}/runtime`;\n const endpoint =\n platform === \"win32\" ? formatWindowsPipeName(identity) : formatUnixSocketPath(normalizedHome, identity);\n\n return {\n homeDir: normalizedHome,\n packageVersion: identity.packageVersion,\n protocolVersion: identity.protocolVersion,\n stateRoot,\n runtimeDir,\n endpoint,\n pidFile: `${runtimeDir}/broker.pid`,\n lockFile: `${runtimeDir}/broker.lock`,\n readyFile: `${runtimeDir}/ready.json`,\n };\n};\n","import { createConnection, type Socket } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n PROTOCOL_VERSION,\n parseServerFrame,\n type BrokerEndpointIdentityOptions,\n type ClientRequestFrame,\n type RequestId,\n type ServerFrame,\n} from \"@opentray/spec\";\n\nimport type { OpenTrayTransport } from \"./client\";\nimport { createNodeDaemonDriver, startDaemon, type DaemonDriver } from \"./daemon/lifecycle\";\nimport { readPackageVersion } from \"./daemon/package-version\";\nimport { resolveDaemonPaths } from \"./daemon/paths\";\n\nconst packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n\nexport type BrokerEventFrame = Extract<ServerFrame, { type: \"event\" | \"ext-event\" }>;\n\nexport interface LocalBrokerClient extends OpenTrayTransport {\n readonly endpoint: string;\n readonly sessionId: string;\n /** @deprecated Use `sessionId`. */\n readonly leaseId: string;\n onEvent(listener: (frame: BrokerEventFrame) => void): () => void;\n close(): Promise<void>;\n}\n\nexport interface ConnectLocalBrokerOptions extends Partial<BrokerEndpointIdentityOptions> {\n endpoint?: string;\n homeDir?: string;\n clientVersion?: string;\n autoStart?: boolean;\n daemonDriver?: DaemonDriver;\n cliEntrypoint?: string;\n}\n\ninterface PendingRequest {\n resolve(frame: ServerFrame): void;\n reject(error: Error): void;\n}\n\ninterface BrokerSocket {\n setEncoding(encoding: BufferEncoding): void;\n on(event: \"data\", listener: (chunk: Buffer | string) => void): void;\n on(event: \"error\", listener: (error: Error) => void): void;\n on(event: \"close\", listener: () => void): void;\n once(event: \"connect\", listener: () => void): void;\n once(event: \"error\", listener: (error: Error) => void): void;\n off(event: \"error\", listener: (error: Error) => void): void;\n write(data: string): void;\n end(callback: () => void): void;\n}\n\nexport const connectLocalBroker = async (\n options: ConnectLocalBrokerOptions = {},\n): Promise<LocalBrokerClient> => {\n const packageVersion = options.packageVersion ?? (await readPackageVersion(packageJsonUrl));\n const clientVersion = options.clientVersion ?? packageVersion;\n const paths = resolveDaemonPaths({\n homeDir: options.homeDir ?? process.env.OPENTRAY_HOME ?? homedir(),\n packageVersion,\n });\n const endpoint = options.endpoint ?? paths.endpoint;\n const autoStart = options.autoStart ?? endpoint === paths.endpoint;\n if (autoStart && endpoint !== paths.endpoint) {\n throw new Error(\"local broker autoStart requires the derived same-version endpoint\");\n }\n if (autoStart) {\n const cliEntrypoint = options.cliEntrypoint ?? resolveCliEntrypoint();\n const driver = options.daemonDriver ?? createNodeDaemonDriver(cliEntrypoint);\n await startDaemon({ paths, driver });\n }\n const socket = await connectSocket(endpoint);\n const connection = new LocalBrokerConnection(socket, endpoint);\n\n await connection.init(clientVersion, options.protocolVersion ?? PROTOCOL_VERSION);\n return connection;\n};\n\nclass LocalBrokerConnection implements LocalBrokerClient {\n readonly endpoint: string;\n sessionId = \"\";\n /** @deprecated Use `sessionId`. */\n leaseId = \"\";\n\n private buffer = \"\";\n private readonly listeners = new Set<(frame: BrokerEventFrame) => void>();\n private readonly pending = new Map<RequestId, PendingRequest>();\n private ready:\n | {\n resolve(frame: Extract<ServerFrame, { type: \"ready\" }>): void;\n reject(error: Error): void;\n }\n | undefined;\n\n constructor(\n private readonly socket: BrokerSocket,\n endpoint: string,\n ) {\n this.endpoint = endpoint;\n socket.setEncoding(\"utf8\");\n socket.on(\"data\", (chunk: Buffer | string) => {\n this.consume(String(chunk));\n });\n socket.on(\"error\", (error) => {\n this.rejectAll(error);\n });\n socket.on(\"close\", () => {\n this.rejectAll(new Error(\"broker connection closed\"));\n });\n }\n\n async init(clientVersion: string, protocolVersion: number): Promise<void> {\n const ready = new Promise<Extract<ServerFrame, { type: \"ready\" }>>((resolve, reject) => {\n this.ready = { resolve, reject };\n });\n this.write({\n type: \"init\",\n protocolVersion,\n clientVersion,\n });\n const frame = await ready;\n this.sessionId = frame.sessionId;\n this.leaseId = frame.sessionId;\n }\n\n async request(frame: ClientRequestFrame): Promise<ServerFrame> {\n if (this.pending.has(frame.requestId)) {\n throw new Error(`duplicate requestId: ${frame.requestId}`);\n }\n\n const response = new Promise<ServerFrame>((resolve, reject) => {\n this.pending.set(frame.requestId, { resolve, reject });\n });\n this.write(frame);\n return response;\n }\n\n onEvent(listener: (frame: BrokerEventFrame) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n async close(): Promise<void> {\n this.write({ type: \"exit\" });\n await new Promise<void>((resolve) => {\n this.socket.end(resolve);\n });\n }\n\n private consume(chunk: string): void {\n this.buffer += chunk;\n while (true) {\n const newline = this.buffer.indexOf(\"\\n\");\n if (newline < 0) {\n return;\n }\n\n const line = this.buffer.slice(0, newline).trim();\n this.buffer = this.buffer.slice(newline + 1);\n if (line.length > 0) {\n this.dispatchLine(line);\n }\n }\n }\n\n private dispatchLine(line: string): void {\n const parsed = parseServerFrame(line);\n if (!parsed.ok || parsed.frame === undefined) {\n this.rejectAll(new Error(parsed.error ?? \"invalid server frame\"));\n return;\n }\n\n this.dispatchFrame(parsed.frame);\n }\n\n private dispatchFrame(frame: ServerFrame): void {\n if (frame.type === \"ready\") {\n this.ready?.resolve(frame);\n this.ready = undefined;\n return;\n }\n\n if (frame.type === \"error\") {\n const error = new Error(`${frame.code}: ${frame.message}`);\n if (frame.requestId !== undefined) {\n this.pending.get(frame.requestId)?.reject(error);\n this.pending.delete(frame.requestId);\n return;\n }\n this.ready?.reject(error);\n this.ready = undefined;\n return;\n }\n\n const requestId = responseRequestId(frame);\n if (requestId !== undefined) {\n // Request responses and broker events are separate streams even on one socket.\n this.pending.get(requestId)?.resolve(frame);\n this.pending.delete(requestId);\n return;\n }\n\n if (frame.type === \"event\" || frame.type === \"ext-event\") {\n for (const listener of this.listeners) {\n listener(frame);\n }\n }\n }\n\n private write(frame: unknown): void {\n this.socket.write(`${JSON.stringify(frame)}\\n`);\n }\n\n private rejectAll(error: Error): void {\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.clear();\n }\n}\n\nconst connectSocket = (endpoint: string): Promise<BrokerSocket> =>\n new Promise((resolve, reject) => {\n const socket = createConnection(endpoint);\n socket.once(\"connect\", () => {\n socket.off(\"error\", reject);\n resolve(socket);\n });\n socket.once(\"error\", reject);\n });\n\nconst responseRequestId = (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 \"daemon-health\":\n return frame.requestId;\n case \"ready\":\n case \"event\":\n case \"ext-event\":\n case \"error\":\n return undefined;\n }\n};\n\nconst resolveCliEntrypoint = (): string => {\n const suffix = fileURLToPath(import.meta.url).endsWith(\".ts\") ? \"cli.ts\" : \"cli.mjs\";\n return fileURLToPath(new URL(`./${suffix}`, import.meta.url));\n};\n"],"mappings":"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"}
package/dist/node.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as OpenTrayTransport } from "./client-h6gZdeOk.mjs";
1
+ import { i as OpenTrayTransport } from "./client-DQn3DLZw.mjs";
2
2
  import { BrokerEndpointIdentityOptions, ServerFrame } from "@opentray/spec";
3
3
 
4
4
  //#region src/daemon/paths.d.ts
package/dist/node.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as connectLocalBroker } from "./local-broker-CEIHPBcK.mjs";
1
+ import { t as connectLocalBroker } from "./local-broker-C9siWyRh.mjs";
2
2
  export { connectLocalBroker };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentray",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Developer-facing OpenTray SDK and CLI package.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,12 +24,11 @@
24
24
  },
25
25
  "files": [
26
26
  "dist",
27
- "assets",
28
27
  "README.md"
29
28
  ],
30
29
  "sideEffects": false,
31
30
  "dependencies": {
32
- "@opentray/spec": "0.4.0"
31
+ "@opentray/spec": "0.4.1"
33
32
  },
34
33
  "devDependencies": {
35
34
  "tsdown": "^0.22.1",
@@ -37,12 +36,12 @@
37
36
  "vitest": "^4.1.7"
38
37
  },
39
38
  "optionalDependencies": {
40
- "@opentray/darwin-arm64": "0.5.1",
41
- "@opentray/darwin-x64": "0.5.1",
42
- "@opentray/linux-arm64": "0.5.1",
43
- "@opentray/linux-x64": "0.5.1",
44
- "@opentray/windows-arm64": "0.5.1",
45
- "@opentray/windows-x64": "0.5.1"
39
+ "@opentray/darwin-arm64": "0.6.0",
40
+ "@opentray/darwin-x64": "0.6.0",
41
+ "@opentray/linux-arm64": "0.6.0",
42
+ "@opentray/linux-x64": "0.6.0",
43
+ "@opentray/windows-arm64": "0.6.0",
44
+ "@opentray/windows-x64": "0.6.0"
46
45
  },
47
46
  "scripts": {
48
47
  "build": "tsdown src/index.ts src/node.ts src/cli.ts --format esm --dts",
@@ -1,14 +0,0 @@
1
- ## Lynx Review Bundle
2
-
3
- This directory contains the package-owned Lynx review bundle used by the public CLI smoke:
4
-
5
- ```bash
6
- opentray smoke daemon-lynx
7
- ```
8
-
9
- The goal is post-publish human verification. A fresh npm install must be able to open a real Lynx window without depending on a workspace checkout or `research/` paths.
10
-
11
- TODO:
12
-
13
- - move the source of this review app into a tracked repo-owned source root instead of relying on a copied research build artifact
14
- - keep the bundle focused on visual/runtime acceptance, not on product features unrelated to extension-host verification
Binary file
@@ -1,111 +0,0 @@
1
- import { PROTOCOL_VERSION } from "@opentray/spec";
2
- //#region src/client.ts
3
- const createInitFrame = (clientVersion) => ({
4
- type: "init",
5
- protocolVersion: PROTOCOL_VERSION,
6
- clientVersion
7
- });
8
- const createClient = (transport, options = {}) => {
9
- const nextRequestId = createRequestIdFactory(options.requestIdPrefix ?? "opentray");
10
- return {
11
- async createSpace(spaceOptions) {
12
- const requestId = nextRequestId();
13
- const space = expectResponse(await transport.request({
14
- type: "create-space",
15
- requestId,
16
- ...spaceOptions
17
- }), requestId, "space-created").space;
18
- return createSpaceHandle(transport, space, nextRequestId);
19
- },
20
- async resolveDefaultSpace() {
21
- const requestId = nextRequestId();
22
- const space = expectResponse(await transport.request({
23
- type: "resolve-default-space",
24
- requestId
25
- }), requestId, "default-space").space;
26
- return createSpaceHandle(transport, space, nextRequestId);
27
- },
28
- async createSurface(spaceOptions) {
29
- return this.createSpace(spaceOptions);
30
- }
31
- };
32
- };
33
- const createSpaceHandle = (transport, space, nextRequestId = createRequestIdFactory("opentray")) => ({
34
- space,
35
- async createTray(options) {
36
- const requestId = nextRequestId();
37
- return createTrayHandle(transport, space, expectResponse(await transport.request({
38
- type: "create-tray",
39
- requestId,
40
- space,
41
- tray: options
42
- }), requestId, "tray-created").trayId, nextRequestId);
43
- }
44
- });
45
- /** @deprecated Use `createSpaceHandle`. */
46
- const createSurfaceHandle = createSpaceHandle;
47
- const createTrayHandle = (transport, space, trayId, nextRequestId = createRequestIdFactory("opentray")) => ({
48
- space,
49
- trayId,
50
- async getBounds() {
51
- const requestId = nextRequestId();
52
- return expectResponse(await transport.request({
53
- type: "get-tray-bounds",
54
- requestId,
55
- spaceId: space.spaceId,
56
- trayId
57
- }), requestId, "tray-bounds").bounds;
58
- },
59
- async commandExtension(ext, data) {
60
- const requestId = nextRequestId();
61
- expectResponse(await transport.request({
62
- type: "ext-command",
63
- requestId,
64
- spaceId: space.spaceId,
65
- trayId,
66
- ext,
67
- data
68
- }), requestId, "ack");
69
- },
70
- async destroy() {
71
- const requestId = nextRequestId();
72
- expectResponse(await transport.request({
73
- type: "destroy-tray",
74
- requestId,
75
- spaceId: space.spaceId,
76
- trayId
77
- }), requestId, "ack");
78
- }
79
- });
80
- const createRequestIdFactory = (prefix) => {
81
- let next = 1;
82
- return () => {
83
- const requestId = `${prefix}-${next}`;
84
- next += 1;
85
- return requestId;
86
- };
87
- };
88
- const expectResponse = (frame, requestId, type) => {
89
- if (frame.type === "error") throw new Error(`${frame.code}: ${frame.message}`);
90
- if (frame.type !== type) throw new Error(`expected ${type} for ${requestId}, received ${frame.type}`);
91
- if (requestIdOf(frame) !== requestId) throw new Error(`expected response for ${requestId}, received ${requestIdOf(frame) ?? "none"}`);
92
- return frame;
93
- };
94
- const requestIdOf = (frame) => {
95
- switch (frame.type) {
96
- case "space-created":
97
- case "default-space":
98
- case "tray-created":
99
- case "tray-bounds":
100
- case "ack":
101
- case "daemon-health": return frame.requestId;
102
- case "error": return frame.requestId;
103
- case "ready":
104
- case "event":
105
- case "ext-event": return;
106
- }
107
- };
108
- //#endregion
109
- export { createTrayHandle as a, createSurfaceHandle as i, createInitFrame as n, createSpaceHandle as r, createClient as t };
110
-
111
- //# sourceMappingURL=client-B_zxQOo5.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-B_zxQOo5.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import {\n PROTOCOL_VERSION,\n type ClientFrame,\n type ClientRequestFrame,\n type RequestId,\n type ServerFrame,\n type SpaceOptions,\n type SpaceRef,\n type TrayBoundsResult,\n type TrayId,\n type TrayOptions,\n} from \"@opentray/spec\";\n\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame): Promise<ServerFrame>;\n}\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\n/** @deprecated Use `SpaceHandle`. */\nexport type SurfaceHandle = SpaceHandle;\n\nexport interface TrayHandle {\n space: SpaceRef;\n trayId: TrayId;\n getBounds(): Promise<TrayBoundsResult>;\n commandExtension(ext: string, data: unknown): Promise<void>;\n destroy(): Promise<void>;\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 const createClient = (\n transport: OpenTrayTransport,\n options: CreateClientOptions = {},\n): OpenTrayClient => {\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 const createSpaceHandle = (\n transport: OpenTrayTransport,\n space: SpaceRef,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): SpaceHandle => ({\n space,\n async createTray(options: TrayOptions): Promise<TrayHandle> {\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/** @deprecated Use `createSpaceHandle`. */\nexport const createSurfaceHandle = createSpaceHandle;\n\nexport const createTrayHandle = (\n transport: OpenTrayTransport,\n space: SpaceRef,\n trayId: TrayId,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\"),\n): 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 commandExtension(ext: string, data: unknown): Promise<void> {\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 expectResponse(response, requestId, \"ack\");\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\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 \"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"],"mappings":";;AAwCA,MAAa,mBAAmB,mBAAwC;CACtE,MAAM;CACN,iBAAiB;CACjB;AACF;AAMA,MAAa,gBACX,WACA,UAA+B,CAAC,MACb;CACnB,MAAM,gBAAgB,uBAAuB,QAAQ,mBAAmB,UAAU;CAElF,OAAO;EACL,MAAM,YAAY,cAAoC;GACpD,MAAM,YAAY,cAAc;GAMhC,MAAM,QAAQ,eAAe,MALN,UAAU,QAAQ;IACvC,MAAM;IACN;IACA,GAAG;GACL,CAAC,GACsC,WAAW,eAAe,EAAE;GACnE,OAAO,kBAAkB,WAAW,OAAO,aAAa;EAC1D;EACA,MAAM,sBAA4C;GAChD,MAAM,YAAY,cAAc;GAKhC,MAAM,QAAQ,eAAe,MAJN,UAAU,QAAQ;IACvC,MAAM;IACN;GACF,CAAC,GACsC,WAAW,eAAe,EAAE;GACnE,OAAO,kBAAkB,WAAW,OAAO,aAAa;EAC1D;EACA,MAAM,cAAc,cAAoC;GACtD,OAAO,KAAK,YAAY,YAAY;EACtC;CACF;AACF;AAEA,MAAa,qBACX,WACA,OACA,gBAAiC,uBAAuB,UAAU,OACjD;CACjB;CACA,MAAM,WAAW,SAA2C;EAC1D,MAAM,YAAY,cAAc;EAQhC,OAAO,iBAAiB,WAAW,OADrB,eAAe,MANN,UAAU,QAAQ;GACvC,MAAM;GACN;GACA;GACA,MAAM;EACR,CAAC,GACsC,WAAW,cACJ,EAAE,QAAQ,aAAa;CACvE;AACF;;AAGA,MAAa,sBAAsB;AAEnC,MAAa,oBACX,WACA,OACA,QACA,gBAAiC,uBAAuB,UAAU,OAClD;CAChB;CACA;CACA,MAAM,YAAuC;EAC3C,MAAM,YAAY,cAAc;EAOhC,OAAO,eAAe,MANC,UAAU,QAAQ;GACvC,MAAM;GACN;GACA,SAAS,MAAM;GACf;EACF,CAAC,GAC+B,WAAW,aAAa,EAAE;CAC5D;CACA,MAAM,iBAAiB,KAAa,MAA8B;EAChE,MAAM,YAAY,cAAc;EAShC,eAAe,MARQ,UAAU,QAAQ;GACvC,MAAM;GACN;GACA,SAAS,MAAM;GACf;GACA;GACA;EACF,CAAC,GACwB,WAAW,KAAK;CAC3C;CACA,MAAM,UAAyB;EAC7B,MAAM,YAAY,cAAc;EAOhC,eAAe,MANQ,UAAU,QAAQ;GACvC,MAAM;GACN;GACA,SAAS,MAAM;GACf;EACF,CAAC,GACwB,WAAW,KAAK;CAC3C;AACF;AAEA,MAAM,0BAA0B,WAAsC;CACpE,IAAI,OAAO;CACX,aAAa;EACX,MAAM,YAAY,GAAG,OAAO,GAAG;EAC/B,QAAQ;EACR,OAAO;CACT;AACF;AAEA,MAAM,kBACJ,OACA,WACA,SAC0C;CAC1C,IAAI,MAAM,SAAS,SACjB,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,IAAI,MAAM,SAAS;CAEnD,IAAI,MAAM,SAAS,MACjB,MAAM,IAAI,MAAM,YAAY,KAAK,OAAO,UAAU,aAAa,MAAM,MAAM;CAE7E,IAAI,YAAY,KAAK,MAAM,WACzB,MAAM,IAAI,MAAM,yBAAyB,UAAU,aAAa,YAAY,KAAK,KAAK,QAAQ;CAEhG,OAAO;AACT;AAEA,MAAM,eAAe,UAA8C;CACjE,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,iBACH,OAAO,MAAM;EACf,KAAK,SACH,OAAO,MAAM;EACf,KAAK;EACL,KAAK;EACL,KAAK,aACH;CACJ;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-h6gZdeOk.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;UAaiB,iBAAA;EACf,OAAA,CAAQ,KAAA,EAAO,kBAAA,GAAqB,OAAA,CAAQ,WAAA;AAAA;AAAA,UAG7B,cAAA;EACf,WAAA,CAAY,OAAA,EAAS,YAAA,GAAe,OAAA,CAAQ,WAAA;EAC5C,mBAAA,IAAuB,OAAA,CAAQ,WAAA;EALa;EAO5C,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;;KAIhC,aAAA,GAAgB,WAAW;AAAA,UAEtB,UAAA;EACf,KAAA,EAAO,QAAA;EACP,MAAA,EAAQ,MAAA;EACR,SAAA,IAAa,OAAA,CAAQ,gBAAA;EACrB,gBAAA,CAAiB,GAAA,UAAa,IAAA,YAAgB,OAAA;EAC9C,OAAA,IAAW,OAAA;AAAA;AAAA,cAGA,eAAA,GAAmB,aAAA,aAAwB,WAItD;AAAA,UAEe,mBAAA;EACf,eAAe;AAAA;AAAA,cAGJ,YAAA,GACX,SAAA,EAAW,iBAAA,EACX,OAAA,GAAS,mBAAA,KACR,cAAA;AAAA,cA6BU,iBAAA,GACX,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,aAAA,SAAqB,SAAA,KACpB,WAAA;;cAgBU,mBAAA,GAAmB,SAAA,EAnBnB,iBAAA,EAAiB,KAAA,EACrB,QAAA,EAAQ,aAAA,SACM,SAAA,KACpB,WAAA;AAAA,cAkBU,gBAAA,GACX,SAAA,EAAW,iBAAA,EACX,KAAA,EAAO,QAAA,EACP,MAAA,EAAQ,MAAA,EACR,aAAA,SAAqB,SAAA,KACpB,UAAA"}