opentray 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -25,6 +25,28 @@ Run a protocol-only example that creates a space, creates a tray, dispatches an
25
25
  pnpm --filter opentray example:basic
26
26
  ```
27
27
 
28
+ The top-level SDK now exposes the mainline broker-backed path directly:
29
+
30
+ ```ts
31
+ import { createSpace, createTray, resolveDefaultSpace } from "opentray";
32
+
33
+ const space = await createSpace({ id: "com.example.status", default: true });
34
+ await space.createTray({
35
+ trayId: "status",
36
+ title: "Status",
37
+ icon: { type: "rgba", data: [0, 0, 0, 0], width: 1, height: 1 },
38
+ });
39
+
40
+ const defaultSpace = await resolveDefaultSpace();
41
+ await createTray({
42
+ trayId: "secondary",
43
+ title: "Secondary",
44
+ icon: { type: "rgba", data: [0, 0, 0, 0], width: 1, height: 1 },
45
+ }, { space: defaultSpace.space });
46
+ ```
47
+
48
+ `createTray()` resolves the broker default space when no explicit target is provided. If you already know the target, pass `space: defaultSpace.space` in the second argument instead of relying on default-space lookup.
49
+
28
50
  Run the human-visible daemon tray example:
29
51
 
30
52
  ```bash
@@ -35,6 +57,7 @@ After installing from npm, use the published CLI smoke path instead of workspace
35
57
 
36
58
  ```bash
37
59
  opentray smoke daemon-tray
60
+ opentray smoke daemon-lynx --bundle ./research/lynx/app/dist/main.lynx.bundle
38
61
  ```
39
62
 
40
63
  This example starts or reuses the same-version daemon automatically, creates a real tray through the public SDK, and prints broker-routed menu events. Use manual lifecycle commands only for operator/debug control:
@@ -49,15 +72,21 @@ The menu includes `WebView Commands` entries that call the `@opentray/ext-webvie
49
72
 
50
73
  The `Show HTML` demo also enables the injected page bridge so the rendered page can call `navigator.window` / `navigator.opentrayWindow` and, for the demo only, opt into `window.close()` / `window.moveTo()` / `window.resizeTo()` overrides. Use the in-page buttons to verify `getCapabilities`, `getStyle`, `setStyle({ frameless })`, move, resize, and close behavior visually instead of relying only on terminal logs.
51
74
 
52
- First-stage platform packages are published for macOS, Linux, and Windows. macOS is the current human-visual acceptance path. Linux and Windows artifacts are present for package topology validation, but unsupported broker/WebView capability must fail explicitly rather than pretending a visible UI exists.
75
+ The Lynx smoke path uses the same generic extension loader but launches a real `LynxExplorer.app.zip` runtime sidecar from `@opentray/ext-lynx-darwin-*`. It starts the requested `.lynx.bundle` immediately on run and exposes `Reload Bundle`, `Hide Window`, and `Quit Smoke` through tray-routed events.
76
+
77
+ First-stage platform packages are published for macOS, Linux, and Windows. macOS is the current human-visual acceptance path. Linux and Windows artifacts are present for package topology validation, but unsupported broker/WebView capability must fail explicitly rather than pretending a visible UI exists. Lynx is intentionally macOS-first for now and should fail honestly on other platforms instead of pretending the runtime exists.
53
78
 
54
79
  For local native smoke before npm publish, stage the current platform artifacts first:
55
80
 
56
81
  ```bash
57
- cargo build -p opentray-bin -p opentray-ext-webview
82
+ cargo build -p opentray-bin -p opentray-ext-webview -p opentray-ext-lynx
58
83
  bun run scripts/binaries/stage-local.ts --kind daemon --source target/debug/opentray
59
84
  bun run scripts/binaries/stage-local.ts --kind webview --source target/debug/libopentray_ext_webview.dylib
85
+ bun run scripts/binaries/stage-local.ts --kind lynx --source target/debug/libopentray_ext_lynx.dylib
86
+ bash scripts/release/build-lynx-runtime.sh /tmp/LynxExplorer.app.zip
87
+ bun run scripts/binaries/stage-local.ts --kind lynx-runtime --source /tmp/LynxExplorer.app.zip
60
88
  OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray cli -- smoke daemon-tray
89
+ pnpm --filter opentray cli -- smoke daemon-lynx --bundle ./research/lynx/app/dist/main.lynx.bundle
61
90
  ```
62
91
 
63
92
  The daemon exits automatically after 30 seconds with no connected clients. Set `OPENTRAY_DAEMON_IDLE_TIMEOUT_MS=0` to keep it alive during debugging, or provide another millisecond value for a custom idle release window.
@@ -65,10 +94,11 @@ The daemon exits automatically after 30 seconds with no connected clients. Set `
65
94
  To confirm the native runtime split on macOS after a release build:
66
95
 
67
96
  ```bash
68
- cargo build -p opentray-bin -p opentray-ext-webview --release
69
- wc -c target/release/opentray target/release/libopentray_ext_webview.dylib
97
+ cargo build -p opentray-bin -p opentray-ext-webview -p opentray-ext-lynx --release
98
+ wc -c target/release/opentray target/release/libopentray_ext_webview.dylib target/release/libopentray_ext_lynx.dylib
70
99
  otool -L target/release/opentray
71
100
  otool -L target/release/libopentray_ext_webview.dylib
101
+ otool -L target/release/libopentray_ext_lynx.dylib
72
102
  ```
73
103
 
74
104
  Current native icon support is `rgba`. `encoded` and `file` are typed protocol shapes, but the native `tray-icon` backend reports them as unsupported until decoding and file loading policy are implemented.
package/dist/cli.d.mts CHANGED
@@ -7,6 +7,10 @@ type CliCommand = {
7
7
  } | {
8
8
  type: "smoke";
9
9
  name: "daemon-tray";
10
+ } | {
11
+ type: "smoke";
12
+ name: "daemon-lynx";
13
+ bundlePath?: string;
10
14
  } | {
11
15
  type: "help";
12
16
  };
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.mts","names":[],"sources":["../src/cli.ts"],"mappings":";;;KAgBK,UAAA;EACC,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;EAAe,IAAA;AAAA;EACf,IAAA;AAAA;AAAA,cAEO,eAAA,GAAmB,IAAA,eAAiB,UAahD;AAAA,cAEY,MAAA,GAAgB,IAAA,eAAiB,OAAO;AAAA,cA+ExC,wBAAA,GAA4B,MAAoB,EAAZ,YAAY;AAAA,cAoBhD,eAAA,GAAmB,aAAA,sBAAmC,UAAkB"}
1
+ {"version":3,"file":"cli.d.mts","names":[],"sources":["../src/cli.ts"],"mappings":";;;KAiBK,UAAA;EACC,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;EAAe,IAAA;AAAA;EACf,IAAA;EAAe,IAAA;EAAqB,UAAA;AAAA;EACpC,IAAA;AAAA;AAAA,cAEO,eAAA,GAAmB,IAAA,eAAiB,UAmBhD;AAAA,cAEY,MAAA,GAAgB,IAAA,eAAiB,OAAO;AAAA,cAsFxC,wBAAA,GAA4B,MAAoB,EAAZ,YAAY;AAAA,cAoBhD,eAAA,GAAmB,aAAA,sBAAmC,UAAkB"}
package/dist/cli.mjs CHANGED
@@ -1,9 +1,166 @@
1
1
  #!/usr/bin/env node
2
- import { t as createClient } from "./client-BBJON7c4.mjs";
2
+ import { t as createClient } from "./client-Db-tztnj.mjs";
3
3
  import { a as inspectDaemon, c as stopDaemon, i as createNodeDaemonDriver, n as resolveDaemonPaths, o as restartDaemon, r as readPackageVersion, s as startDaemon, t as connectLocalBroker } from "./local-broker-mQmeVLF5.mjs";
