sweetlink 0.1.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.
Files changed (300) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +237 -0
  4. package/dist/daemon/src/codename.d.ts +8 -0
  5. package/dist/daemon/src/codename.d.ts.map +1 -0
  6. package/dist/daemon/src/codename.js +42 -0
  7. package/dist/daemon/src/codename.js.map +1 -0
  8. package/dist/daemon/src/index.d.ts +3 -0
  9. package/dist/daemon/src/index.d.ts.map +1 -0
  10. package/dist/daemon/src/index.js +675 -0
  11. package/dist/daemon/src/index.js.map +1 -0
  12. package/dist/shared/src/env.d.ts +24 -0
  13. package/dist/shared/src/env.d.ts.map +1 -0
  14. package/dist/shared/src/env.js +39 -0
  15. package/dist/shared/src/env.js.map +1 -0
  16. package/dist/shared/src/index.d.ts +211 -0
  17. package/dist/shared/src/index.d.ts.map +1 -0
  18. package/dist/shared/src/index.js +73 -0
  19. package/dist/shared/src/index.js.map +1 -0
  20. package/dist/shared/src/node.d.ts +12 -0
  21. package/dist/shared/src/node.d.ts.map +1 -0
  22. package/dist/shared/src/node.js +67 -0
  23. package/dist/shared/src/node.js.map +1 -0
  24. package/dist/src/codex.d.ts +11 -0
  25. package/dist/src/codex.d.ts.map +1 -0
  26. package/dist/src/codex.js +67 -0
  27. package/dist/src/codex.js.map +1 -0
  28. package/dist/src/commands/click.d.ts +3 -0
  29. package/dist/src/commands/click.d.ts.map +1 -0
  30. package/dist/src/commands/click.js +93 -0
  31. package/dist/src/commands/click.js.map +1 -0
  32. package/dist/src/commands/run-js.d.ts +4 -0
  33. package/dist/src/commands/run-js.d.ts.map +1 -0
  34. package/dist/src/commands/run-js.js +28 -0
  35. package/dist/src/commands/run-js.js.map +1 -0
  36. package/dist/src/commands/trust-ca.d.ts +3 -0
  37. package/dist/src/commands/trust-ca.d.ts.map +1 -0
  38. package/dist/src/commands/trust-ca.js +43 -0
  39. package/dist/src/commands/trust-ca.js.map +1 -0
  40. package/dist/src/core/config-file.d.ts +41 -0
  41. package/dist/src/core/config-file.d.ts.map +1 -0
  42. package/dist/src/core/config-file.js +284 -0
  43. package/dist/src/core/config-file.js.map +1 -0
  44. package/dist/src/core/config.d.ts +23 -0
  45. package/dist/src/core/config.d.ts.map +1 -0
  46. package/dist/src/core/config.js +132 -0
  47. package/dist/src/core/config.js.map +1 -0
  48. package/dist/src/core/env.d.ts +11 -0
  49. package/dist/src/core/env.d.ts.map +1 -0
  50. package/dist/src/core/env.js +30 -0
  51. package/dist/src/core/env.js.map +1 -0
  52. package/dist/src/devtools-registry.d.ts +3 -0
  53. package/dist/src/devtools-registry.d.ts.map +1 -0
  54. package/dist/src/devtools-registry.js +294 -0
  55. package/dist/src/devtools-registry.js.map +1 -0
  56. package/dist/src/env.d.ts +16 -0
  57. package/dist/src/env.d.ts.map +1 -0
  58. package/dist/src/env.js +17 -0
  59. package/dist/src/env.js.map +1 -0
  60. package/dist/src/http.d.ts +2 -0
  61. package/dist/src/http.d.ts.map +1 -0
  62. package/dist/src/http.js +53 -0
  63. package/dist/src/http.js.map +1 -0
  64. package/dist/src/index.d.ts +19 -0
  65. package/dist/src/index.d.ts.map +1 -0
  66. package/dist/src/index.js +1941 -0
  67. package/dist/src/index.js.map +1 -0
  68. package/dist/src/runtime/browser/client.d.ts +10 -0
  69. package/dist/src/runtime/browser/client.d.ts.map +1 -0
  70. package/dist/src/runtime/browser/client.js +497 -0
  71. package/dist/src/runtime/browser/client.js.map +1 -0
  72. package/dist/src/runtime/browser/commands/index.d.ts +10 -0
  73. package/dist/src/runtime/browser/commands/index.d.ts.map +1 -0
  74. package/dist/src/runtime/browser/commands/index.js +219 -0
  75. package/dist/src/runtime/browser/commands/index.js.map +1 -0
  76. package/dist/src/runtime/browser/dom-to-image-loader.d.ts +6 -0
  77. package/dist/src/runtime/browser/dom-to-image-loader.d.ts.map +1 -0
  78. package/dist/src/runtime/browser/dom-to-image-loader.js +50 -0
  79. package/dist/src/runtime/browser/dom-to-image-loader.js.map +1 -0
  80. package/dist/src/runtime/browser/index.d.ts +4 -0
  81. package/dist/src/runtime/browser/index.d.ts.map +1 -0
  82. package/dist/src/runtime/browser/index.js +4 -0
  83. package/dist/src/runtime/browser/index.js.map +1 -0
  84. package/dist/src/runtime/browser/module-loader.d.ts +6 -0
  85. package/dist/src/runtime/browser/module-loader.d.ts.map +1 -0
  86. package/dist/src/runtime/browser/module-loader.js +26 -0
  87. package/dist/src/runtime/browser/module-loader.js.map +1 -0
  88. package/dist/src/runtime/browser/screenshot/hooks.d.ts +71 -0
  89. package/dist/src/runtime/browser/screenshot/hooks.d.ts.map +1 -0
  90. package/dist/src/runtime/browser/screenshot/hooks.js +219 -0
  91. package/dist/src/runtime/browser/screenshot/hooks.js.map +1 -0
  92. package/dist/src/runtime/browser/screenshot/index.d.ts +9 -0
  93. package/dist/src/runtime/browser/screenshot/index.d.ts.map +1 -0
  94. package/dist/src/runtime/browser/screenshot/index.js +90 -0
  95. package/dist/src/runtime/browser/screenshot/index.js.map +1 -0
  96. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.d.ts +13 -0
  97. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.d.ts.map +1 -0
  98. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.js +51 -0
  99. package/dist/src/runtime/browser/screenshot/renderers/dom-to-image.js.map +1 -0
  100. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.d.ts +12 -0
  101. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.d.ts.map +1 -0
  102. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.js +136 -0
  103. package/dist/src/runtime/browser/screenshot/renderers/html2canvas.js.map +1 -0
  104. package/dist/src/runtime/browser/screenshot/targets.d.ts +6 -0
  105. package/dist/src/runtime/browser/screenshot/targets.d.ts.map +1 -0
  106. package/dist/src/runtime/browser/screenshot/targets.js +53 -0
  107. package/dist/src/runtime/browser/screenshot/targets.js.map +1 -0
  108. package/dist/src/runtime/browser/screenshot/utils.d.ts +9 -0
  109. package/dist/src/runtime/browser/screenshot/utils.d.ts.map +1 -0
  110. package/dist/src/runtime/browser/screenshot/utils.js +471 -0
  111. package/dist/src/runtime/browser/screenshot/utils.js.map +1 -0
  112. package/dist/src/runtime/browser/selector-discovery.d.ts +9 -0
  113. package/dist/src/runtime/browser/selector-discovery.d.ts.map +1 -0
  114. package/dist/src/runtime/browser/selector-discovery.js +218 -0
  115. package/dist/src/runtime/browser/selector-discovery.js.map +1 -0
  116. package/dist/src/runtime/browser/storage/session-storage.d.ts +13 -0
  117. package/dist/src/runtime/browser/storage/session-storage.d.ts.map +1 -0
  118. package/dist/src/runtime/browser/storage/session-storage.js +119 -0
  119. package/dist/src/runtime/browser/storage/session-storage.js.map +1 -0
  120. package/dist/src/runtime/browser/types.d.ts +96 -0
  121. package/dist/src/runtime/browser/types.d.ts.map +1 -0
  122. package/dist/src/runtime/browser/types.js +6 -0
  123. package/dist/src/runtime/browser/types.js.map +1 -0
  124. package/dist/src/runtime/browser/utils/console.d.ts +5 -0
  125. package/dist/src/runtime/browser/utils/console.d.ts.map +1 -0
  126. package/dist/src/runtime/browser/utils/console.js +54 -0
  127. package/dist/src/runtime/browser/utils/console.js.map +1 -0
  128. package/dist/src/runtime/browser/utils/environment.d.ts +3 -0
  129. package/dist/src/runtime/browser/utils/environment.d.ts.map +1 -0
  130. package/dist/src/runtime/browser/utils/environment.js +13 -0
  131. package/dist/src/runtime/browser/utils/environment.js.map +1 -0
  132. package/dist/src/runtime/browser/utils/errors.d.ts +3 -0
  133. package/dist/src/runtime/browser/utils/errors.d.ts.map +1 -0
  134. package/dist/src/runtime/browser/utils/errors.js +42 -0
  135. package/dist/src/runtime/browser/utils/errors.js.map +1 -0
  136. package/dist/src/runtime/browser/utils/number.d.ts +2 -0
  137. package/dist/src/runtime/browser/utils/number.d.ts.map +1 -0
  138. package/dist/src/runtime/browser/utils/number.js +2 -0
  139. package/dist/src/runtime/browser/utils/number.js.map +1 -0
  140. package/dist/src/runtime/browser/utils/object.d.ts +3 -0
  141. package/dist/src/runtime/browser/utils/object.d.ts.map +1 -0
  142. package/dist/src/runtime/browser/utils/object.js +9 -0
  143. package/dist/src/runtime/browser/utils/object.js.map +1 -0
  144. package/dist/src/runtime/browser/utils/sanitize.d.ts +2 -0
  145. package/dist/src/runtime/browser/utils/sanitize.d.ts.map +1 -0
  146. package/dist/src/runtime/browser/utils/sanitize.js +28 -0
  147. package/dist/src/runtime/browser/utils/sanitize.js.map +1 -0
  148. package/dist/src/runtime/browser/utils/time.d.ts +2 -0
  149. package/dist/src/runtime/browser/utils/time.d.ts.map +1 -0
  150. package/dist/src/runtime/browser/utils/time.js +7 -0
  151. package/dist/src/runtime/browser/utils/time.js.map +1 -0
  152. package/dist/src/runtime/chrome/constants.d.ts +5 -0
  153. package/dist/src/runtime/chrome/constants.d.ts.map +1 -0
  154. package/dist/src/runtime/chrome/constants.js +5 -0
  155. package/dist/src/runtime/chrome/constants.js.map +1 -0
  156. package/dist/src/runtime/chrome/cookies.d.ts +20 -0
  157. package/dist/src/runtime/chrome/cookies.d.ts.map +1 -0
  158. package/dist/src/runtime/chrome/cookies.js +139 -0
  159. package/dist/src/runtime/chrome/cookies.js.map +1 -0
  160. package/dist/src/runtime/chrome/diagnostics.d.ts +6 -0
  161. package/dist/src/runtime/chrome/diagnostics.d.ts.map +1 -0
  162. package/dist/src/runtime/chrome/diagnostics.js +49 -0
  163. package/dist/src/runtime/chrome/diagnostics.js.map +1 -0
  164. package/dist/src/runtime/chrome/focus.d.ts +2 -0
  165. package/dist/src/runtime/chrome/focus.d.ts.map +1 -0
  166. package/dist/src/runtime/chrome/focus.js +41 -0
  167. package/dist/src/runtime/chrome/focus.js.map +1 -0
  168. package/dist/src/runtime/chrome/launch.d.ts +23 -0
  169. package/dist/src/runtime/chrome/launch.d.ts.map +1 -0
  170. package/dist/src/runtime/chrome/launch.js +102 -0
  171. package/dist/src/runtime/chrome/launch.js.map +1 -0
  172. package/dist/src/runtime/chrome/puppeteer.d.ts +7 -0
  173. package/dist/src/runtime/chrome/puppeteer.d.ts.map +1 -0
  174. package/dist/src/runtime/chrome/puppeteer.js +87 -0
  175. package/dist/src/runtime/chrome/puppeteer.js.map +1 -0
  176. package/dist/src/runtime/chrome/reuse/constants.d.ts +4 -0
  177. package/dist/src/runtime/chrome/reuse/constants.d.ts.map +1 -0
  178. package/dist/src/runtime/chrome/reuse/constants.js +4 -0
  179. package/dist/src/runtime/chrome/reuse/constants.js.map +1 -0
  180. package/dist/src/runtime/chrome/reuse.d.ts +13 -0
  181. package/dist/src/runtime/chrome/reuse.d.ts.map +1 -0
  182. package/dist/src/runtime/chrome/reuse.js +183 -0
  183. package/dist/src/runtime/chrome/reuse.js.map +1 -0
  184. package/dist/src/runtime/chrome/session.d.ts +13 -0
  185. package/dist/src/runtime/chrome/session.d.ts.map +1 -0
  186. package/dist/src/runtime/chrome/session.js +47 -0
  187. package/dist/src/runtime/chrome/session.js.map +1 -0
  188. package/dist/src/runtime/chrome.d.ts +9 -0
  189. package/dist/src/runtime/chrome.d.ts.map +1 -0
  190. package/dist/src/runtime/chrome.js +10 -0
  191. package/dist/src/runtime/chrome.js.map +1 -0
  192. package/dist/src/runtime/cookies.d.ts +37 -0
  193. package/dist/src/runtime/cookies.d.ts.map +1 -0
  194. package/dist/src/runtime/cookies.js +592 -0
  195. package/dist/src/runtime/cookies.js.map +1 -0
  196. package/dist/src/runtime/devstack.d.ts +14 -0
  197. package/dist/src/runtime/devstack.d.ts.map +1 -0
  198. package/dist/src/runtime/devstack.js +174 -0
  199. package/dist/src/runtime/devstack.js.map +1 -0
  200. package/dist/src/runtime/devtools/background.d.ts +5 -0
  201. package/dist/src/runtime/devtools/background.d.ts.map +1 -0
  202. package/dist/src/runtime/devtools/background.js +109 -0
  203. package/dist/src/runtime/devtools/background.js.map +1 -0
  204. package/dist/src/runtime/devtools/cdp.d.ts +16 -0
  205. package/dist/src/runtime/devtools/cdp.d.ts.map +1 -0
  206. package/dist/src/runtime/devtools/cdp.js +392 -0
  207. package/dist/src/runtime/devtools/cdp.js.map +1 -0
  208. package/dist/src/runtime/devtools/config.d.ts +12 -0
  209. package/dist/src/runtime/devtools/config.d.ts.map +1 -0
  210. package/dist/src/runtime/devtools/config.js +78 -0
  211. package/dist/src/runtime/devtools/config.js.map +1 -0
  212. package/dist/src/runtime/devtools/constants.d.ts +10 -0
  213. package/dist/src/runtime/devtools/constants.d.ts.map +1 -0
  214. package/dist/src/runtime/devtools/constants.js +18 -0
  215. package/dist/src/runtime/devtools/constants.js.map +1 -0
  216. package/dist/src/runtime/devtools/diagnostics.d.ts +8 -0
  217. package/dist/src/runtime/devtools/diagnostics.d.ts.map +1 -0
  218. package/dist/src/runtime/devtools/diagnostics.js +189 -0
  219. package/dist/src/runtime/devtools/diagnostics.js.map +1 -0
  220. package/dist/src/runtime/devtools/oauth.d.ts +9 -0
  221. package/dist/src/runtime/devtools/oauth.d.ts.map +1 -0
  222. package/dist/src/runtime/devtools/oauth.js +130 -0
  223. package/dist/src/runtime/devtools/oauth.js.map +1 -0
  224. package/dist/src/runtime/devtools/types.d.ts +108 -0
  225. package/dist/src/runtime/devtools/types.d.ts.map +1 -0
  226. package/dist/src/runtime/devtools/types.js +2 -0
  227. package/dist/src/runtime/devtools/types.js.map +1 -0
  228. package/dist/src/runtime/devtools.d.ts +8 -0
  229. package/dist/src/runtime/devtools.d.ts.map +1 -0
  230. package/dist/src/runtime/devtools.js +9 -0
  231. package/dist/src/runtime/devtools.js.map +1 -0
  232. package/dist/src/runtime/next-devtools.d.ts +2 -0
  233. package/dist/src/runtime/next-devtools.d.ts.map +1 -0
  234. package/dist/src/runtime/next-devtools.js +72 -0
  235. package/dist/src/runtime/next-devtools.js.map +1 -0
  236. package/dist/src/runtime/screenshot.d.ts +78 -0
  237. package/dist/src/runtime/screenshot.d.ts.map +1 -0
  238. package/dist/src/runtime/screenshot.js +232 -0
  239. package/dist/src/runtime/screenshot.js.map +1 -0
  240. package/dist/src/runtime/scripts.d.ts +16 -0
  241. package/dist/src/runtime/scripts.d.ts.map +1 -0
  242. package/dist/src/runtime/scripts.js +110 -0
  243. package/dist/src/runtime/scripts.js.map +1 -0
  244. package/dist/src/runtime/session.d.ts +64 -0
  245. package/dist/src/runtime/session.d.ts.map +1 -0
  246. package/dist/src/runtime/session.js +205 -0
  247. package/dist/src/runtime/session.js.map +1 -0
  248. package/dist/src/runtime/smoke.d.ts +36 -0
  249. package/dist/src/runtime/smoke.d.ts.map +1 -0
  250. package/dist/src/runtime/smoke.js +417 -0
  251. package/dist/src/runtime/smoke.js.map +1 -0
  252. package/dist/src/runtime/url.d.ts +10 -0
  253. package/dist/src/runtime/url.d.ts.map +1 -0
  254. package/dist/src/runtime/url.js +147 -0
  255. package/dist/src/runtime/url.js.map +1 -0
  256. package/dist/src/screenshot-hooks.d.ts +13 -0
  257. package/dist/src/screenshot-hooks.d.ts.map +1 -0
  258. package/dist/src/screenshot-hooks.js +56 -0
  259. package/dist/src/screenshot-hooks.js.map +1 -0
  260. package/dist/src/shared/env.d.ts +23 -0
  261. package/dist/src/shared/env.d.ts.map +1 -0
  262. package/dist/src/shared/env.js +38 -0
  263. package/dist/src/shared/env.js.map +1 -0
  264. package/dist/src/shared/index.d.ts +211 -0
  265. package/dist/src/shared/index.d.ts.map +1 -0
  266. package/dist/src/shared/index.js +73 -0
  267. package/dist/src/shared/index.js.map +1 -0
  268. package/dist/src/shared/node.d.ts +12 -0
  269. package/dist/src/shared/node.d.ts.map +1 -0
  270. package/dist/src/shared/node.js +67 -0
  271. package/dist/src/shared/node.js.map +1 -0
  272. package/dist/src/token.d.ts +4 -0
  273. package/dist/src/token.d.ts.map +1 -0
  274. package/dist/src/token.js +58 -0
  275. package/dist/src/token.js.map +1 -0
  276. package/dist/src/types.d.ts +17 -0
  277. package/dist/src/types.d.ts.map +1 -0
  278. package/dist/src/types.js +2 -0
  279. package/dist/src/types.js.map +1 -0
  280. package/dist/src/util/app-label.d.ts +5 -0
  281. package/dist/src/util/app-label.d.ts.map +1 -0
  282. package/dist/src/util/app-label.js +21 -0
  283. package/dist/src/util/app-label.js.map +1 -0
  284. package/dist/src/util/errors.d.ts +9 -0
  285. package/dist/src/util/errors.d.ts.map +1 -0
  286. package/dist/src/util/errors.js +56 -0
  287. package/dist/src/util/errors.js.map +1 -0
  288. package/dist/src/util/path.d.ts +3 -0
  289. package/dist/src/util/path.d.ts.map +1 -0
  290. package/dist/src/util/path.js +6 -0
  291. package/dist/src/util/path.js.map +1 -0
  292. package/dist/src/util/regex.d.ts +4 -0
  293. package/dist/src/util/regex.d.ts.map +1 -0
  294. package/dist/src/util/regex.js +5 -0
  295. package/dist/src/util/regex.js.map +1 -0
  296. package/dist/src/util/time.d.ts +3 -0
  297. package/dist/src/util/time.d.ts.map +1 -0
  298. package/dist/src/util/time.js +7 -0
  299. package/dist/src/util/time.js.map +1 -0
  300. package/package.json +86 -0
