sweetlink 0.2.0 → 0.2.2

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.
Files changed (233) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/LICENSE +1 -1
  3. package/README.md +6 -6
  4. package/dist/daemon/src/cli.d.ts +3 -0
  5. package/dist/daemon/src/cli.d.ts.map +1 -0
  6. package/dist/daemon/src/cli.js +14 -0
  7. package/dist/daemon/src/cli.js.map +1 -0
  8. package/dist/daemon/src/codename.d.ts.map +1 -1
  9. package/dist/daemon/src/codename.js +11 -11
  10. package/dist/daemon/src/codename.js.map +1 -1
  11. package/dist/daemon/src/index.d.ts +1 -1
  12. package/dist/daemon/src/index.js +143 -128
  13. package/dist/daemon/src/index.js.map +1 -1
  14. package/dist/shared/src/env.d.ts.map +1 -1
  15. package/dist/shared/src/env.js +12 -12
  16. package/dist/shared/src/env.js.map +1 -1
  17. package/dist/shared/src/index.d.ts +30 -30
  18. package/dist/shared/src/index.d.ts.map +1 -1
  19. package/dist/shared/src/index.js +17 -17
  20. package/dist/shared/src/index.js.map +1 -1
  21. package/dist/shared/src/node.d.ts +1 -1
  22. package/dist/shared/src/node.d.ts.map +1 -1
  23. package/dist/shared/src/node.js +18 -18
  24. package/dist/shared/src/node.js.map +1 -1
  25. package/dist/src/codex.d.ts +1 -1
  26. package/dist/src/codex.js +19 -19
  27. package/dist/src/codex.js.map +1 -1
  28. package/dist/src/commands/click.d.ts +1 -1
  29. package/dist/src/commands/click.d.ts.map +1 -1
  30. package/dist/src/commands/click.js +32 -24
  31. package/dist/src/commands/click.js.map +1 -1
  32. package/dist/src/commands/run-js.d.ts +1 -1
  33. package/dist/src/commands/run-js.d.ts.map +1 -1
  34. package/dist/src/commands/run-js.js +10 -10
  35. package/dist/src/commands/run-js.js.map +1 -1
  36. package/dist/src/commands/trust-ca.d.ts +1 -1
  37. package/dist/src/commands/trust-ca.js +15 -15
  38. package/dist/src/core/config-file.d.ts.map +1 -1
  39. package/dist/src/core/config-file.js +49 -41
  40. package/dist/src/core/config-file.js.map +1 -1
  41. package/dist/src/core/config.d.ts +2 -2
  42. package/dist/src/core/config.d.ts.map +1 -1
  43. package/dist/src/core/config.js +22 -18
  44. package/dist/src/core/config.js.map +1 -1
  45. package/dist/src/core/dev-bootstrap.d.ts +1 -1
  46. package/dist/src/core/dev-bootstrap.d.ts.map +1 -1
  47. package/dist/src/core/dev-bootstrap.js +12 -12
  48. package/dist/src/core/dev-bootstrap.js.map +1 -1
  49. package/dist/src/core/env.d.ts +1 -1
  50. package/dist/src/core/env.d.ts.map +1 -1
  51. package/dist/src/core/env.js +3 -3
  52. package/dist/src/core/env.js.map +1 -1
  53. package/dist/src/devtools-registry.d.ts.map +1 -1
  54. package/dist/src/devtools-registry.js +48 -46
  55. package/dist/src/devtools-registry.js.map +1 -1
  56. package/dist/src/env.d.ts +1 -1
  57. package/dist/src/env.js +1 -1
  58. package/dist/src/http.d.ts.map +1 -1
  59. package/dist/src/http.js +7 -6
  60. package/dist/src/http.js.map +1 -1
  61. package/dist/src/index.d.ts +7 -7
  62. package/dist/src/index.d.ts.map +1 -1
  63. package/dist/src/index.js +399 -367
  64. package/dist/src/index.js.map +1 -1
  65. package/dist/src/runtime/browser/client.d.ts +5 -4
  66. package/dist/src/runtime/browser/client.d.ts.map +1 -1
  67. package/dist/src/runtime/browser/client.js +79 -72
  68. package/dist/src/runtime/browser/client.js.map +1 -1
  69. package/dist/src/runtime/browser/commands/index.d.ts +2 -2
  70. package/dist/src/runtime/browser/commands/index.js +17 -17
  71. package/dist/src/runtime/browser/commands/index.js.map +1 -1
  72. package/dist/src/runtime/browser/dom-to-image-loader.d.ts.map +1 -1
  73. package/dist/src/runtime/browser/dom-to-image-loader.js +7 -7
  74. package/dist/src/runtime/browser/dom-to-image-loader.js.map +1 -1
  75. package/dist/src/runtime/browser/index.d.ts +3 -3
  76. package/dist/src/runtime/browser/index.js +2 -2
  77. package/dist/src/runtime/browser/module-loader.js +2 -2
  78. package/dist/src/runtime/browser/screenshot/hooks.d.ts +5 -5
  79. package/dist/src/runtime/browser/screenshot/hooks.d.ts.map +1 -1
  80. package/dist/src/runtime/browser/screenshot/hooks.js +32 -29
  81. package/dist/src/runtime/browser/screenshot/hooks.js.map +1 -1
  82. package/dist/src/runtime/browser/screenshot/index.d.ts +3 -3
  83. package/dist/src/runtime/browser/screenshot/index.d.ts.map +1 -1
  84. package/dist/src/runtime/browser/screenshot/index.js +17 -15
  85. package/dist/src/runtime/browser/screenshot/index.js.map +1 -1
  86. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.d.ts +1 -1
  87. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.js +13 -13
  88. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.js.map +1 -1
  89. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.d.ts +1 -1
  90. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.d.ts.map +1 -1
  91. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.js +24 -24
  92. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.js.map +1 -1
  93. package/dist/src/runtime/browser/screenshot/targets.d.ts +2 -2
  94. package/dist/src/runtime/browser/screenshot/targets.js +9 -9
  95. package/dist/src/runtime/browser/screenshot/utils.d.ts +1 -1
  96. package/dist/src/runtime/browser/screenshot/utils.d.ts.map +1 -1
  97. package/dist/src/runtime/browser/screenshot/utils.js +73 -71
  98. package/dist/src/runtime/browser/screenshot/utils.js.map +1 -1
  99. package/dist/src/runtime/browser/selector-discovery.d.ts +1 -1
  100. package/dist/src/runtime/browser/selector-discovery.d.ts.map +1 -1
  101. package/dist/src/runtime/browser/selector-discovery.js +24 -22
  102. package/dist/src/runtime/browser/selector-discovery.js.map +1 -1
  103. package/dist/src/runtime/browser/storage/session-storage.d.ts +10 -5
  104. package/dist/src/runtime/browser/storage/session-storage.d.ts.map +1 -1
  105. package/dist/src/runtime/browser/storage/session-storage.js +12 -10
  106. package/dist/src/runtime/browser/storage/session-storage.js.map +1 -1
  107. package/dist/src/runtime/browser/types.d.ts +7 -7
  108. package/dist/src/runtime/browser/types.js +1 -1
  109. package/dist/src/runtime/browser/utils/console.d.ts +1 -1
  110. package/dist/src/runtime/browser/utils/console.js +16 -16
  111. package/dist/src/runtime/browser/utils/console.js.map +1 -1
  112. package/dist/src/runtime/browser/utils/environment.js +2 -2
  113. package/dist/src/runtime/browser/utils/errors.d.ts.map +1 -1
  114. package/dist/src/runtime/browser/utils/errors.js +11 -11
  115. package/dist/src/runtime/browser/utils/number.d.ts.map +1 -1
  116. package/dist/src/runtime/browser/utils/number.js.map +1 -1
  117. package/dist/src/runtime/browser/utils/object.d.ts.map +1 -1
  118. package/dist/src/runtime/browser/utils/object.js +2 -2
  119. package/dist/src/runtime/browser/utils/object.js.map +1 -1
  120. package/dist/src/runtime/browser/utils/sanitize.js +2 -2
  121. package/dist/src/runtime/browser/utils/time.d.ts.map +1 -1
  122. package/dist/src/runtime/browser/utils/time.js +1 -1
  123. package/dist/src/runtime/chrome/cookies.d.ts +4 -4
  124. package/dist/src/runtime/chrome/cookies.d.ts.map +1 -1
  125. package/dist/src/runtime/chrome/cookies.js +31 -31
  126. package/dist/src/runtime/chrome/cookies.js.map +1 -1
  127. package/dist/src/runtime/chrome/deep-link.d.ts +1 -1
  128. package/dist/src/runtime/chrome/deep-link.d.ts.map +1 -1
  129. package/dist/src/runtime/chrome/deep-link.js +46 -36
  130. package/dist/src/runtime/chrome/deep-link.js.map +1 -1
  131. package/dist/src/runtime/chrome/diagnostics.d.ts.map +1 -1
  132. package/dist/src/runtime/chrome/diagnostics.js +13 -11
  133. package/dist/src/runtime/chrome/diagnostics.js.map +1 -1
  134. package/dist/src/runtime/chrome/focus.d.ts.map +1 -1
  135. package/dist/src/runtime/chrome/focus.js +5 -5
  136. package/dist/src/runtime/chrome/focus.js.map +1 -1
  137. package/dist/src/runtime/chrome/launch.d.ts.map +1 -1
  138. package/dist/src/runtime/chrome/launch.js +30 -30
  139. package/dist/src/runtime/chrome/launch.js.map +1 -1
  140. package/dist/src/runtime/chrome/puppeteer.d.ts +2 -2
  141. package/dist/src/runtime/chrome/puppeteer.d.ts.map +1 -1
  142. package/dist/src/runtime/chrome/puppeteer.js +16 -11
  143. package/dist/src/runtime/chrome/puppeteer.js.map +1 -1
  144. package/dist/src/runtime/chrome/reuse.d.ts.map +1 -1
  145. package/dist/src/runtime/chrome/reuse.js +38 -35
  146. package/dist/src/runtime/chrome/reuse.js.map +1 -1
  147. package/dist/src/runtime/chrome/session.d.ts +1 -1
  148. package/dist/src/runtime/chrome/session.d.ts.map +1 -1
  149. package/dist/src/runtime/chrome/session.js +12 -10
  150. package/dist/src/runtime/chrome/session.js.map +1 -1
  151. package/dist/src/runtime/chrome.d.ts +8 -8
  152. package/dist/src/runtime/chrome.js +8 -8
  153. package/dist/src/runtime/cookies.d.ts +1 -16
  154. package/dist/src/runtime/cookies.d.ts.map +1 -1
  155. package/dist/src/runtime/cookies.js +175 -286
  156. package/dist/src/runtime/cookies.js.map +1 -1
  157. package/dist/src/runtime/devstack.d.ts +1 -1
  158. package/dist/src/runtime/devstack.d.ts.map +1 -1
  159. package/dist/src/runtime/devstack.js +31 -28
  160. package/dist/src/runtime/devstack.js.map +1 -1
  161. package/dist/src/runtime/devtools/background.js +22 -22
  162. package/dist/src/runtime/devtools/cdp.d.ts +3 -3
  163. package/dist/src/runtime/devtools/cdp.d.ts.map +1 -1
  164. package/dist/src/runtime/devtools/cdp.js +59 -55
  165. package/dist/src/runtime/devtools/cdp.js.map +1 -1
  166. package/dist/src/runtime/devtools/config.d.ts.map +1 -1
  167. package/dist/src/runtime/devtools/config.js +15 -15
  168. package/dist/src/runtime/devtools/config.js.map +1 -1
  169. package/dist/src/runtime/devtools/constants.d.ts.map +1 -1
  170. package/dist/src/runtime/devtools/constants.js +18 -10
  171. package/dist/src/runtime/devtools/constants.js.map +1 -1
  172. package/dist/src/runtime/devtools/diagnostics.d.ts +4 -4
  173. package/dist/src/runtime/devtools/diagnostics.d.ts.map +1 -1
  174. package/dist/src/runtime/devtools/diagnostics.js +40 -38
  175. package/dist/src/runtime/devtools/diagnostics.js.map +1 -1
  176. package/dist/src/runtime/devtools/oauth.d.ts +1 -1
  177. package/dist/src/runtime/devtools/oauth.d.ts.map +1 -1
  178. package/dist/src/runtime/devtools/oauth.js +35 -28
  179. package/dist/src/runtime/devtools/oauth.js.map +1 -1
  180. package/dist/src/runtime/devtools/types.d.ts +3 -3
  181. package/dist/src/runtime/devtools/types.d.ts.map +1 -1
  182. package/dist/src/runtime/devtools.d.ts +7 -7
  183. package/dist/src/runtime/devtools.js +7 -7
  184. package/dist/src/runtime/next-devtools.d.ts.map +1 -1
  185. package/dist/src/runtime/next-devtools.js +12 -12
  186. package/dist/src/runtime/next-devtools.js.map +1 -1
  187. package/dist/src/runtime/screenshot.d.ts +9 -9
  188. package/dist/src/runtime/screenshot.d.ts.map +1 -1
  189. package/dist/src/runtime/screenshot.js +65 -46
  190. package/dist/src/runtime/screenshot.js.map +1 -1
  191. package/dist/src/runtime/scripts.d.ts +1 -1
  192. package/dist/src/runtime/scripts.d.ts.map +1 -1
  193. package/dist/src/runtime/scripts.js +28 -28
  194. package/dist/src/runtime/scripts.js.map +1 -1
  195. package/dist/src/runtime/session.d.ts +6 -6
  196. package/dist/src/runtime/session.d.ts.map +1 -1
  197. package/dist/src/runtime/session.js +35 -35
  198. package/dist/src/runtime/session.js.map +1 -1
  199. package/dist/src/runtime/smoke.d.ts +3 -3
  200. package/dist/src/runtime/smoke.d.ts.map +1 -1
  201. package/dist/src/runtime/smoke.js +85 -79
  202. package/dist/src/runtime/smoke.js.map +1 -1
  203. package/dist/src/runtime/url.d.ts +2 -2
  204. package/dist/src/runtime/url.d.ts.map +1 -1
  205. package/dist/src/runtime/url.js +20 -20
  206. package/dist/src/runtime/url.js.map +1 -1
  207. package/dist/src/screenshot-hooks.d.ts +1 -1
  208. package/dist/src/screenshot-hooks.d.ts.map +1 -1
  209. package/dist/src/screenshot-hooks.js +12 -12
  210. package/dist/src/screenshot-hooks.js.map +1 -1
  211. package/dist/src/shared/env.d.ts.map +1 -1
  212. package/dist/src/shared/env.js +11 -11
  213. package/dist/src/shared/env.js.map +1 -1
  214. package/dist/src/shared/index.d.ts +30 -30
  215. package/dist/src/shared/index.d.ts.map +1 -1
  216. package/dist/src/shared/index.js +17 -17
  217. package/dist/src/shared/index.js.map +1 -1
  218. package/dist/src/shared/node.d.ts +1 -1
  219. package/dist/src/shared/node.d.ts.map +1 -1
  220. package/dist/src/shared/node.js +18 -18
  221. package/dist/src/shared/node.js.map +1 -1
  222. package/dist/src/token.d.ts +1 -1
  223. package/dist/src/token.d.ts.map +1 -1
  224. package/dist/src/token.js +16 -16
  225. package/dist/src/token.js.map +1 -1
  226. package/dist/src/types.d.ts +1 -1
  227. package/dist/src/util/app-label.js +4 -4
  228. package/dist/src/util/errors.d.ts.map +1 -1
  229. package/dist/src/util/errors.js +12 -10
  230. package/dist/src/util/errors.js.map +1 -1
  231. package/dist/src/util/path.js +2 -2
  232. package/dist/src/util/regex.js +4 -4
  233. package/package.json +53 -45
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import 'dotenv/config';
3
- import { spawnSync } from 'node:child_process';
4
- import { existsSync, mkdirSync, readFileSync } from 'node:fs';
5
- import { createServer as createHttpsServer, request as httpsRequest } from 'node:https';
6
- import os from 'node:os';
7
- import path from 'node:path';
8
- import { URL } from 'node:url';
9
- import { createSweetLinkCommandId, SWEETLINK_DEFAULT_PORT, SWEETLINK_HEARTBEAT_INTERVAL_MS, SWEETLINK_HEARTBEAT_TOLERANCE_MS, SWEETLINK_WS_PATH, verifySweetLinkToken, } from '../../shared/src/index.js';
10
- import { readSweetLinkEnv } from '../../shared/src/env.js';
11
- import { getDefaultSweetLinkSecretPath, resolveSweetLinkSecret, } from '../../shared/src/node.js';
12
- import WebSocket, { WebSocketServer } from 'ws';
13
- import { z } from 'zod';
14
- import { generateSessionCodename } from './codename.js';
2
+ import "dotenv/config";
3
+ import { spawnSync } from "node:child_process";
4
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
5
+ import { createServer as createHttpsServer, request as httpsRequest } from "node:https";
6
+ import os from "node:os";
7
+ import path from "node:path";
8
+ import { URL } from "node:url";
9
+ import { createSweetLinkCommandId, SWEETLINK_DEFAULT_PORT, SWEETLINK_HEARTBEAT_INTERVAL_MS, SWEETLINK_HEARTBEAT_TOLERANCE_MS, SWEETLINK_WS_PATH, verifySweetLinkToken, } from "../../shared/src/index.js";
10
+ import { readSweetLinkEnv } from "../../shared/src/env.js";
11
+ import { getDefaultSweetLinkSecretPath, resolveSweetLinkSecret, } from "../../shared/src/node.js";
12
+ import WebSocket, { WebSocketServer } from "ws";
13
+ import { z } from "zod";
14
+ import { formatDaemonHelp, isDaemonHelpRequest } from "./cli.js";
15
+ import { generateSessionCodename } from "./codename.js";
15
16
  const SHUTDOWN_GRACE_MS = 1000;