4
4
  import { homedir } from "node:os";
5
5
  import { fileURLToPath } from "node:url";
6
- import { realpathSync } from "node:fs";
6
+ import { existsSync, realpathSync } from "node:fs";
7
+ import { resolve } from "node:path";
8
+ //#region src/smoke/daemon-lynx.ts
9
+ const menuLabels$1 = new Map([
10
+ [1, "Reload Bundle"],
11
+ [2, "Hide Window"],
12
+ [99, "Quit Smoke"]
13
+ ]);
14
+ const DEFAULT_LYNX_BUNDLE_ENV = "OPENTRAY_LYNX_BUNDLE";
15
+ const runDaemonLynxSmoke = async (options = {}) => {
16
+ const bundlePath = resolveLynxBundlePath(options.bundlePath);
17
+ const connection = await connectLocalBroker();
18
+ const client = createClient(connection, { requestIdPrefix: "daemon-lynx" });
19
+ console.log(`connected: endpoint=${connection.endpoint} session=${connection.sessionId}`);
20
+ const space = await client.createSpace({
21
+ id: "com.example.opentray.daemon-lynx",
22
+ title: "OpenTray Lynx Smoke",
23
+ default: true
24
+ });
25
+ console.log(`space: ${JSON.stringify(space.space)}`);
26
+ const tray = await space.createTray({
27
+ trayId: "daemon-lynx-status",
28
+ title: "OpenTray Lynx",
29
+ tooltip: {
30
+ title: "OpenTray Lynx",
31
+ description: "Generic extension smoke for a real Lynx runtime window"
32
+ },
33
+ icon: createVisibleIcon$1(),
34
+ menu: { items: [
35
+ {
36
+ type: "item",
37
+ id: 1,
38
+ title: "Reload Bundle"
39
+ },
40
+ {
41
+ type: "item",
42
+ id: 2,
43
+ title: "Hide Window"
44
+ },
45
+ { type: "separator" },
46
+ {
47
+ type: "item",
48
+ id: 99,
49
+ title: "Quit Smoke"
50
+ }
51
+ ] }
52
+ });
53
+ console.log(`tray: ${tray.trayId}`);
54
+ await connection.request({
55
+ type: "load-ext",
56
+ requestId: "daemon-lynx-load",
57
+ spaceId: space.space.spaceId,
58
+ name: "lynx",
59
+ path: "@opentray/ext-lynx"
60
+ });
61
+ console.log("lynx extension requested through the generic load-ext path");
62
+ let closed = false;
63
+ let exitTimer;
64
+ let resolveClosed;
65
+ const show = async () => {
66
+ await tray.commandExtension("lynx", {
67
+ type: "show",
68
+ bundlePath
69
+ });
70
+ console.log(`lynx command: show bundle=${bundlePath}`);
71
+ };
72
+ const hide = async () => {
73
+ await tray.commandExtension("lynx", { type: "hide" });
74
+ console.log("lynx command: hide");
75
+ };
76
+ const shutdown = async () => {
77
+ if (closed) return;
78
+ closed = true;
79
+ if (exitTimer !== void 0) clearTimeout(exitTimer);
80
+ process.off("SIGINT", onSignal);
81
+ process.off("SIGTERM", onSignal);
82
+ try {
83
+ await hide();
84
+ } catch (error) {
85
+ console.error(`lynx hide during shutdown failed: ${String(error)}`);
86
+ }
87
+ await connection.close();
88
+ resolveClosed?.();
89
+ };
90
+ const handleMenuClick = async (itemId) => {
91
+ switch (itemId) {
92
+ case 1:
93
+ await show();
94
+ return;
95
+ case 2:
96
+ await hide();
97
+ return;
98
+ case 99:
99
+ console.log("quit item routed; closing lynx smoke connection");
100
+ await shutdown();
101
+ return;
102
+ default: return;
103
+ }
104
+ };
105
+ connection.onEvent((frame) => {
106
+ console.log(`broker -> client ${JSON.stringify(frame)}`);
107
+ if (frame.type === "event" && frame.event.type === "menuClick") {
108
+ console.log(`menu click: ${menuLabels$1.get(frame.event.itemId) ?? frame.event.itemId}`);
109
+ handleMenuClick(frame.event.itemId);
110
+ return;
111
+ }
112
+ if (frame.type === "ext-event" && frame.ext === "lynx") console.log(`lynx event: ${JSON.stringify(frame.data)}`);
113
+ });
114
+ const onSignal = () => {
115
+ shutdown();
116
+ };
117
+ process.on("SIGINT", onSignal);
118
+ process.on("SIGTERM", onSignal);
119
+ const exitAfter = process.env.OPENTRAY_EXAMPLE_EXIT_AFTER_MS;
120
+ if (exitAfter !== void 0 && exitAfter.length > 0) {
121
+ const duration = Number.parseInt(exitAfter, 10);
122
+ if (Number.isInteger(duration) && duration > 0) exitTimer = setTimeout(() => {
123
+ shutdown();
124
+ }, duration);
125
+ }
126
+ try {
127
+ await show();
128
+ console.log("use the tray menu to reload or hide the Lynx window, or press Ctrl+C to exit");
129
+ } catch (error) {
130
+ await connection.close();
131
+ process.off("SIGINT", onSignal);
132
+ process.off("SIGTERM", onSignal);
133
+ throw error;
134
+ }
135
+ await new Promise((resolve) => {
136
+ resolveClosed = resolve;
137
+ });
138
+ };
139
+ const resolveLynxBundlePath = (value) => {
140
+ const resolved = value ?? process.env[DEFAULT_LYNX_BUNDLE_ENV];
141
+ if (resolved === void 0 || resolved.length === 0) throw new Error(`lynx smoke requires --bundle <path> or ${DEFAULT_LYNX_BUNDLE_ENV}=<path-to-main.lynx.bundle>`);
142
+ const absolutePath = resolve(process.env.INIT_CWD ?? process.cwd(), resolved);
143
+ if (!existsSync(absolutePath)) throw new Error(`lynx smoke bundle does not exist: ${absolutePath}`);
144
+ return realpathSync(absolutePath);
145
+ };
146
+ function createVisibleIcon$1() {
147
+ const width = 32;
148
+ const height = 32;
149
+ const data = [];
150
+ for (let y = 0; y < height; y += 1) for (let x = 0; x < width; x += 1) {
151
+ const inStroke = x <= 5 || x >= 13 && x <= 18 || y >= 26;
152
+ const inDiagonal = y >= x + 10 && x <= 18;
153
+ const alpha = inStroke || inDiagonal ? 255 : 0;
154
+ data.push(34, 92, 56, alpha);
155
+ }
156
+ return {
157
+ type: "rgba",
158
+ width,
159
+ height,
160
+ data
161
+ };
162
+ }
163
+ //#endregion
7
164
  //#region src/smoke/daemon-tray.ts