@@ -0,0 +1,73 @@
1
+ import { createHmac, randomUUID, timingSafeEqual } from 'node:crypto';
2
+ export const SWEETLINK_DEFAULT_PORT = 4455;
3
+ export const SWEETLINK_WS_PATH = '/bridge';
4
+ export const SWEETLINK_SESSION_EXP_SECONDS = 60 * 5; // 5 minutes
5
+ export const SWEETLINK_CLI_EXP_SECONDS = 60 * 60; // 1 hour
6
+ export const SWEETLINK_HEARTBEAT_INTERVAL_MS = 15_000;
7
+ export const SWEETLINK_HEARTBEAT_TOLERANCE_MS = 45_000;
8
+ export function signSweetLinkToken({ secret, scope, subject, ttlSeconds, sessionId }) {
9
+ // We encode the payload ourselves (instead of relying on a JWT lib) so both daemon and browser
10
+ // can verify tokens without pulling in heavyweight dependencies.
11
+ if (!secret) {
12
+ throw new Error('SweetLink secret is not configured');
13
+ }
14
+ const issuedAt = Math.floor(Date.now() / 1000);
15
+ const payload = {
16
+ tokenId: randomUUID(),
17
+ scope,
18
+ sub: subject,
19
+ sessionId,
20
+ issuedAt,
21
+ expiresAt: issuedAt + ttlSeconds,
22
+ };
23
+ const encodedPayload = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
24
+ const signature = signEncodedPayload(secret, encodedPayload);
25
+ return `${encodedPayload}.${signature}`;
26
+ }
27
+ export function verifySweetLinkToken({ secret, token, expectedScope }) {
28
+ if (!secret) {
29
+ throw new Error('SweetLink secret is not configured');
30
+ }
31
+ const [encodedPayload, providedSignature] = token.split('.', 2);
32
+ if (!(encodedPayload && providedSignature)) {
33
+ throw new Error('Malformed SweetLink token');
34
+ }
35
+ const expectedSignature = signEncodedPayload(secret, encodedPayload);
36
+ if (!timingSafeCompare(Buffer.from(providedSignature, 'base64url'), Buffer.from(expectedSignature, 'base64url'))) {
37
+ throw new Error('Invalid SweetLink token signature');
38
+ }
39
+ const decoded = JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf8'));
40
+ if (!decoded || typeof decoded !== 'object') {
41
+ throw new Error('Invalid SweetLink token payload');
42
+ }
43
+ const now = Math.floor(Date.now() / 1000);
44
+ if (decoded.expiresAt < now) {
45
+ throw new Error('SweetLink token expired');
46
+ }
47
+ if (expectedScope && decoded.scope !== expectedScope) {
48
+ throw new Error('SweetLink token scope mismatch');
49
+ }
50
+ return decoded;
51
+ }
52
+ function signEncodedPayload(secret, encodedPayload) {
53
+ return createHmac('sha256', secret).update(encodedPayload).digest('base64url');
54
+ }
55
+ function timingSafeCompare(a, b) {
56
+ if (a.length !== b.length) {
57
+ return false;
58
+ }
59
+ try {
60
+ // timingSafeEqual throws if lengths mismatch; handle that here so callers only see false.
61
+ return timingSafeEqual(a, b);
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ export function createSweetLinkSessionId() {
68
+ return randomUUID();
69
+ }
70
+ export function createSweetLinkCommandId() {
71
+ return randomUUID();
72
+ }
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface ResolveSweetLinkSecretOptions {
2
+ readonly autoCreate?: boolean;
3
+ readonly secretPath?: string;
4
+ }
5
+ export interface SweetLinkSecretResolution {
6
+ readonly secret: string;
7
+ readonly source: 'env' | 'file' | 'generated';
8
+ readonly path?: string;
9
+ }
10
+ export declare function resolveSweetLinkSecret(options?: ResolveSweetLinkSecretOptions): Promise<SweetLinkSecretResolution>;
11
+ export declare function getDefaultSweetLinkSecretPath(): string;
12
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/shared/node.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAmCD,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,yBAAyB,CAAC,CAmCpC;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD"}
@@ -0,0 +1,67 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { constants as fsConstants } from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { debuglog } from 'node:util';
6
+ import { sweetLinkEnv } from './env.js';
7
+ const DEFAULT_SECRET_PATH = path.join(os.homedir(), '.sweetlink', 'secret.key');
8
+ const FS_PROMISES_MODULE = 'node:fs/promises';
9
+ let cachedFsPromises = null;
10
+ const debug = debuglog('sweetlink');
11
+ function ensureNodeRuntime() {
12
+ const globalScope = globalThis;
13
+ const nodeVersion = globalScope.process?.versions?.node;
14
+ if (nodeVersion) {
15
+ return;
16
+ }
17
+ if (globalScope.window !== undefined) {
18
+ throw new TypeError('SweetLink secret resolution requires a Node.js runtime; detected browser-like window without Node metadata.');
19
+ }
20
+ throw new TypeError('Node.js runtime metadata is unavailable; refusing to access SweetLink secrets.');
21
+ }
22
+ async function loadFsModule() {
23
+ if (cachedFsPromises) {
24
+ return cachedFsPromises;
25
+ }
26
+ ensureNodeRuntime();
27
+ cachedFsPromises = (await import(FS_PROMISES_MODULE));
28
+ return cachedFsPromises;
29
+ }
30
+ export async function resolveSweetLinkSecret(options = {}) {
31
+ const envSecret = sweetLinkEnv.secret;
32
+ if (envSecret && envSecret.length >= 32) {
33
+ return { secret: envSecret, source: 'env' };
34
+ }
35
+ const secretPath = options.secretPath ?? DEFAULT_SECRET_PATH;
36
+ try {
37
+ const fsModule = await loadFsModule();
38
+ const readSecretFile = async () => {
39
+ await fsModule.access(secretPath, fsConstants.R_OK);
40
+ return fsModule.readFile(secretPath, 'utf8');
41
+ };
42
+ const secretFileContents = await readSecretFile();
43
+ const fileSecret = secretFileContents.trim();
44
+ if (fileSecret.length >= 32) {
45
+ return { secret: fileSecret, source: 'file', path: secretPath };
46
+ }
47
+ }
48
+ catch (error) {
49
+ debug('Unable to read SweetLink secret from file; falling back to autoCreate logic.', {
50
+ path: secretPath,
51
+ error,
52
+ });
53
+ }
54
+ if (!options.autoCreate) {
55
+ throw new Error('SWEETLINK_SECRET is not configured; provide env var or run daemon with autoCreate enabled');
56
+ }
57
+ const generated = randomBytes(48).toString('base64url');
58
+ const directory = path.dirname(secretPath);
59
+ const { mkdir, writeFile } = await loadFsModule();
60
+ await mkdir(directory, { recursive: true });
61
+ await writeFile(secretPath, `${generated}\n`, { mode: 0o600 });
62
+ return { secret: generated, source: 'generated', path: secretPath };
63
+ }
64
+ export function getDefaultSweetLinkSecretPath() {
65
+ return DEFAULT_SECRET_PATH;
66
+ }
67
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/shared/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CliConfig } from './types.js';
2
+ export declare function resetCliTokenCache(): void;
3
+ export declare function fetchCliToken(config: CliConfig): Promise<string>;
4
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/token.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAwB,SAAS,EAAE,MAAM,YAAY,CAAC;AAclE,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDtE"}
@@ -0,0 +1,58 @@
1
+ import { SWEETLINK_CLI_EXP_SECONDS, signSweetLinkToken } from '../shared/src/index.js';
2
+ import { resolveSweetLinkSecret } from '../shared/src/node.js';
3
+ import { fetchJson } from './http.js';
4
+ import { describeAppForPrompt } from './util/app-label.js';
5
+ import { describeUnknown } from './util/errors.js';
6
+ import { TRAILING_SLASH_PATTERN } from './util/regex.js';
7
+ let cachedCliToken = null;
8
+ export function resetCliTokenCache() {
9
+ cachedCliToken = null;
10
+ }
11
+ export async function fetchCliToken(config) {
12
+ const now = Math.floor(Date.now() / 1000);
13
+ if (cachedCliToken && cachedCliToken.expiresAt - 30 > now) {
14
+ return cachedCliToken.token;
15
+ }
16
+ if (config.adminApiKey) {
17
+ try {
18
+ const response = await fetchJson(`${config.appBaseUrl.replace(TRAILING_SLASH_PATTERN, '')}/api/admin/sweetlink/cli-token`, {
19
+ method: 'POST',
20
+ headers: {
21
+ Authorization: `Bearer ${config.adminApiKey}`,
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ });
25
+ cachedCliToken = {
26
+ token: response.accessToken,
27
+ expiresAt: response.expiresAt,
28
+ source: 'api',
29
+ };
30
+ return response.accessToken;
31
+ }
32
+ catch (error) {
33
+ const detail = error instanceof Error ? error.message : String(error);
34
+ console.warn('[SweetLink CLI] Falling back to local secret after CLI token request failed:', detail);
35
+ }
36
+ }
37
+ try {
38
+ const secretResolution = await resolveSweetLinkSecret();
39
+ const token = signSweetLinkToken({
40
+ secret: secretResolution.secret,
41
+ scope: 'cli',
42
+ subject: 'local-cli',
43
+ ttlSeconds: SWEETLINK_CLI_EXP_SECONDS,
44
+ });
45
+ const expiresAt = Math.floor(Date.now() / 1000) + SWEETLINK_CLI_EXP_SECONDS;
46
+ cachedCliToken = { token, expiresAt, source: 'secret' };
47
+ return token;
48
+ }
49
+ catch (error) {
50
+ const detail = error instanceof Error ? error.message : describeUnknown(error);
51
+ const targetDescription = describeAppForPrompt(config.appLabel);
52
+ const hint = config.adminApiKey
53
+ ? `Check that your admin key is valid or ensure ${targetDescription} is running.`
54
+ : 'Provide --admin-key or start the SweetLink daemon once (pnpm sweetlink) to generate the shared secret.';
55
+ throw new Error(`Unable to resolve SweetLink CLI token. Reason: ${detail}. ${hint}`);
56
+ }
57
+ }
58
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface CliConfig {
2
+ readonly appLabel: string;
3
+ readonly appBaseUrl: string;
4
+ readonly daemonBaseUrl: string;
5
+ readonly adminApiKey: string | null;
6
+ readonly oauthScriptPath: string | null;
7
+ readonly servers: Record<string, ServerConfig>;
8
+ }
9
+ export type CachedCliTokenSource = 'secret' | 'api';
10
+ export interface ServerConfig {
11
+ readonly env: string;
12
+ readonly start: string[] | null;
13
+ readonly check: string[] | null;
14
+ readonly cwd: string | null;
15
+ readonly timeoutMs: number | null;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export declare const DEFAULT_APP_LABEL = "your application";
2
+ export declare function normalizeAppLabel(value: unknown): string | null;
3
+ export declare function formatAppLabel(label: string | null | undefined): string;
4
+ export declare function describeAppForPrompt(label: string | null | undefined): string;
5
+ //# sourceMappingURL=app-label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-label.d.ts","sourceRoot":"","sources":["../../../src/util/app-label.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAGpD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM/D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAEvE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAM7E"}
@@ -0,0 +1,21 @@
1
+ import { regex } from 'arkregex';
2
+ export const DEFAULT_APP_LABEL = 'your application';
3
+ const LEADING_ARTICLE_PATTERN = regex.as(String.raw `^(?:the|a|an|your)\b`, 'i');
4
+ export function normalizeAppLabel(value) {
5
+ if (typeof value !== 'string') {
6
+ return null;
7
+ }
8
+ const trimmed = value.trim();
9
+ return trimmed.length > 0 ? trimmed : null;
10
+ }
11
+ export function formatAppLabel(label) {
12
+ return normalizeAppLabel(label) ?? DEFAULT_APP_LABEL;
13
+ }
14
+ export function describeAppForPrompt(label) {
15
+ const formatted = formatAppLabel(label);
16
+ if (LEADING_ARTICLE_PATTERN.test(formatted)) {
17
+ return formatted;
18
+ }
19
+ return `the "${formatted}" application`;
20
+ }
21
+ //# sourceMappingURL=app-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-label.js","sourceRoot":"","sources":["../../../src/util/app-label.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACpD,MAAM,uBAAuB,GAAG,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAA,sBAAsB,EAAE,GAAG,CAAC,CAAC;AAEhF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgC;IAC7D,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAgC;IACnE,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,SAAS,eAAe,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** Extracts a readable message from unknown error-like values. */
2
+ export declare function extractEventMessage(event: unknown, prefix?: string): string;
3
+ /** Type guard for Node errno exceptions. */
4
+ export declare function isErrnoException(value: unknown): value is NodeJS.ErrnoException;
5
+ /** Formats unknown values for human-readable logging. */
6
+ export declare function describeUnknown(value: unknown, fallback?: string): string;
7
+ /** Emits a warning when debug logging is enabled. */
8
+ export declare function logDebugError(context: string, error: unknown): void;
9
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/util/errors.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB3E;AAED,4CAA4C;AAC5C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE/E;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAY,GAAG,MAAM,CAkB5E;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAMnE"}
@@ -0,0 +1,56 @@
1
+ import { sweetLinkDebug } from '../env.js';
2
+ /** Extracts a readable message from unknown error-like values. */
3
+ export function extractEventMessage(event, prefix) {
4
+ const parts = [];
5
+ if (prefix) {
6
+ parts.push(prefix);
7
+ }
8
+ if (typeof event === 'string') {
9
+ parts.push(event);
10
+ }
11
+ else if (event instanceof Error) {
12
+ parts.push(event.message || event.name || 'Unknown error');
13
+ }
14
+ else if (event && typeof event === 'object' && 'message' in event) {
15
+ const message = event.message;
16
+ parts.push(typeof message === 'string' ? message : JSON.stringify(message));
17
+ }
18
+ else {
19
+ parts.push(String(event));
20
+ }
21
+ return parts.join(': ');
22
+ }
23
+ /** Type guard for Node errno exceptions. */
24
+ export function isErrnoException(value) {
25
+ return typeof value === 'object' && value !== null && typeof value.code === 'string';
26
+ }
27
+ /** Formats unknown values for human-readable logging. */
28
+ export function describeUnknown(value, fallback = 'unknown') {
29
+ if (value === null || value === undefined) {
30
+ return fallback;
31
+ }
32
+ if (value instanceof Error) {
33
+ return value.message || value.name || fallback;
34
+ }
35
+ if (typeof value === 'string') {
36
+ return value;
37
+ }
38
+ if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {
39
+ return String(value);
40
+ }
41
+ try {
42
+ return JSON.stringify(value);
43
+ }
44
+ catch {
45
+ return fallback;
46
+ }
47
+ }
48
+ /** Emits a warning when debug logging is enabled. */
49
+ export function logDebugError(context, error) {
50
+ if (!sweetLinkDebug) {
51
+ return;
52
+ }
53
+ const message = error instanceof Error ? error.message : describeUnknown(error);
54
+ console.warn(`[SweetLink CLI] ${context}: ${message}`, error);
55
+ }
56
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/util/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,kEAAkE;AAClE,MAAM,UAAU,mBAAmB,CAAC,KAAc,EAAE,MAAe;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,eAAe,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QACpE,MAAM,OAAO,GAAI,KAA+B,CAAC,OAAO,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC/G,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,QAAQ,GAAG,SAAS;IAClE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACzF,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,KAAc;IAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAChF,OAAO,CAAC,IAAI,CAAC,mBAAmB,OAAO,KAAK,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Collapses the current home directory so paths read cleanly in logs. */
2
+ export declare function formatPathForDisplay(value: string): string;
3
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/util/path.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,6 @@
1
+ import os from 'node:os';
2
+ /** Collapses the current home directory so paths read cleanly in logs. */
3
+ export function formatPathForDisplay(value) {
4
+ return value.replace(os.homedir(), '~');
5
+ }
6
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/util/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const TRAILING_SLASH_PATTERN: import("arkregex").Regex<string, {}>;
2
+ export declare const OPTIONAL_TRAILING_SLASH_PATTERN: import("arkregex").Regex<string, {}>;
3
+ export declare const LEADING_SLASH_PATTERN: import("arkregex").Regex<string, {}>;
4
+ //# sourceMappingURL=regex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex.d.ts","sourceRoot":"","sources":["../../../src/util/regex.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,sCAAkB,CAAC;AACtD,eAAO,MAAM,+BAA+B,sCAAkB,CAAC;AAC/D,eAAO,MAAM,qBAAqB,sCAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { regex } from 'arkregex';
2
+ export const TRAILING_SLASH_PATTERN = regex.as('/+$');
3
+ export const OPTIONAL_TRAILING_SLASH_PATTERN = regex.as('/?$');
4
+ export const LEADING_SLASH_PATTERN = regex.as('^/+');
5
+ //# sourceMappingURL=regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex.js","sourceRoot":"","sources":["../../../src/util/regex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Delay helper returning a promise that resolves after the specified milliseconds. */
2
+ export declare function delay(ms: number): Promise<void>;
3
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../../src/util/time.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C"}
@@ -0,0 +1,7 @@
1
+ /** Delay helper returning a promise that resolves after the specified milliseconds. */
2
+ export function delay(ms) {
3
+ return new Promise((resolve) => {
4
+ setTimeout(resolve, ms);
5
+ });
6
+ }
7
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../../src/util/time.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "sweetlink",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "private": false,
6
+ "type": "module",
7
+ "description": "Controlled-browser automation CLI for SweetLink sessions.",
8
+ "homepage": "https://github.com/steipete/sweetlink",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/steipete/sweetlink.git",
12
+ "directory": "apps/sweetlink"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/steipete/sweetlink/issues"
16
+ },
17
+ "keywords": [
18
+ "sweetlink",
19
+ "automation",
20
+ "browser",
21
+ "devtools",
22
+ "cli"
23
+ ],
24
+ "bin": {
25
+ "sweetlink": "./dist/src/index.js"
26
+ },
27
+ "devDependencies": {
28
+ "@biomejs/biome": "^2.3.4",
29
+ "@types/node": "^22.19.0",
30
+ "@types/ws": "^8.18.1",
31
+ "tsx": "^4.20.6",
32
+ "typescript": "^5.9.3",
33
+ "ultracite": "^6.3.2",
34
+ "vitest": "^4.0.8"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE",
40
+ "CHANGELOG.md"
41
+ ],
42
+ "main": "./dist/src/index.js",
43
+ "module": "./dist/src/index.js",
44
+ "types": "./dist/src/index.d.ts",
45
+ "exports": {
46
+ ".": {
47
+ "types": "./dist/src/index.d.ts",
48
+ "import": "./dist/src/index.js",
49
+ "default": "./dist/src/index.js"
50
+ },
51
+ "./runtime/browser": {
52
+ "types": "./dist/src/runtime/browser/index.d.ts",
53
+ "import": "./dist/src/runtime/browser/index.js",
54
+ "default": "./dist/src/runtime/browser/index.js"
55
+ }
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "engines": {
61
+ "node": ">=22.0.0",
62
+ "pnpm": ">=10.16.0"
63
+ },
64
+ "dependencies": {
65
+ "arkregex": "^0.0.2",
66
+ "chrome-cookies-secure": "^3.0.0",
67
+ "commander": "^14.0.2",
68
+ "dotenv": "^17.2.3",
69
+ "es-toolkit": "^1.41.0",
70
+ "html2canvas": "^1.4.1",
71
+ "playwright-core": "^1.56.1",
72
+ "puppeteer": "^24.29.1",
73
+ "random-word-slugs": "^0.1.7",
74
+ "tldjs": "^2.3.2",
75
+ "undici": "^7.16.0",
76
+ "ws": "^8.18.3",
77
+ "zod": "^3.25.76"
78
+ },
79
+ "scripts": {
80
+ "dev": "tsx src/index.ts",
81
+ "build": "tsc --project tsconfig.build.json",
82
+ "test": "vitest run --config vitest.config.ts",
83
+ "lint": "biome lint ./src ./shared/src ./daemon/src ./tests",
84
+ "standalone:post-sync": "tsx scripts/post-sync.ts"
85
+ }
86
+ }