16
17
  const unrefTimer = (handle) => {
17
18
  const candidate = handle;
18
- if (typeof candidate === 'object' && candidate !== null && 'unref' in candidate) {
19
+ if (typeof candidate === "object" && candidate !== null && "unref" in candidate) {
19
20
  const unref = candidate.unref;
20
- if (typeof unref === 'function') {
21
+ if (typeof unref === "function") {
21
22
  unref.call(candidate);
22
23
  }
23
24
  }
@@ -26,31 +27,31 @@ const toError = (value) => {
26
27
  if (value instanceof Error) {
27
28
  return value;
28
29
  }
29
- if (typeof value === 'string') {
30
+ if (typeof value === "string") {
30
31
  return Object.assign(new Error(value), { cause: value });
31
32
  }
32
- if (value && typeof value === 'object' && 'message' in value) {
33
+ if (value && typeof value === "object" && "message" in value) {
33
34
  const candidate = value.message;
34
- if (typeof candidate === 'string' && candidate.trim().length > 0) {
35
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
35
36
  return Object.assign(new Error(candidate.trim()), { cause: value });
36
37
  }
37
38
  }
38
- return Object.assign(new Error('Unknown error'), { cause: value });
39
+ return Object.assign(new Error("Unknown error"), { cause: value });
39
40
  };
40
41
  const getErrorMessage = (value) => {
41
42
  const error = toError(value);
42
- return error.message || 'Unknown error';
43
+ return error.message || "Unknown error";
43
44
  };
44
- const CERT_DIR = path.join(os.homedir(), '.sweetlink', 'certs');
45
- const CERT_PATH = path.join(CERT_DIR, 'localhost-cert.pem');
46
- const KEY_PATH = path.join(CERT_DIR, 'localhost-key.pem');
45
+ const CERT_DIR = path.join(os.homedir(), ".sweetlink", "certs");
46
+ const CERT_PATH = path.join(CERT_DIR, "localhost-cert.pem");
47
+ const KEY_PATH = path.join(CERT_DIR, "localhost-key.pem");
47
48
  const SOCKET_STATE_LABEL = {
48
- 0: 'connecting',
49
- 1: 'open',
50
- 2: 'closing',
51
- 3: 'closed',
49
+ 0: "connecting",
50
+ 1: "open",
51
+ 2: "closing",
52
+ 3: "closed",
52
53
  };
53
- const SweetLinkConsoleLevelSchema = z.enum(['log', 'info', 'warn', 'error', 'debug']);
54
+ const SweetLinkConsoleLevelSchema = z.enum(["log", "info", "warn", "error", "debug"]);
54
55
  const consoleEventSchema = z
55
56
  .object({
56
57
  id: z.string(),
@@ -59,7 +60,7 @@ const consoleEventSchema = z
59
60
  args: z.array(z.unknown()),
60
61
  })
61
62
  .passthrough();
62
- const commandResultSchema = z.discriminatedUnion('ok', [
63
+ const commandResultSchema = z.discriminatedUnion("ok", [
63
64
  z
64
65
  .object({
65
66
  ok: z.literal(true),
@@ -82,7 +83,7 @@ const commandResultSchema = z.discriminatedUnion('ok', [
82
83
  ]);
83
84
  const registerMessageSchema = z
84
85
  .object({
85
- kind: z.literal('register'),
86
+ kind: z.literal("register"),
86
87
  token: z.string(),
87
88
  sessionId: z.string(),
88
89
  url: z.string(),
@@ -93,25 +94,25 @@ const registerMessageSchema = z
93
94
  .passthrough();
94
95
  const heartbeatMessageSchema = z
95
96
  .object({
96
- kind: z.literal('heartbeat'),
97
+ kind: z.literal("heartbeat"),
97
98
  sessionId: z.string(),
98
99
  })
99
100
  .passthrough();
100
101
  const commandResultMessageSchema = z
101
102
  .object({
102
- kind: z.literal('commandResult'),
103
+ kind: z.literal("commandResult"),
103
104
  sessionId: z.string(),
104
105
  result: commandResultSchema,
105
106
  })
106
107
  .passthrough();
107
108
  const consoleMessageSchema = z
108
109
  .object({
109
- kind: z.literal('console'),
110
+ kind: z.literal("console"),
110
111
  sessionId: z.string(),
111
112
  events: z.array(consoleEventSchema),
112
113
  })
113
114
  .passthrough();
114
- const clientMessageSchema = z.discriminatedUnion('kind', [
115
+ const clientMessageSchema = z.discriminatedUnion("kind", [
115
116
  registerMessageSchema,
116
117
  heartbeatMessageSchema,
117
118
  commandResultMessageSchema,
@@ -119,7 +120,7 @@ const clientMessageSchema = z.discriminatedUnion('kind', [
119
120
  ]);
120
121
  const runScriptCommandSchema = z
121
122
  .object({
122
- type: z.literal('runScript'),
123
+ type: z.literal("runScript"),
123
124
  code: z.string(),
124
125
  timeoutMs: z.number().finite().positive().optional(),
125
126
  captureConsole: z.boolean().optional(),
@@ -127,44 +128,49 @@ const runScriptCommandSchema = z
127
128
  .passthrough();
128
129
  const getDomCommandSchema = z
129
130
  .object({
130
- type: z.literal('getDom'),
131
+ type: z.literal("getDom"),
131
132
  selector: z.string().optional(),
132
133
  includeShadowDom: z.boolean().optional(),
133
134
  })
134
135
  .passthrough();
135
136
  const navigateCommandSchema = z
136
137
  .object({
137
- type: z.literal('navigate'),
138
+ type: z.literal("navigate"),
138
139
  url: z.string(),
139
140
  })
140
141
  .passthrough();
141
142
  const pingCommandSchema = z
142
143
  .object({
143
- type: z.literal('ping'),
144
+ type: z.literal("ping"),
144
145
  })
145
146
  .passthrough();
146
147
  const screenshotCommandSchema = z
147
148
  .object({
148
- type: z.literal('screenshot'),
149
- mode: z.union([z.literal('full'), z.literal('element')]).default('full'),
149
+ type: z.literal("screenshot"),
150
+ mode: z.union([z.literal("full"), z.literal("element")]).default("full"),
150
151
  selector: z.union([z.string(), z.null()]).optional(),
151
152
  quality: z.number().finite().min(0).max(100).optional(),
152
153
  timeoutMs: z.number().finite().positive().optional(),
153
154
  renderer: z
154
- .union([z.literal('auto'), z.literal('puppeteer'), z.literal('html2canvas'), z.literal('html-to-image')])
155
+ .union([
156
+ z.literal("auto"),
157
+ z.literal("puppeteer"),
158
+ z.literal("html2canvas"),
159
+ z.literal("html-to-image"),
160
+ ])
155
161
  .optional(),
156
162
  hooks: z.array(z.unknown()).optional(),
157
163
  })
158
164
  .passthrough();
159
165
  const discoverSelectorsCommandSchema = z
160
166
  .object({
161
- type: z.literal('discoverSelectors'),
167
+ type: z.literal("discoverSelectors"),
162
168
  scopeSelector: z.union([z.string(), z.null()]).optional(),
163
169
  limit: z.number().int().positive().optional(),
164
170
  includeHidden: z.boolean().optional(),
165
171
  })
166
172
  .passthrough();
167
- const commandSchema = z.discriminatedUnion('type', [
173
+ const commandSchema = z.discriminatedUnion("type", [
168
174
  runScriptCommandSchema,
169
175
  getDomCommandSchema,
170
176
  navigateCommandSchema,
@@ -174,33 +180,35 @@ const commandSchema = z.discriminatedUnion('type', [
174
180
  ]);
175
181
  const timeoutOverrideSchema = z.number().finite().positive().optional();
176
182
  const resolveDaemonPort = (value) => {
177
- if (value && typeof value === 'object' && value !== null) {
183
+ if (value && typeof value === "object" && value !== null) {
178
184
  const portCandidate = value.port;
179
- if (typeof portCandidate === 'number' && Number.isFinite(portCandidate) && portCandidate > 0) {
185
+ if (typeof portCandidate === "number" && Number.isFinite(portCandidate) && portCandidate > 0) {
180
186
  return portCandidate;
181
187
  }
182
188
  }
183
189
  return SWEETLINK_DEFAULT_PORT;
184
190
  };
185
191
  const isSecretResolution = (value) => {
186
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
192
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
187
193
  return false;
188
194
  }
189
195
  const candidate = value;
190
- if (typeof candidate.secret !== 'string' || candidate.secret.length === 0) {
196
+ if (typeof candidate.secret !== "string" || candidate.secret.length === 0) {
191
197
  return false;
192
198
  }
193
- if (candidate.source !== 'env' && candidate.source !== 'file' && candidate.source !== 'generated') {
199
+ if (candidate.source !== "env" &&
200
+ candidate.source !== "file" &&
201
+ candidate.source !== "generated") {
194
202
  return false;
195
203
  }
196
- if (candidate.path !== undefined && typeof candidate.path !== 'string') {
204
+ if (candidate.path !== undefined && typeof candidate.path !== "string") {
197
205
  return false;
198
206
  }
199
207
  return true;
200
208
  };
201
209
  const assertSecretResolution = (value) => {
202
210
  if (!isSecretResolution(value)) {
203
- throw new TypeError('SweetLink secret resolution payload is invalid');
211
+ throw new TypeError("SweetLink secret resolution payload is invalid");
204
212
  }
205
213
  return value;
206
214
  };
@@ -213,24 +221,24 @@ async function main() {
213
221
  }
214
222
  const rawSecretResolution = await resolveSweetLinkSecret({ autoCreate: true });
215
223
  const { secret, source, path: secretPath } = assertSecretResolution(rawSecretResolution);
216
- log(`SweetLink secret source: ${source}${secretPath ? ` (${secretPath})` : ''}`);
224
+ log(`SweetLink secret source: ${source}${secretPath ? ` (${secretPath})` : ""}`);
217
225
  ensureCertificates();
218
226
  const { cert, key } = loadCertificates();
219
227
  const state = new SweetLinkState(secret);
220
228
  const server = createHttpsServer({ key, cert }, (req, res) => {
221
229
  handleHttpRequest(state, req, res).catch((error) => {
222
- console.warn('SweetLink daemon request handler failed:', getErrorMessage(error));
230
+ console.warn("SweetLink daemon request handler failed:", getErrorMessage(error));
223
231
  });
224
232
  });
225
233
  const wsServer = new WebSocketServer({ server, path: SWEETLINK_WS_PATH });
226
- wsServer.on('connection', (socket) => state.handleSocket(socket));
227
- server.listen(daemonPort, '127.0.0.1', () => {
234
+ wsServer.on("connection", (socket) => state.handleSocket(socket));
235
+ server.listen(daemonPort, "127.0.0.1", () => {
228
236
  log(`SweetLink daemon listening on https://localhost:${daemonPort}`);
229
237
  log(`WebSocket endpoint ready at wss://localhost:${daemonPort}${SWEETLINK_WS_PATH}`);
230
- log('Press Ctrl+C to stop.');
238
+ log("Press Ctrl+C to stop.");
231
239
  });
232
- process.on('SIGINT', () => shutdown('SIGINT'));
233
- process.on('SIGTERM', () => shutdown('SIGTERM'));
240
+ process.on("SIGINT", () => shutdown("SIGINT"));
241
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
234
242
  function shutdown(signal) {
235
243
  log(`Received ${signal}, shutting down SweetLink daemon...`);
236
244
  wsServer.close();
@@ -248,18 +256,18 @@ async function main() {
248
256
  async function isDaemonAlreadyRunning(port) {
249
257
  return await new Promise((resolve) => {
250
258
  const request = httpsRequest({
251
- hostname: '127.0.0.1',
259
+ hostname: "127.0.0.1",
252
260
  port,
253
- path: '/healthz',
254
- method: 'GET',
261
+ path: "/healthz",
262
+ method: "GET",
255
263
  rejectUnauthorized: false,
256
264
  timeout: 750,
257
265
  }, (response) => {
258
266
  response.resume();
259
267
  resolve(response.statusCode === 200);
260
268
  });
261
- request.on('error', () => resolve(false));
262
- request.on('timeout', () => {
269
+ request.on("error", () => resolve(false));
270
+ request.on("timeout", () => {
263
271
  request.destroy();
264
272
  resolve(false);
265
273
  });
@@ -275,29 +283,29 @@ class SweetLinkState {
275
283
  unrefTimer(expiryInterval);
276
284
  }
277
285
  verifyCliToken(token) {
278
- return verifySweetLinkToken({ secret: this.#secret, token, expectedScope: 'cli' });
286
+ return verifySweetLinkToken({ secret: this.#secret, token, expectedScope: "cli" });
279
287
  }
280
288
  handleSocket(socket) {
281
289
  let sessionId = null;
282
- socket.on('message', (data) => {
290
+ socket.on("message", (data) => {
283
291
  try {
284
292
  const raw = decodeSocketPayload(data);
285
293
  const parsedMessage = parseClientMessage(JSON.parse(raw));
286
294
  const message = parsedMessage;
287
295
  switch (message.kind) {
288
- case 'register': {
296
+ case "register": {
289
297
  sessionId = this.#handleRegister(socket, message);
290
298
  break;
291
299
  }
292
- case 'heartbeat': {
300
+ case "heartbeat": {
293
301
  this.#touchSession(message.sessionId);
294
302
  break;
295
303
  }
296
- case 'commandResult': {
304
+ case "commandResult": {
297
305
  this.#handleCommandResult(message.sessionId, message.result);
298
306
  break;
299
307
  }
300
- case 'console': {
308
+ case "console": {
301
309
  this.#handleConsoleEvents(message.sessionId, message.events);
302
310
  break;
303
311
  }
@@ -314,10 +322,12 @@ class SweetLinkState {
314
322
  console.warn(`SweetLink socket error: ${errorMessage}`);
315
323
  }
316
324
  });
317
- socket.once('close', (code, reasonBuffer) => {
325
+ socket.once("close", (code, reasonBuffer) => {
318
326
  if (sessionId) {
319
- const reasonText = reasonBuffer?.toString?.('utf8') ?? '';
320
- const closeDetail = reasonText && reasonText.length > 0 ? `socket closed (${code}: ${reasonText})` : `socket closed (${code})`;
327
+ const reasonText = reasonBuffer?.toString?.("utf8") ?? "";
328
+ const closeDetail = reasonText && reasonText.length > 0
329
+ ? `socket closed (${code}: ${reasonText})`
330
+ : `socket closed (${code})`;
321
331
  this.#removeSession(sessionId, closeDetail);
322
332
  }
323
333
  });
@@ -328,7 +338,7 @@ class SweetLinkState {
328
338
  const consoleEventsBuffered = entry.consoleBuffer.length;
329
339
  let consoleErrorsBuffered = 0;
330
340
  for (const event of entry.consoleBuffer) {
331
- if (event.level === 'error') {
341
+ if (event.level === "error") {
332
342
  consoleErrorsBuffered += 1;
333
343
  }
334
344
  }
@@ -354,15 +364,15 @@ class SweetLinkState {
354
364
  sendCommand(sessionId, rawCommand, timeoutMs = 15_000) {
355
365
  const session = this.#sessions.get(sessionId);
356
366
  if (!session) {
357
- throw new Error('Session not found or offline');
367
+ throw new Error("Session not found or offline");
358
368
  }
359
369
  if (session.socket.readyState !== WebSocket.OPEN) {
360
- throw new Error('Session socket is not open');
370
+ throw new Error("Session socket is not open");
361
371
  }
362
372
  const commandId = createSweetLinkCommandId();
363
373
  const command = { ...rawCommand, id: commandId };
364
374
  const payload = {
365
- kind: 'command',
375
+ kind: "command",
366
376
  sessionId: session.metadata.sessionId,
367
377
  command,
368
378
  };
@@ -370,7 +380,7 @@ class SweetLinkState {
370
380
  return new Promise((resolve, reject) => {
371
381
  const timeout = setTimeout(() => {
372
382
  session.pending.delete(commandId);
373
- reject(new Error('Command timed out'));
383
+ reject(new Error("Command timed out"));
374
384
  }, timeoutMs);
375
385
  session.pending.set(commandId, {
376
386
  commandId,
@@ -400,9 +410,9 @@ class SweetLinkState {
400
410
  #handleRegister(socket, message) {
401
411
  const token = message.token;
402
412
  const sessionId = message.sessionId;
403
- const payload = verifySweetLinkToken({ secret: this.#secret, token, expectedScope: 'session' });
413
+ const payload = verifySweetLinkToken({ secret: this.#secret, token, expectedScope: "session" });
404
414
  if (!payload.sessionId || payload.sessionId !== sessionId) {
405
- throw new Error('Session token mismatch');
415
+ throw new Error("Session token mismatch");
406
416
  }
407
417
  const metadata = {
408
418
  sessionId,
@@ -429,7 +439,7 @@ class SweetLinkState {
429
439
  this.#sessions.set(sessionId, entry);
430
440
  try {
431
441
  const metadataMessage = {
432
- kind: 'metadata',
442
+ kind: "metadata",
433
443
  sessionId,
434
444
  codename: metadata.codename,
435
445
  };
@@ -476,7 +486,7 @@ class SweetLinkState {
476
486
  }
477
487
  }
478
488
  #socketStateToString(readyState) {
479
- return SOCKET_STATE_LABEL[readyState] ?? 'unknown';
489
+ return SOCKET_STATE_LABEL[readyState] ?? "unknown";
480
490
  }
481
491
  #removeSession(sessionId, reason) {
482
492
  const session = this.#sessions.get(sessionId);
@@ -505,24 +515,24 @@ async function handleHttpRequest(state, req, res) {
505
515
  const basePort = daemonPort;
506
516
  const requestUrl = req.url ? new URL(req.url, `https://localhost:${basePort}`) : null;
507
517
  if (!requestUrl) {
508
- respondJson(res, 400, { error: 'Invalid request URL' });
518
+ respondJson(res, 400, { error: "Invalid request URL" });
509
519
  return;
510
520
  }
511
- if (req.method === 'OPTIONS') {
521
+ if (req.method === "OPTIONS") {
512
522
  respondCors(res);
513
523
  return;
514
524
  }
515
- if (requestUrl.pathname === '/healthz') {
516
- respondJson(res, 200, { status: 'ok' });
525
+ if (requestUrl.pathname === "/healthz") {
526
+ respondJson(res, 200, { status: "ok" });
517
527
  return;
518
528
  }
519
529
  const authorization = req.headers.authorization;
520
- if (!authorization?.startsWith('Bearer ')) {
521
- respondJson(res, 401, { error: 'Missing SweetLink token' });
530
+ if (!authorization?.startsWith("Bearer ")) {
531
+ respondJson(res, 401, { error: "Missing SweetLink token" });
522
532
  return;
523
533
  }
524
534
  try {
525
- const token = authorization.slice('Bearer '.length).trim();
535
+ const token = authorization.slice("Bearer ".length).trim();
526
536
  state.verifyCliToken(token);
527
537
  }
528
538
  catch (error) {
@@ -530,29 +540,29 @@ async function handleHttpRequest(state, req, res) {
530
540
  respondJson(res, 401, { error: message });
531
541
  return;
532
542
  }
533
- if (req.method === 'GET' && requestUrl.pathname === '/sessions') {
543
+ if (req.method === "GET" && requestUrl.pathname === "/sessions") {
534
544
  const sessions = state.listSessions();
535
545
  respondJson(res, 200, { sessions });
536
546
  return;
537
547
  }
538
- if (req.method === 'GET' &&
539
- requestUrl.pathname.startsWith('/sessions/') &&
540
- requestUrl.pathname.endsWith('/console')) {
541
- const sessionId = requestUrl.pathname.split('/')[2];
548
+ if (req.method === "GET" &&
549
+ requestUrl.pathname.startsWith("/sessions/") &&
550
+ requestUrl.pathname.endsWith("/console")) {
551
+ const sessionId = requestUrl.pathname.split("/")[2];
542
552
  if (sessionId == null) {
543
- respondJson(res, 400, { error: 'Session id missing' });
553
+ respondJson(res, 400, { error: "Session id missing" });
544
554
  return;
545
555
  }
546
556
  const events = state.getSessionConsole(sessionId);
547
557
  respondJson(res, 200, { sessionId, events });
548
558
  return;
549
559
  }
550
- if (req.method === 'POST' &&
551
- requestUrl.pathname.startsWith('/sessions/') &&
552
- requestUrl.pathname.endsWith('/command')) {
553
- const sessionId = requestUrl.pathname.split('/')[2];
560
+ if (req.method === "POST" &&
561
+ requestUrl.pathname.startsWith("/sessions/") &&
562
+ requestUrl.pathname.endsWith("/command")) {
563
+ const sessionId = requestUrl.pathname.split("/")[2];
554
564
  if (sessionId == null) {
555
- respondJson(res, 400, { error: 'Session id missing' });
565
+ respondJson(res, 400, { error: "Session id missing" });
556
566
  return;
557
567
  }
558
568
  try {
@@ -567,18 +577,18 @@ async function handleHttpRequest(state, req, res) {
567
577
  }
568
578
  return;
569
579
  }
570
- respondJson(res, 404, { error: 'Not Found' });
580
+ respondJson(res, 404, { error: "Not Found" });
571
581
  }
572
582
  async function readJson(req) {
573
583
  const chunks = [];
574
584
  for await (const chunk of req) {
575
- const bufferChunk = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk;
585
+ const bufferChunk = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
576
586
  chunks.push(bufferChunk);
577
587
  }
578
588
  if (chunks.length === 0) {
579
589
  return {};
580
590
  }
581
- const text = Buffer.concat(chunks).toString('utf8');
591
+ const text = Buffer.concat(chunks).toString("utf8");
582
592
  if (!text) {
583
593
  return {};
584
594
  }
@@ -587,38 +597,38 @@ async function readJson(req) {
587
597
  function respondJson(res, status, body) {
588
598
  const payload = JSON.stringify(body ?? {}, null, 2);
589
599
  res.statusCode = status;
590
- res.setHeader('Content-Type', 'application/json');
591
- res.setHeader('Access-Control-Allow-Origin', '*');
592
- res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
593
- res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
600
+ res.setHeader("Content-Type", "application/json");
601
+ res.setHeader("Access-Control-Allow-Origin", "*");
602
+ res.setHeader("Access-Control-Allow-Headers", "authorization, content-type");
603
+ res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
594
604
  res.end(payload);
595
605
  }
596
606
  function respondCors(res) {
597
607
  res.statusCode = 204;
598
- res.setHeader('Access-Control-Allow-Origin', '*');
599
- res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
600
- res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
608
+ res.setHeader("Access-Control-Allow-Origin", "*");
609
+ res.setHeader("Access-Control-Allow-Headers", "authorization, content-type");
610
+ res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
601
611
  res.end();
602
612
  }
603
613
  function decodeSocketPayload(data) {
604
- if (typeof data === 'string') {
614
+ if (typeof data === "string") {
605
615
  return data;
606
616
  }
607
617
  if (Buffer.isBuffer(data)) {
608
- return data.toString('utf8');
618
+ return data.toString("utf8");
609
619
  }
610
620
  if (Array.isArray(data)) {
611
621
  const buffers = data.map((chunk) => (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
612
- return Buffer.concat(buffers).toString('utf8');
622
+ return Buffer.concat(buffers).toString("utf8");
613
623
  }
614
624
  if (ArrayBuffer.isView(data)) {
615
625
  const view = data;
616
- return Buffer.from(view.buffer, view.byteOffset, view.byteLength).toString('utf8');
626
+ return Buffer.from(view.buffer, view.byteOffset, view.byteLength).toString("utf8");
617
627
  }
618
628
  if (data instanceof ArrayBuffer) {
619
- return Buffer.from(data).toString('utf8');
629
+ return Buffer.from(data).toString("utf8");
620
630
  }
621
- return Buffer.from([]).toString('utf8');
631
+ return Buffer.from([]).toString("utf8");
622
632
  }
623
633
  function parseClientMessage(raw) {
624
634
  return clientMessageSchema.parse(raw);
@@ -630,8 +640,8 @@ function parseCommandRequest(raw) {
630
640
  return { command, timeoutMs };
631
641
  }
632
642
  function ensureObject(value) {
633
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
634
- throw new Error('Request body must be a JSON object');
643
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
644
+ throw new Error("Request body must be a JSON object");
635
645
  }
636
646
  return value;
637
647
  }
@@ -639,21 +649,21 @@ function ensureCertificates() {
639
649
  if (existsSync(CERT_PATH) && existsSync(KEY_PATH)) {
640
650
  return;
641
651
  }
642
- log('Generating SweetLink TLS certificates via mkcert...');
652
+ log("Generating SweetLink TLS certificates via mkcert...");
643
653
  mkdirSync(CERT_DIR, { recursive: true });
644
- const mkcertLookup = spawnSync('which', ['mkcert'], { stdio: 'pipe' });
654
+ const mkcertLookup = spawnSync("which", ["mkcert"], { stdio: "pipe" });
645
655
  if (mkcertLookup.status !== 0) {
646
656
  const secretPath = getDefaultSweetLinkSecretPath();
647
657
  throw new Error('mkcert is required but not found. Install via "brew install mkcert nss" and rerun pnpm sweetlink. ' +
648
658
  `Generated SweetLink secret saved at ${secretPath}.`);
649
659
  }
650
- const install = spawnSync('mkcert', ['-install'], { stdio: 'inherit' });
660
+ const install = spawnSync("mkcert", ["-install"], { stdio: "inherit" });
651
661
  if (install.status !== 0) {
652
- throw new Error('Failed to run mkcert -install');
662
+ throw new Error("Failed to run mkcert -install");
653
663
  }
654
- const create = spawnSync('mkcert', ['-cert-file', CERT_PATH, '-key-file', KEY_PATH, 'localhost', '127.0.0.1', '::1'], { stdio: 'inherit' });
664
+ const create = spawnSync("mkcert", ["-cert-file", CERT_PATH, "-key-file", KEY_PATH, "localhost", "127.0.0.1", "::1"], { stdio: "inherit" });
655
665
  if (create.status !== 0) {
656
- throw new Error('Failed to generate mkcert certificates');
666
+ throw new Error("Failed to generate mkcert certificates");
657
667
  }
658
668
  }
659
669
  function loadCertificates() {
@@ -664,12 +674,17 @@ function loadCertificates() {
664
674
  function log(message) {
665
675
  console.log(`[SweetLink] ${message}`);
666
676
  }
667
- try {
668
- await main();
677
+ if (isDaemonHelpRequest(process.argv.slice(2))) {
678
+ console.log(formatDaemonHelp());
669
679
  }
670
- catch (error) {
671
- const message = getErrorMessage(error);
672
- console.error(`[SweetLink] Daemon failed: ${message}`);
673
- process.exit(1);
680
+ else {
681
+ try {
682
+ await main();
683
+ }
684
+ catch (error) {
685
+ const message = getErrorMessage(error);
686
+ console.error(`[SweetLink] Daemon failed: ${message}`);
687
+ process.exit(1);
688
+ }
674
689
  }
675
690
  //# sourceMappingURL=index.js.map