8
165
  const menuLabels = new Map([
9
166
  [1, "Primary Action"],
@@ -370,12 +527,23 @@ function sleep(ms) {
370
527
  const packageJsonUrl = new URL("../package.json", import.meta.url);
371
528
  const cliModulePath = fileURLToPath(import.meta.url);
372
529
  const parseCliCommand = (argv) => {
373
- const [group, action] = argv;
530
+ const [group, action, ...rest] = argv;
374
531
  if (group !== "daemon") {
375
532
  if (group === "smoke" && action === "daemon-tray") return {
376
533
  type: "smoke",
377
534
  name: "daemon-tray"
378
535
  };
536
+ if (group === "smoke" && action === "daemon-lynx") {
537
+ const bundlePath = parseSmokeBundlePath(rest);
538
+ return bundlePath === void 0 ? {
539
+ type: "smoke",
540
+ name: "daemon-lynx"
541
+ } : {
542
+ type: "smoke",
543
+ name: "daemon-lynx",
544
+ bundlePath
545
+ };
546
+ }
379
547
  return { type: "help" };
380
548
  }
381
549
  if (action === "start" || action === "stop" || action === "restart" || action === "health") return {
@@ -396,7 +564,8 @@ const runCli = async (argv) => {
396
564
  return 1;
397
565
  }
398
566
  if (command.type === "smoke") {
399
- await runDaemonTraySmoke();
567
+ if (command.name === "daemon-tray") await runDaemonTraySmoke();
568
+ else await runDaemonLynxSmoke(command.bundlePath === void 0 ? {} : { bundlePath: command.bundlePath });
400
569
  return 0;
401
570
  }
402
571
  const driver = createNodeDaemonDriver(cliModulePath);
@@ -456,6 +625,7 @@ const runCli = async (argv) => {
456
625
  const printHelp = () => {
457
626
  console.error("Usage: opentray daemon <start|stop|restart|health>");
458
627
  console.error(" opentray smoke daemon-tray");
628
+ console.error(" opentray smoke daemon-lynx --bundle <path-to-main.lynx.bundle>");
459
629
  };
460
630
  const formatDaemonHealthOutput = (health) => {
461
631
  const lines = [
@@ -480,6 +650,9 @@ const isCliEntrypoint = (argvEntryPath, modulePath) => {
480
650
  return argvEntryPath === modulePath;
481
651
  }
482
652
  };
653
+ function parseSmokeBundlePath(argv) {
654
+ for (let index = 0; index < argv.length; index += 1) if (argv[index] === "--bundle") return argv[index + 1];
655
+ }
483
656
  if (isCliEntrypoint(process.argv[1], cliModulePath)) runCli(process.argv.slice(2)).then((code) => {
484
657
  process.exitCode = code;
485
658
  });
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/smoke/daemon-tray.ts","../src/cli.ts"],"sourcesContent":["import type { Rect } from \"@opentray/spec\";\n\nimport { createClient } from \"../client\";\nimport { connectLocalBroker } from \"../local-broker\";\n\nconst menuLabels = new Map<number, string>([\n [1, \"Primary Action\"],\n [3, \"Checked Capability\"],\n [4, \"Radio: Active\"],\n [5, \"Radio: Passive\"],\n [6, \"Nested Action\"],\n [7, \"Nested Check\"],\n [8, \"WebView: Show HTML\"],\n [9, \"WebView: Navigate\"],\n [10, \"WebView: Post Message\"],\n [11, \"WebView: Evaluate\"],\n [12, \"WebView: Hide\"],\n [99, \"Quit Demo\"],\n]);\n\ninterface WebviewShowCommand {\n type: \"show\";\n html?: string;\n url?: string;\n width?: number;\n height?: number;\n fallbackRect?: Rect;\n nativeWindowApi?: boolean;\n bindWindowGlobals?: boolean;\n}\n\nexport const runDaemonTraySmoke = async (): Promise<void> => {\n const connection = await connectLocalBroker();\n const client = createClient(connection, { requestIdPrefix: \"daemon-smoke\" });\n console.log(`connected: endpoint=${connection.endpoint} session=${connection.sessionId}`);\n\n const space = await client.createSpace({\n id: \"com.example.opentray.daemon-smoke\",\n title: \"OpenTray Daemon Smoke\",\n default: true,\n });\n console.log(`space: ${JSON.stringify(space.space)}`);\n\n const tray = await space.createTray({\n trayId: \"daemon-smoke-status\",\n title: \"OpenTray\",\n tooltip: {\n title: \"OpenTray\",\n description: \"npm-installed daemon smoke with broker-routed menu events\",\n },\n icon: createVisibleIcon(),\n menu: {\n items: [\n { type: \"item\", id: 1, title: \"Primary Action\" },\n { type: \"item\", id: 2, title: \"Disabled Action\", enabled: false },\n { type: \"check\", id: 3, title: \"Checked Capability\", checked: true },\n { type: \"radio\", id: 4, title: \"Radio: Active\", group: 1, checked: true },\n { type: \"radio\", id: 5, title: \"Radio: Passive\", group: 1 },\n { type: \"separator\" },\n {\n type: \"submenu\",\n title: \"Nested Actions\",\n items: [\n { type: \"item\", id: 6, title: \"Nested Action\" },\n { type: \"check\", id: 7, title: \"Nested Check\", checked: false },\n ],\n },\n {\n type: \"submenu\",\n title: \"WebView Commands\",\n items: [\n { type: \"item\", id: 8, title: \"Show HTML\" },\n { type: \"item\", id: 9, title: \"Navigate\" },\n { type: \"item\", id: 10, title: \"Post Message\" },\n { type: \"item\", id: 11, title: \"Evaluate JS\" },\n { type: \"item\", id: 12, title: \"Hide\" },\n ],\n },\n { type: \"separator\" },\n { type: \"item\", id: 99, title: \"Quit Demo\" },\n ],\n },\n });\n console.log(`tray: ${tray.trayId}`);\n\n await connection.request({\n type: \"load-ext\",\n requestId: \"daemon-smoke-load-webview\",\n spaceId: space.space.spaceId,\n name: \"webview\",\n path: \"@opentray/ext-webview\",\n });\n console.log(\"webview extension requested through the generic load-ext path\");\n console.log(\"open the system tray item and choose any enabled menu item to see routed events\");\n\n let closed = false;\n let messageCount = 0;\n let evalCount = 0;\n let exitTimer: NodeJS.Timeout | undefined;\n\n const shutdown = async (): Promise<void> => {\n if (closed) {\n return;\n }\n closed = true;\n if (exitTimer !== undefined) {\n clearTimeout(exitTimer);\n }\n await connection.close();\n };\n\n const commandWebview = async (command: WebviewShowCommand | Record<string, unknown>): Promise<void> => {\n await tray.commandExtension(\"webview\", command);\n };\n\n const handleMenuClick = async (itemId: number): Promise<void> => {\n if (itemId === 99) {\n console.log(\"quit item routed; closing smoke connection\");\n await shutdown();\n return;\n }\n\n if (itemId < 8 || itemId > 12) {\n return;\n }\n\n switch (itemId) {\n case 8:\n await commandWebview({\n type: \"show\",\n html: createWebviewDemoHtml(),\n width: 420,\n height: 260,\n fallbackRect: { x: 0, y: 0, width: 1, height: 1 },\n nativeWindowApi: true,\n bindWindowGlobals: true,\n });\n console.log(\"webview command: show\");\n break;\n case 9:\n await commandWebview({ type: \"navigate\", url: \"https://example.com/opentray-status\" });\n console.log(\"webview command: navigate\");\n break;\n case 10:\n messageCount += 1;\n await commandWebview({\n type: \"postMessage\",\n payload: {\n kind: \"ping\",\n source: \"opentray smoke daemon-tray\",\n count: messageCount,\n sentAt: new Date().toISOString(),\n },\n });\n console.log(\"webview command: postMessage\");\n break;\n case 11:\n evalCount += 1;\n await commandWebview({ type: \"evaluate\", js: createVisibleEvaluateScript(evalCount) });\n console.log(\"webview command: evaluate\");\n break;\n case 12:\n await commandWebview({ type: \"hide\" });\n console.log(\"webview command: hide\");\n break;\n }\n };\n\n connection.onEvent((frame) => {\n console.log(`broker -> client ${JSON.stringify(frame)}`);\n if (frame.type === \"event\" && frame.event.type === \"menuClick\") {\n console.log(`menu click: ${menuLabels.get(frame.event.itemId) ?? frame.event.itemId}`);\n void handleMenuClick(frame.event.itemId);\n }\n });\n\n const exitAfter = process.env.OPENTRAY_EXAMPLE_EXIT_AFTER_MS;\n if (exitAfter !== undefined && exitAfter.length > 0) {\n const duration = Number.parseInt(exitAfter, 10);\n if (Number.isInteger(duration) && duration > 0) {\n exitTimer = setTimeout(() => {\n void shutdown();\n }, duration);\n }\n }\n\n const webviewSmoke = process.env.OPENTRAY_EXAMPLE_WEBVIEW_SMOKE;\n try {\n if (webviewSmoke === \"show\") {\n await handleMenuClick(8);\n } else if (webviewSmoke === \"1\") {\n if (exitTimer !== undefined) {\n clearTimeout(exitTimer);\n exitTimer = undefined;\n }\n for (const itemId of [8, 10, 11, 9, 12]) {\n await handleMenuClick(itemId);\n }\n await sleep(300);\n await shutdown();\n }\n } catch (error) {\n await shutdown();\n throw error;\n }\n};\n\nfunction createVisibleIcon(): { type: \"rgba\"; width: number; height: number; data: number[] } {\n const width = 32;\n const height = 32;\n const data: number[] = [];\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const dx = x - 15.5;\n const dy = y - 15.5;\n const distance = Math.sqrt(dx * dx + dy * dy);\n const inRing = distance >= 9 && distance <= 14;\n const inCore = distance <= 5;\n const inNeedle = Math.abs(dx + dy) <= 1.2 && x >= 9 && x <= 23 && y >= 9 && y <= 23;\n\n if (inRing || inCore || inNeedle) {\n data.push(inCore ? 255 : 24, inNeedle ? 240 : 132, inRing ? 72 : 96, 255);\n } else {\n data.push(0, 0, 0, 0);\n }\n }\n }\n\n return { type: \"rgba\", width, height, data };\n}\n\nfunction createWebviewDemoHtml(): string {\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <title>OpenTray WebView</title>\n <style>\n :root {\n color: #18220f;\n background: #f6edd8;\n font: 15px ui-rounded, \"SF Pro Rounded\", \"Avenir Next\", sans-serif;\n }\n body {\n margin: 0;\n }\n main {\n min-height: 100vh;\n box-sizing: border-box;\n padding: 22px;\n background:\n radial-gradient(circle at 84% 10%, rgba(34, 132, 96, 0.22), transparent 34%),\n linear-gradient(135deg, #fff8e7 0%, #e9f0d8 100%);\n }\n h1 {\n margin: 0 0 8px;\n font-size: 24px;\n letter-spacing: -0.04em;\n }\n p {\n margin: 0 0 16px;\n color: #526044;\n }\n section {\n display: grid;\n gap: 10px;\n }\n .card {\n border: 1px solid rgba(24, 34, 15, 0.16);\n border-radius: 14px;\n padding: 12px;\n background: rgba(255, 255, 255, 0.72);\n box-shadow: 0 12px 30px rgba(56, 72, 36, 0.12);\n }\n .label {\n margin-bottom: 5px;\n color: #7b5b1d;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n }\n code {\n word-break: break-word;\n }\n </style>\n </head>\n <body>\n <main>\n <h1>OpenTray WebView</h1>\n <p>Use the tray menu to mutate this native WebView through extension commands.</p>\n <section>\n <div class=\"card\">\n <div class=\"label\">postMessage</div>\n <code id=\"message-status\">Waiting for WebView Commands -> Post Message</code>\n </div>\n <div class=\"card\">\n <div class=\"label\">evaluate JS</div>\n <code id=\"eval-status\">Waiting for WebView Commands -> Evaluate JS</code>\n </div>\n </section>\n </main>\n <script>\n window.addEventListener(\"message\", (event) => {\n const target = document.getElementById(\"message-status\");\n if (target) {\n target.textContent = JSON.stringify(event.data, null, 2);\n }\n });\n </script>\n </body>\n</html>`;\n}\n\nfunction createVisibleEvaluateScript(count: number): string {\n return `(() => {\n let target = document.getElementById(\"eval-status\");\n if (!target) {\n const panel = document.createElement(\"div\");\n panel.style.cssText = \"position:fixed;left:16px;right:16px;bottom:16px;z-index:2147483647;padding:12px;border-radius:12px;background:#fff8e7;color:#18220f;box-shadow:0 12px 30px rgba(0,0,0,.18);font:14px ui-rounded, sans-serif;\";\n panel.textContent = \"OpenTray Evaluate JS: \";\n target = document.createElement(\"code\");\n target.id = \"eval-status\";\n panel.appendChild(target);\n document.body.appendChild(panel);\n }\n if (target) {\n target.textContent = \"Evaluate JS updated the WebView, count=${count}, at \" + new Date().toLocaleTimeString();\n }\n window.__OPENTRAY_DEMO__ = { evaluated: true, count: ${count} };\n })();`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","#!/usr/bin/env node\nimport { realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { DaemonHealth } from \"@opentray/spec\";\n\nimport { createNodeDaemonDriver, inspectDaemon, restartDaemon, startDaemon, stopDaemon } from \"./daemon/lifecycle\";\nimport { readPackageVersion } from \"./daemon/package-version\";\nimport { resolveDaemonPaths } from \"./daemon/paths\";\nimport { connectLocalBroker } from \"./local-broker\";\nimport { runDaemonTraySmoke } from \"./smoke/daemon-tray\";\n\nconst packageJsonUrl = new URL(\"../package.json\", import.meta.url);\nconst cliModulePath = fileURLToPath(import.meta.url);\n\ntype CliCommand =\n | { type: \"daemon\"; action: \"start\" | \"stop\" | \"restart\" | \"health\" }\n | { type: \"smoke\"; name: \"daemon-tray\" }\n | { type: \"help\" };\n\nexport const parseCliCommand = (argv: string[]): CliCommand => {\n const [group, action] = argv;\n if (group !== \"daemon\") {\n if (group === \"smoke\" && action === \"daemon-tray\") {\n return { type: \"smoke\", name: \"daemon-tray\" };\n }\n return { type: \"help\" };\n }\n if (action === \"start\" || action === \"stop\" || action === \"restart\" || action === \"health\") {\n return { type: \"daemon\", action };\n }\n\n return { type: \"help\" };\n};\n\nexport const runCli = async (argv: string[]): Promise<number> => {\n const command = parseCliCommand(argv);\n const packageVersion = process.env.OPENTRAY_DAEMON_PACKAGE_VERSION ?? (await readPackageVersion(packageJsonUrl));\n const paths = resolveDaemonPaths({\n homeDir: process.env.OPENTRAY_HOME ?? homedir(),\n packageVersion,\n });\n\n if (command.type === \"help\") {\n printHelp();\n return 1;\n }\n\n if (command.type === \"smoke\") {\n await runDaemonTraySmoke();\n return 0;\n }\n\n const driver = createNodeDaemonDriver(cliModulePath);\n\n if (command.action === \"start\") {\n const result = await startDaemon({ paths, driver });\n console.log(`opentray daemon ${result.status}: pid=${result.pid} endpoint=${result.paths.endpoint}`);\n return 0;\n }\n\n if (command.action === \"stop\") {\n const result = await stopDaemon({ paths, driver });\n console.log(\n result.status === \"stopped\"\n ? `opentray daemon stopped: pid=${result.pid}`\n : \"opentray daemon not running\",\n );\n return 0;\n }\n\n if (command.action === \"restart\") {\n const result = await restartDaemon({ paths, driver });\n console.log(`opentray daemon ${result.status}: pid=${result.pid} endpoint=${result.paths.endpoint}`);\n return 0;\n }\n\n if (command.action === \"health\") {\n const inspected = await inspectDaemon({ paths, driver });\n if (inspected.status === \"not-running\") {\n console.log(\"opentray daemon not running\");\n return 0;\n }\n\n const connection = await connectLocalBroker({\n autoStart: false,\n endpoint: paths.endpoint,\n homeDir: paths.homeDir,\n packageVersion,\n });\n try {\n const response = await connection.request({\n type: \"health\",\n requestId: \"opentray-daemon-health\",\n });\n if (response.type !== \"daemon-health\") {\n throw new Error(`expected daemon-health response, received ${response.type}`);\n }\n console.log(formatDaemonHealthOutput(response.health));\n } finally {\n await connection.close();\n }\n return 0;\n }\n\n printHelp();\n return 1;\n};\n\nconst printHelp = (): void => {\n console.error(\"Usage: opentray daemon <start|stop|restart|health>\");\n console.error(\" opentray smoke daemon-tray\");\n};\n\nexport const formatDaemonHealthOutput = (health: DaemonHealth): string => {\n const lines = [\n \"opentray daemon running\",\n `pid: ${health.pid}`,\n `endpoint: ${health.endpoint}`,\n `packageVersion: ${health.packageVersion}`,\n `protocolVersion: ${health.protocolVersion}`,\n `sessions: ${health.sessionCount}`,\n ];\n\n for (const session of health.sessions) {\n const internalLease = session.internalLeaseId ?? \"(pending)\";\n lines.push(\n `- sessionId=${session.sessionId} initialized=${session.initialized} internalLeaseId=${internalLease}`,\n );\n }\n\n return lines.join(\"\\n\");\n};\n\nexport const isCliEntrypoint = (argvEntryPath: string | undefined, modulePath: string): boolean => {\n if (argvEntryPath === undefined) return false;\n try {\n return realpathSync(argvEntryPath) === realpathSync(modulePath);\n } catch {\n return argvEntryPath === modulePath;\n }\n};\n\nif (isCliEntrypoint(process.argv[1], cliModulePath)) {\n runCli(process.argv.slice(2)).then((code) => {\n process.exitCode = code;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["menuLabels","createVisibleIcon"],"sources":["../src/smoke/daemon-lynx.ts","../src/smoke/daemon-tray.ts","../src/cli.ts"],"sourcesContent":["import { existsSync, realpathSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nimport { createClient } from \"../client\";\nimport { connectLocalBroker } from \"../local-broker\";\n\nconst menuLabels = new Map<number, string>([\n [1, \"Reload Bundle\"],\n [2, \"Hide Window\"],\n [99, \"Quit Smoke\"],\n]);\n\nconst DEFAULT_LYNX_BUNDLE_ENV = \"OPENTRAY_LYNX_BUNDLE\";\n\nexport interface DaemonLynxSmokeOptions {\n bundlePath?: string;\n}\n\nexport const runDaemonLynxSmoke = async (\n options: DaemonLynxSmokeOptions = {},\n): Promise<void> => {\n const bundlePath = resolveLynxBundlePath(options.bundlePath);\n const connection = await connectLocalBroker();\n const client = createClient(connection, { requestIdPrefix: \"daemon-lynx\" });\n console.log(`connected: endpoint=${connection.endpoint} session=${connection.sessionId}`);\n\n const space = await client.createSpace({\n id: \"com.example.opentray.daemon-lynx\",\n title: \"OpenTray Lynx Smoke\",\n default: true,\n });\n console.log(`space: ${JSON.stringify(space.space)}`);\n\n const tray = await space.createTray({\n trayId: \"daemon-lynx-status\",\n title: \"OpenTray Lynx\",\n tooltip: {\n title: \"OpenTray Lynx\",\n description: \"Generic extension smoke for a real Lynx runtime window\",\n },\n icon: createVisibleIcon(),\n menu: {\n items: [\n { type: \"item\", id: 1, title: \"Reload Bundle\" },\n { type: \"item\", id: 2, title: \"Hide Window\" },\n { type: \"separator\" },\n { type: \"item\", id: 99, title: \"Quit Smoke\" },\n ],\n },\n });\n console.log(`tray: ${tray.trayId}`);\n\n await connection.request({\n type: \"load-ext\",\n requestId: \"daemon-lynx-load\",\n spaceId: space.space.spaceId,\n name: \"lynx\",\n path: \"@opentray/ext-lynx\",\n });\n console.log(\"lynx extension requested through the generic load-ext path\");\n\n let closed = false;\n let exitTimer: NodeJS.Timeout | undefined;\n let resolveClosed: (() => void) | undefined;\n\n const show = async (): Promise<void> => {\n await tray.commandExtension(\"lynx\", {\n type: \"show\",\n bundlePath,\n });\n console.log(`lynx command: show bundle=${bundlePath}`);\n };\n\n const hide = async (): Promise<void> => {\n await tray.commandExtension(\"lynx\", { type: \"hide\" });\n console.log(\"lynx command: hide\");\n };\n\n const shutdown = async (): Promise<void> => {\n if (closed) {\n return;\n }\n closed = true;\n if (exitTimer !== undefined) {\n clearTimeout(exitTimer);\n }\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n try {\n await hide();\n } catch (error) {\n console.error(`lynx hide during shutdown failed: ${String(error)}`);\n }\n await connection.close();\n resolveClosed?.();\n };\n\n const handleMenuClick = async (itemId: number): Promise<void> => {\n switch (itemId) {\n case 1:\n await show();\n return;\n case 2:\n await hide();\n return;\n case 99:\n console.log(\"quit item routed; closing lynx smoke connection\");\n await shutdown();\n return;\n default:\n return;\n }\n };\n\n connection.onEvent((frame) => {\n console.log(`broker -> client ${JSON.stringify(frame)}`);\n if (frame.type === \"event\" && frame.event.type === \"menuClick\") {\n console.log(`menu click: ${menuLabels.get(frame.event.itemId) ?? frame.event.itemId}`);\n void handleMenuClick(frame.event.itemId);\n return;\n }\n if (frame.type === \"ext-event\" && frame.ext === \"lynx\") {\n console.log(`lynx event: ${JSON.stringify(frame.data)}`);\n }\n });\n\n const onSignal = (): void => {\n void shutdown();\n };\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n\n const exitAfter = process.env.OPENTRAY_EXAMPLE_EXIT_AFTER_MS;\n if (exitAfter !== undefined && exitAfter.length > 0) {\n const duration = Number.parseInt(exitAfter, 10);\n if (Number.isInteger(duration) && duration > 0) {\n exitTimer = setTimeout(() => {\n void shutdown();\n }, duration);\n }\n }\n\n try {\n await show();\n console.log(\"use the tray menu to reload or hide the Lynx window, or press Ctrl+C to exit\");\n } catch (error) {\n await connection.close();\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n throw error;\n }\n\n await new Promise<void>((resolve) => {\n resolveClosed = resolve;\n });\n};\n\nexport const resolveLynxBundlePath = (value?: string): string => {\n const resolved = value ?? process.env[DEFAULT_LYNX_BUNDLE_ENV];\n if (resolved === undefined || resolved.length === 0) {\n throw new Error(\n `lynx smoke requires --bundle <path> or ${DEFAULT_LYNX_BUNDLE_ENV}=<path-to-main.lynx.bundle>`,\n );\n }\n const baseDir = process.env.INIT_CWD ?? process.cwd();\n const absolutePath = resolve(baseDir, resolved);\n if (!existsSync(absolutePath)) {\n throw new Error(`lynx smoke bundle does not exist: ${absolutePath}`);\n }\n return realpathSync(absolutePath);\n};\n\nfunction createVisibleIcon(): { type: \"rgba\"; width: number; height: number; data: number[] } {\n const width = 32;\n const height = 32;\n const data: number[] = [];\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const inStroke = x <= 5 || (x >= 13 && x <= 18) || y >= 26;\n const inDiagonal = y >= x + 10 && x <= 18;\n const alpha = inStroke || inDiagonal ? 255 : 0;\n data.push(34, 92, 56, alpha);\n }\n }\n\n return { type: \"rgba\", width, height, data };\n}\n","import type { Rect } from \"@opentray/spec\";\n\nimport { createClient } from \"../client\";\nimport { connectLocalBroker } from \"../local-broker\";\n\nconst menuLabels = new Map<number, string>([\n [1, \"Primary Action\"],\n [3, \"Checked Capability\"],\n [4, \"Radio: Active\"],\n [5, \"Radio: Passive\"],\n [6, \"Nested Action\"],\n [7, \"Nested Check\"],\n [8, \"WebView: Show HTML\"],\n [9, \"WebView: Navigate\"],\n [10, \"WebView: Post Message\"],\n [11, \"WebView: Evaluate\"],\n [12, \"WebView: Hide\"],\n [99, \"Quit Demo\"],\n]);\n\ninterface WebviewShowCommand {\n type: \"show\";\n html?: string;\n url?: string;\n width?: number;\n height?: number;\n fallbackRect?: Rect;\n nativeWindowApi?: boolean;\n bindWindowGlobals?: boolean;\n}\n\nexport const runDaemonTraySmoke = async (): Promise<void> => {\n const connection = await connectLocalBroker();\n const client = createClient(connection, { requestIdPrefix: \"daemon-smoke\" });\n console.log(`connected: endpoint=${connection.endpoint} session=${connection.sessionId}`);\n\n const space = await client.createSpace({\n id: \"com.example.opentray.daemon-smoke\",\n title: \"OpenTray Daemon Smoke\",\n default: true,\n });\n console.log(`space: ${JSON.stringify(space.space)}`);\n\n const tray = await space.createTray({\n trayId: \"daemon-smoke-status\",\n title: \"OpenTray\",\n tooltip: {\n title: \"OpenTray\",\n description: \"npm-installed daemon smoke with broker-routed menu events\",\n },\n icon: createVisibleIcon(),\n menu: {\n items: [\n { type: \"item\", id: 1, title: \"Primary Action\" },\n { type: \"item\", id: 2, title: \"Disabled Action\", enabled: false },\n { type: \"check\", id: 3, title: \"Checked Capability\", checked: true },\n { type: \"radio\", id: 4, title: \"Radio: Active\", group: 1, checked: true },\n { type: \"radio\", id: 5, title: \"Radio: Passive\", group: 1 },\n { type: \"separator\" },\n {\n type: \"submenu\",\n title: \"Nested Actions\",\n items: [\n { type: \"item\", id: 6, title: \"Nested Action\" },\n { type: \"check\", id: 7, title: \"Nested Check\", checked: false },\n ],\n },\n {\n type: \"submenu\",\n title: \"WebView Commands\",\n items: [\n { type: \"item\", id: 8, title: \"Show HTML\" },\n { type: \"item\", id: 9, title: \"Navigate\" },\n { type: \"item\", id: 10, title: \"Post Message\" },\n { type: \"item\", id: 11, title: \"Evaluate JS\" },\n { type: \"item\", id: 12, title: \"Hide\" },\n ],\n },\n { type: \"separator\" },\n { type: \"item\", id: 99, title: \"Quit Demo\" },\n ],\n },\n });\n console.log(`tray: ${tray.trayId}`);\n\n await connection.request({\n type: \"load-ext\",\n requestId: \"daemon-smoke-load-webview\",\n spaceId: space.space.spaceId,\n name: \"webview\",\n path: \"@opentray/ext-webview\",\n });\n console.log(\"webview extension requested through the generic load-ext path\");\n console.log(\"open the system tray item and choose any enabled menu item to see routed events\");\n\n let closed = false;\n let messageCount = 0;\n let evalCount = 0;\n let exitTimer: NodeJS.Timeout | undefined;\n\n const shutdown = async (): Promise<void> => {\n if (closed) {\n return;\n }\n closed = true;\n if (exitTimer !== undefined) {\n clearTimeout(exitTimer);\n }\n await connection.close();\n };\n\n const commandWebview = async (command: WebviewShowCommand | Record<string, unknown>): Promise<void> => {\n await tray.commandExtension(\"webview\", command);\n };\n\n const handleMenuClick = async (itemId: number): Promise<void> => {\n if (itemId === 99) {\n console.log(\"quit item routed; closing smoke connection\");\n await shutdown();\n return;\n }\n\n if (itemId < 8 || itemId > 12) {\n return;\n }\n\n switch (itemId) {\n case 8:\n await commandWebview({\n type: \"show\",\n html: createWebviewDemoHtml(),\n width: 420,\n height: 260,\n fallbackRect: { x: 0, y: 0, width: 1, height: 1 },\n nativeWindowApi: true,\n bindWindowGlobals: true,\n });\n console.log(\"webview command: show\");\n break;\n case 9:\n await commandWebview({ type: \"navigate\", url: \"https://example.com/opentray-status\" });\n console.log(\"webview command: navigate\");\n break;\n case 10:\n messageCount += 1;\n await commandWebview({\n type: \"postMessage\",\n payload: {\n kind: \"ping\",\n source: \"opentray smoke daemon-tray\",\n count: messageCount,\n sentAt: new Date().toISOString(),\n },\n });\n console.log(\"webview command: postMessage\");\n break;\n case 11:\n evalCount += 1;\n await commandWebview({ type: \"evaluate\", js: createVisibleEvaluateScript(evalCount) });\n console.log(\"webview command: evaluate\");\n break;\n case 12:\n await commandWebview({ type: \"hide\" });\n console.log(\"webview command: hide\");\n break;\n }\n };\n\n connection.onEvent((frame) => {\n console.log(`broker -> client ${JSON.stringify(frame)}`);\n if (frame.type === \"event\" && frame.event.type === \"menuClick\") {\n console.log(`menu click: ${menuLabels.get(frame.event.itemId) ?? frame.event.itemId}`);\n void handleMenuClick(frame.event.itemId);\n }\n });\n\n const exitAfter = process.env.OPENTRAY_EXAMPLE_EXIT_AFTER_MS;\n if (exitAfter !== undefined && exitAfter.length > 0) {\n const duration = Number.parseInt(exitAfter, 10);\n if (Number.isInteger(duration) && duration > 0) {\n exitTimer = setTimeout(() => {\n void shutdown();\n }, duration);\n }\n }\n\n const webviewSmoke = process.env.OPENTRAY_EXAMPLE_WEBVIEW_SMOKE;\n try {\n if (webviewSmoke === \"show\") {\n await handleMenuClick(8);\n } else if (webviewSmoke === \"1\") {\n if (exitTimer !== undefined) {\n clearTimeout(exitTimer);\n exitTimer = undefined;\n }\n for (const itemId of [8, 10, 11, 9, 12]) {\n await handleMenuClick(itemId);\n }\n await sleep(300);\n await shutdown();\n }\n } catch (error) {\n await shutdown();\n throw error;\n }\n};\n\nfunction createVisibleIcon(): { type: \"rgba\"; width: number; height: number; data: number[] } {\n const width = 32;\n const height = 32;\n const data: number[] = [];\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const dx = x - 15.5;\n const dy = y - 15.5;\n const distance = Math.sqrt(dx * dx + dy * dy);\n const inRing = distance >= 9 && distance <= 14;\n const inCore = distance <= 5;\n const inNeedle = Math.abs(dx + dy) <= 1.2 && x >= 9 && x <= 23 && y >= 9 && y <= 23;\n\n if (inRing || inCore || inNeedle) {\n data.push(inCore ? 255 : 24, inNeedle ? 240 : 132, inRing ? 72 : 96, 255);\n } else {\n data.push(0, 0, 0, 0);\n }\n }\n }\n\n return { type: \"rgba\", width, height, data };\n}\n\nfunction createWebviewDemoHtml(): string {\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <title>OpenTray WebView</title>\n <style>\n :root {\n color: #18220f;\n background: #f6edd8;\n font: 15px ui-rounded, \"SF Pro Rounded\", \"Avenir Next\", sans-serif;\n }\n body {\n margin: 0;\n }\n main {\n min-height: 100vh;\n box-sizing: border-box;\n padding: 22px;\n background:\n radial-gradient(circle at 84% 10%, rgba(34, 132, 96, 0.22), transparent 34%),\n linear-gradient(135deg, #fff8e7 0%, #e9f0d8 100%);\n }\n h1 {\n margin: 0 0 8px;\n font-size: 24px;\n letter-spacing: -0.04em;\n }\n p {\n margin: 0 0 16px;\n color: #526044;\n }\n section {\n display: grid;\n gap: 10px;\n }\n .card {\n border: 1px solid rgba(24, 34, 15, 0.16);\n border-radius: 14px;\n padding: 12px;\n background: rgba(255, 255, 255, 0.72);\n box-shadow: 0 12px 30px rgba(56, 72, 36, 0.12);\n }\n .label {\n margin-bottom: 5px;\n color: #7b5b1d;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n }\n code {\n word-break: break-word;\n }\n </style>\n </head>\n <body>\n <main>\n <h1>OpenTray WebView</h1>\n <p>Use the tray menu to mutate this native WebView through extension commands.</p>\n <section>\n <div class=\"card\">\n <div class=\"label\">postMessage</div>\n <code id=\"message-status\">Waiting for WebView Commands -> Post Message</code>\n </div>\n <div class=\"card\">\n <div class=\"label\">evaluate JS</div>\n <code id=\"eval-status\">Waiting for WebView Commands -> Evaluate JS</code>\n </div>\n </section>\n </main>\n <script>\n window.addEventListener(\"message\", (event) => {\n const target = document.getElementById(\"message-status\");\n if (target) {\n target.textContent = JSON.stringify(event.data, null, 2);\n }\n });\n </script>\n </body>\n</html>`;\n}\n\nfunction createVisibleEvaluateScript(count: number): string {\n return `(() => {\n let target = document.getElementById(\"eval-status\");\n if (!target) {\n const panel = document.createElement(\"div\");\n panel.style.cssText = \"position:fixed;left:16px;right:16px;bottom:16px;z-index:2147483647;padding:12px;border-radius:12px;background:#fff8e7;color:#18220f;box-shadow:0 12px 30px rgba(0,0,0,.18);font:14px ui-rounded, sans-serif;\";\n panel.textContent = \"OpenTray Evaluate JS: \";\n target = document.createElement(\"code\");\n target.id = \"eval-status\";\n panel.appendChild(target);\n document.body.appendChild(panel);\n }\n if (target) {\n target.textContent = \"Evaluate JS updated the WebView, count=${count}, at \" + new Date().toLocaleTimeString();\n }\n window.__OPENTRAY_DEMO__ = { evaluated: true, count: ${count} };\n })();`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","#!/usr/bin/env node\nimport { realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { DaemonHealth } from \"@opentray/spec\";\n\nimport { createNodeDaemonDriver, inspectDaemon, restartDaemon, startDaemon, stopDaemon } from \"./daemon/lifecycle\";\nimport { readPackageVersion } from \"./daemon/package-version\";\nimport { resolveDaemonPaths } from \"./daemon/paths\";\nimport { connectLocalBroker } from \"./local-broker\";\nimport { runDaemonLynxSmoke } from \"./smoke/daemon-lynx\";\nimport { runDaemonTraySmoke } from \"./smoke/daemon-tray\";\n\nconst packageJsonUrl = new URL(\"../package.json\", import.meta.url);\nconst cliModulePath = fileURLToPath(import.meta.url);\n\ntype CliCommand =\n | { type: \"daemon\"; action: \"start\" | \"stop\" | \"restart\" | \"health\" }\n | { type: \"smoke\"; name: \"daemon-tray\" }\n | { type: \"smoke\"; name: \"daemon-lynx\"; bundlePath?: string }\n | { type: \"help\" };\n\nexport const parseCliCommand = (argv: string[]): CliCommand => {\n const [group, action, ...rest] = argv;\n if (group !== \"daemon\") {\n if (group === \"smoke\" && action === \"daemon-tray\") {\n return { type: \"smoke\", name: \"daemon-tray\" };\n }\n if (group === \"smoke\" && action === \"daemon-lynx\") {\n const bundlePath = parseSmokeBundlePath(rest);\n return bundlePath === undefined\n ? { type: \"smoke\", name: \"daemon-lynx\" }\n : { type: \"smoke\", name: \"daemon-lynx\", bundlePath };\n }\n return { type: \"help\" };\n }\n if (action === \"start\" || action === \"stop\" || action === \"restart\" || action === \"health\") {\n return { type: \"daemon\", action };\n }\n\n return { type: \"help\" };\n};\n\nexport const runCli = async (argv: string[]): Promise<number> => {\n const command = parseCliCommand(argv);\n const packageVersion = process.env.OPENTRAY_DAEMON_PACKAGE_VERSION ?? (await readPackageVersion(packageJsonUrl));\n const paths = resolveDaemonPaths({\n homeDir: process.env.OPENTRAY_HOME ?? homedir(),\n packageVersion,\n });\n\n if (command.type === \"help\") {\n printHelp();\n return 1;\n }\n\n if (command.type === \"smoke\") {\n if (command.name === \"daemon-tray\") {\n await runDaemonTraySmoke();\n } else {\n await runDaemonLynxSmoke(\n command.bundlePath === undefined ? {} : { bundlePath: command.bundlePath },\n );\n }\n return 0;\n }\n\n const driver = createNodeDaemonDriver(cliModulePath);\n\n if (command.action === \"start\") {\n const result = await startDaemon({ paths, driver });\n console.log(`opentray daemon ${result.status}: pid=${result.pid} endpoint=${result.paths.endpoint}`);\n return 0;\n }\n\n if (command.action === \"stop\") {\n const result = await stopDaemon({ paths, driver });\n console.log(\n result.status === \"stopped\"\n ? `opentray daemon stopped: pid=${result.pid}`\n : \"opentray daemon not running\",\n );\n return 0;\n }\n\n if (command.action === \"restart\") {\n const result = await restartDaemon({ paths, driver });\n console.log(`opentray daemon ${result.status}: pid=${result.pid} endpoint=${result.paths.endpoint}`);\n return 0;\n }\n\n if (command.action === \"health\") {\n const inspected = await inspectDaemon({ paths, driver });\n if (inspected.status === \"not-running\") {\n console.log(\"opentray daemon not running\");\n return 0;\n }\n\n const connection = await connectLocalBroker({\n autoStart: false,\n endpoint: paths.endpoint,\n homeDir: paths.homeDir,\n packageVersion,\n });\n try {\n const response = await connection.request({\n type: \"health\",\n requestId: \"opentray-daemon-health\",\n });\n if (response.type !== \"daemon-health\") {\n throw new Error(`expected daemon-health response, received ${response.type}`);\n }\n console.log(formatDaemonHealthOutput(response.health));\n } finally {\n await connection.close();\n }\n return 0;\n }\n\n printHelp();\n return 1;\n};\n\nconst printHelp = (): void => {\n console.error(\"Usage: opentray daemon <start|stop|restart|health>\");\n console.error(\" opentray smoke daemon-tray\");\n console.error(\" opentray smoke daemon-lynx --bundle <path-to-main.lynx.bundle>\");\n};\n\nexport const formatDaemonHealthOutput = (health: DaemonHealth): string => {\n const lines = [\n \"opentray daemon running\",\n `pid: ${health.pid}`,\n `endpoint: ${health.endpoint}`,\n `packageVersion: ${health.packageVersion}`,\n `protocolVersion: ${health.protocolVersion}`,\n `sessions: ${health.sessionCount}`,\n ];\n\n for (const session of health.sessions) {\n const internalLease = session.internalLeaseId ?? \"(pending)\";\n lines.push(\n `- sessionId=${session.sessionId} initialized=${session.initialized} internalLeaseId=${internalLease}`,\n );\n }\n\n return lines.join(\"\\n\");\n};\n\nexport const isCliEntrypoint = (argvEntryPath: string | undefined, modulePath: string): boolean => {\n if (argvEntryPath === undefined) return false;\n try {\n return realpathSync(argvEntryPath) === realpathSync(modulePath);\n } catch {\n return argvEntryPath === modulePath;\n }\n};\n\nfunction parseSmokeBundlePath(argv: string[]): string | undefined {\n for (let index = 0; index < argv.length; index += 1) {\n if (argv[index] === \"--bundle\") {\n return argv[index + 1];\n }\n }\n return undefined;\n}\n\nif (isCliEntrypoint(process.argv[1], cliModulePath)) {\n runCli(process.argv.slice(2)).then((code) => {\n process.exitCode = code;\n });\n}\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ interface OpenTrayTransport {
6
6
  }
7
7
  interface OpenTrayClient {
8
8
  createSpace(options: SpaceOptions): Promise<SpaceHandle>;
9
+ resolveDefaultSpace(): Promise<SpaceHandle>;
9
10
  /** @deprecated Use `createSpace`. */
10
11
  createSurface(options: SpaceOptions): Promise<SpaceHandle>;
11
12
  }
@@ -32,4 +33,4 @@ declare const createSurfaceHandle: (transport: OpenTrayTransport, space: SpaceRe
32
33
  declare const createTrayHandle: (transport: OpenTrayTransport, space: SpaceRef, trayId: TrayId, nextRequestId?: () => RequestId) => TrayHandle;
33
34
  //#endregion
34
35
  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 };
35
- //# sourceMappingURL=client-D-lSB3Rd.d.mts.map
36
+ //# sourceMappingURL=client-C_zT7PEt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-C_zT7PEt.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;UAYiB,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,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"}
@@ -17,6 +17,14 @@ const createClient = (transport, options = {}) => {
17
17
  }), requestId, "space-created").space;
18
18
  return createSpaceHandle(transport, space, nextRequestId);
19
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
+ },
20
28
  async createSurface(spaceOptions) {
21
29
  return this.createSpace(spaceOptions);
22
30
  }
@@ -90,4 +98,4 @@ const requestIdOf = (frame) => {
90
98
  //#endregion
91
99
  export { createTrayHandle as a, createSurfaceHandle as i, createInitFrame as n, createSpaceHandle as r, createClient as t };
92
100
 
93
- //# sourceMappingURL=client-BBJON7c4.mjs.map
101
+ //# sourceMappingURL=client-Db-tztnj.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-Db-tztnj.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 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 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 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 \"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":";;AAsCA,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,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,iBACH,OAAO,MAAM;EACf,KAAK,SACH,OAAO,MAAM;EACf,KAAK;EACL,KAAK;EACL,KAAK,aACH;CACJ;AACF"}
package/dist/index.d.mts CHANGED
@@ -1,3 +1,23 @@
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-D-lSB3Rd.mjs";
2
- import { BrokerEndpointIdentity, BrokerEndpointIdentityOptions, PROTOCOL_VERSION, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
3
- export { type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type CreateClientOptions, type OpenTrayClient, type OpenTrayTransport, PROTOCOL_VERSION, type SpaceHandle, type SurfaceHandle, type TrayHandle, createBrokerEndpointIdentity, createClient, createInitFrame, createSpaceHandle, createSurfaceHandle, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion };
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-C_zT7PEt.mjs";
2
+ import { BrokerEndpointIdentity, BrokerEndpointIdentityOptions, PROTOCOL_VERSION, SpaceOptions, SpaceRef, TrayOptions, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
3
+
4
+ //#region src/sdk.d.ts
5
+ interface BrokerConnectOptions {
6
+ endpoint?: string;
7
+ homeDir?: string;
8
+ packageVersion?: string;
9
+ protocolVersion?: number;
10
+ clientVersion?: string;
11
+ autoStart?: boolean;
12
+ }
13
+ interface CreateTrayOptions extends BrokerConnectOptions {
14
+ space?: SpaceRef;
15
+ }
16
+ declare const createSpace: (options: SpaceOptions, brokerOptions?: BrokerConnectOptions) => Promise<SpaceHandle>;
17
+ /** @deprecated Use `createSpace`. */
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>;
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 };
23
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +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"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,21 @@
1
- import { a as createTrayHandle, i as createSurfaceHandle, n as createInitFrame, r as createSpaceHandle, t as createClient } from "./client-BBJON7c4.mjs";
1
+ import { a as createTrayHandle, i as createSurfaceHandle, n as createInitFrame, r as createSpaceHandle, t as createClient } from "./client-Db-tztnj.mjs";
2
+ import { t as connectLocalBroker } from "./local-broker-mQmeVLF5.mjs";
2
3
  import { PROTOCOL_VERSION, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion } from "@opentray/spec";
3
- export { PROTOCOL_VERSION, createBrokerEndpointIdentity, createClient, createInitFrame, createSpaceHandle, createSurfaceHandle, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion };
4
+ //#region src/sdk.ts
5
+ const createSpace = async (options, brokerOptions = {}) => {
6
+ return createClient(await connectLocalBroker(brokerOptions)).createSpace(options);
7
+ };
8
+ /** @deprecated Use `createSpace`. */
9
+ const createSurface = async (options, brokerOptions = {}) => createSpace(options, brokerOptions);
10
+ const resolveDefaultSpace = async (brokerOptions = {}) => {
11
+ return createClient(await connectLocalBroker(brokerOptions)).resolveDefaultSpace();
12
+ };
13
+ const createTray = async (options, brokerOptions = {}) => {
14
+ const { space, ...connectOptions } = brokerOptions;
15
+ const connection = await connectLocalBroker(connectOptions);
16
+ return (space ? createSpaceHandle(connection, space) : await createClient(connection).resolveDefaultSpace()).createTray(options);
17
+ };
18
+ //#endregion
19
+ export { PROTOCOL_VERSION, createBrokerEndpointIdentity, createClient, createInitFrame, createSpace, createSpaceHandle, createSurface, createSurfaceHandle, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveDefaultSpace };
20
+
21
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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"}
package/dist/node.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as OpenTrayTransport } from "./client-D-lSB3Rd.mjs";
1
+ import { r as OpenTrayTransport } from "./client-C_zT7PEt.mjs";
2
2
  import { BrokerEndpointIdentityOptions, ServerFrame } from "@opentray/spec";
3
3
 
4
4
  //#region src/daemon/paths.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentray",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Developer-facing OpenTray SDK and CLI package.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,17 +36,18 @@
36
36
  "vitest": "^4.1.7"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@opentray/darwin-arm64": "0.3.0",
40
- "@opentray/darwin-x64": "0.3.0",
41
- "@opentray/linux-arm64": "0.3.0",
42
- "@opentray/linux-x64": "0.3.0",
43
- "@opentray/windows-arm64": "0.3.0",
44
- "@opentray/windows-x64": "0.3.0"
39
+ "@opentray/darwin-arm64": "0.4.0",
40
+ "@opentray/darwin-x64": "0.4.0",
41
+ "@opentray/linux-arm64": "0.4.0",
42
+ "@opentray/linux-x64": "0.4.0",
43
+ "@opentray/windows-arm64": "0.4.0",
44
+ "@opentray/windows-x64": "0.4.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsdown src/index.ts src/node.ts src/cli.ts --format esm --dts",
48
48
  "cli": "bun run src/cli.ts",
49
49
  "example:basic": "bun run examples/basic-space.ts",
50
+ "example:daemon-lynx": "bun run examples/daemon-lynx.ts",
50
51
  "example:daemon-tray": "bun run examples/daemon-tray.ts",
51
52
  "test": "vitest run",
52
53
  "typecheck": "tsc --noEmit"
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-BBJON7c4.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 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 /** @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 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 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 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 \"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":";;AAqCA,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,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,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,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-D-lSB3Rd.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;UAYiB,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;EAJ7B;EAMf,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,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,cAoBU,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"}