@hs-x/cli 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 (302) hide show
  1. package/README.md +1001 -0
  2. package/dist/account-store.d.ts +51 -0
  3. package/dist/account-store.d.ts.map +1 -0
  4. package/dist/account-store.js +138 -0
  5. package/dist/account-store.js.map +1 -0
  6. package/dist/bin/hs-x.d.ts +3 -0
  7. package/dist/bin/hs-x.d.ts.map +1 -0
  8. package/dist/bin/hs-x.js +47 -0
  9. package/dist/bin/hs-x.js.map +1 -0
  10. package/dist/cli/index.d.ts +3 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +595 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli-error.d.ts +36 -0
  15. package/dist/cli-error.d.ts.map +1 -0
  16. package/dist/cli-error.js +40 -0
  17. package/dist/cli-error.js.map +1 -0
  18. package/dist/cloudflare-auth.d.ts +25 -0
  19. package/dist/cloudflare-auth.d.ts.map +1 -0
  20. package/dist/cloudflare-auth.js +251 -0
  21. package/dist/cloudflare-auth.js.map +1 -0
  22. package/dist/cloudflare-kv.d.ts +23 -0
  23. package/dist/cloudflare-kv.d.ts.map +1 -0
  24. package/dist/cloudflare-kv.js +101 -0
  25. package/dist/cloudflare-kv.js.map +1 -0
  26. package/dist/cloudflare-oauth-store.d.ts +16 -0
  27. package/dist/cloudflare-oauth-store.d.ts.map +1 -0
  28. package/dist/cloudflare-oauth-store.js +80 -0
  29. package/dist/cloudflare-oauth-store.js.map +1 -0
  30. package/dist/cloudflare-oauth.d.ts +82 -0
  31. package/dist/cloudflare-oauth.d.ts.map +1 -0
  32. package/dist/cloudflare-oauth.js +336 -0
  33. package/dist/cloudflare-oauth.js.map +1 -0
  34. package/dist/cloudflare-pointer.d.ts +13 -0
  35. package/dist/cloudflare-pointer.d.ts.map +1 -0
  36. package/dist/cloudflare-pointer.js +46 -0
  37. package/dist/cloudflare-pointer.js.map +1 -0
  38. package/dist/command-history.d.ts +7 -0
  39. package/dist/command-history.d.ts.map +1 -0
  40. package/dist/command-history.js +34 -0
  41. package/dist/command-history.js.map +1 -0
  42. package/dist/commands/account.d.ts +7 -0
  43. package/dist/commands/account.d.ts.map +1 -0
  44. package/dist/commands/account.js +315 -0
  45. package/dist/commands/account.js.map +1 -0
  46. package/dist/commands/api.d.ts +36 -0
  47. package/dist/commands/api.d.ts.map +1 -0
  48. package/dist/commands/api.js +521 -0
  49. package/dist/commands/api.js.map +1 -0
  50. package/dist/commands/completion.d.ts +7 -0
  51. package/dist/commands/completion.d.ts.map +1 -0
  52. package/dist/commands/completion.js +121 -0
  53. package/dist/commands/completion.js.map +1 -0
  54. package/dist/commands/connect.d.ts +7 -0
  55. package/dist/commands/connect.d.ts.map +1 -0
  56. package/dist/commands/connect.js +1123 -0
  57. package/dist/commands/connect.js.map +1 -0
  58. package/dist/commands/control-plane-read.d.ts +22 -0
  59. package/dist/commands/control-plane-read.d.ts.map +1 -0
  60. package/dist/commands/control-plane-read.js +350 -0
  61. package/dist/commands/control-plane-read.js.map +1 -0
  62. package/dist/commands/deploy-promote.d.ts +14 -0
  63. package/dist/commands/deploy-promote.d.ts.map +1 -0
  64. package/dist/commands/deploy-promote.js +105 -0
  65. package/dist/commands/deploy-promote.js.map +1 -0
  66. package/dist/commands/deploy.d.ts +18 -0
  67. package/dist/commands/deploy.d.ts.map +1 -0
  68. package/dist/commands/deploy.js +2764 -0
  69. package/dist/commands/deploy.js.map +1 -0
  70. package/dist/commands/dev.d.ts +7 -0
  71. package/dist/commands/dev.d.ts.map +1 -0
  72. package/dist/commands/dev.js +913 -0
  73. package/dist/commands/dev.js.map +1 -0
  74. package/dist/commands/doctor.d.ts +8 -0
  75. package/dist/commands/doctor.d.ts.map +1 -0
  76. package/dist/commands/doctor.js +258 -0
  77. package/dist/commands/doctor.js.map +1 -0
  78. package/dist/commands/flags.d.ts +22 -0
  79. package/dist/commands/flags.d.ts.map +1 -0
  80. package/dist/commands/flags.js +185 -0
  81. package/dist/commands/flags.js.map +1 -0
  82. package/dist/commands/help-command.d.ts +13 -0
  83. package/dist/commands/help-command.d.ts.map +1 -0
  84. package/dist/commands/help-command.js +482 -0
  85. package/dist/commands/help-command.js.map +1 -0
  86. package/dist/commands/history.d.ts +6 -0
  87. package/dist/commands/history.d.ts.map +1 -0
  88. package/dist/commands/history.js +42 -0
  89. package/dist/commands/history.js.map +1 -0
  90. package/dist/commands/init.d.ts +8 -0
  91. package/dist/commands/init.d.ts.map +1 -0
  92. package/dist/commands/init.js +233 -0
  93. package/dist/commands/init.js.map +1 -0
  94. package/dist/commands/link.d.ts +26 -0
  95. package/dist/commands/link.d.ts.map +1 -0
  96. package/dist/commands/link.js +441 -0
  97. package/dist/commands/link.js.map +1 -0
  98. package/dist/commands/login.d.ts +8 -0
  99. package/dist/commands/login.d.ts.map +1 -0
  100. package/dist/commands/login.js +381 -0
  101. package/dist/commands/login.js.map +1 -0
  102. package/dist/commands/migrate.d.ts +8 -0
  103. package/dist/commands/migrate.d.ts.map +1 -0
  104. package/dist/commands/migrate.js +258 -0
  105. package/dist/commands/migrate.js.map +1 -0
  106. package/dist/commands/rollback.d.ts +21 -0
  107. package/dist/commands/rollback.d.ts.map +1 -0
  108. package/dist/commands/rollback.js +301 -0
  109. package/dist/commands/rollback.js.map +1 -0
  110. package/dist/commands/secrets.d.ts +7 -0
  111. package/dist/commands/secrets.d.ts.map +1 -0
  112. package/dist/commands/secrets.js +230 -0
  113. package/dist/commands/secrets.js.map +1 -0
  114. package/dist/commands/status.d.ts +7 -0
  115. package/dist/commands/status.d.ts.map +1 -0
  116. package/dist/commands/status.js +241 -0
  117. package/dist/commands/status.js.map +1 -0
  118. package/dist/commands/unlink.d.ts +21 -0
  119. package/dist/commands/unlink.d.ts.map +1 -0
  120. package/dist/commands/unlink.js +83 -0
  121. package/dist/commands/unlink.js.map +1 -0
  122. package/dist/commands/update.d.ts +11 -0
  123. package/dist/commands/update.d.ts.map +1 -0
  124. package/dist/commands/update.js +154 -0
  125. package/dist/commands/update.js.map +1 -0
  126. package/dist/commands/validate.d.ts +9 -0
  127. package/dist/commands/validate.d.ts.map +1 -0
  128. package/dist/commands/validate.js +39 -0
  129. package/dist/commands/validate.js.map +1 -0
  130. package/dist/config.d.ts +12 -0
  131. package/dist/config.d.ts.map +1 -0
  132. package/dist/config.js +64 -0
  133. package/dist/config.js.map +1 -0
  134. package/dist/constants.d.ts +4 -0
  135. package/dist/constants.d.ts.map +1 -0
  136. package/dist/constants.js +4 -0
  137. package/dist/constants.js.map +1 -0
  138. package/dist/control-plane-fetch.d.ts +34 -0
  139. package/dist/control-plane-fetch.d.ts.map +1 -0
  140. package/dist/control-plane-fetch.js +73 -0
  141. package/dist/control-plane-fetch.js.map +1 -0
  142. package/dist/control-plane-loader.d.ts +16 -0
  143. package/dist/control-plane-loader.d.ts.map +1 -0
  144. package/dist/control-plane-loader.js +24 -0
  145. package/dist/control-plane-loader.js.map +1 -0
  146. package/dist/dev/compat-shim.d.ts +40 -0
  147. package/dist/dev/compat-shim.d.ts.map +1 -0
  148. package/dist/dev/compat-shim.js +65 -0
  149. package/dist/dev/compat-shim.js.map +1 -0
  150. package/dist/dev/event-bus.d.ts +27 -0
  151. package/dist/dev/event-bus.d.ts.map +1 -0
  152. package/dist/dev/event-bus.js +32 -0
  153. package/dist/dev/event-bus.js.map +1 -0
  154. package/dist/dev/log-server.d.ts +52 -0
  155. package/dist/dev/log-server.d.ts.map +1 -0
  156. package/dist/dev/log-server.js +216 -0
  157. package/dist/dev/log-server.js.map +1 -0
  158. package/dist/dev/session-manager.d.ts +33 -0
  159. package/dist/dev/session-manager.d.ts.map +1 -0
  160. package/dist/dev/session-manager.js +132 -0
  161. package/dist/dev/session-manager.js.map +1 -0
  162. package/dist/dev/stream-renderer.d.ts +22 -0
  163. package/dist/dev/stream-renderer.d.ts.map +1 -0
  164. package/dist/dev/stream-renderer.js +65 -0
  165. package/dist/dev/stream-renderer.js.map +1 -0
  166. package/dist/dev/tunnel.d.ts +40 -0
  167. package/dist/dev/tunnel.d.ts.map +1 -0
  168. package/dist/dev/tunnel.js +139 -0
  169. package/dist/dev/tunnel.js.map +1 -0
  170. package/dist/effect-http.d.ts +10 -0
  171. package/dist/effect-http.d.ts.map +1 -0
  172. package/dist/effect-http.js +38 -0
  173. package/dist/effect-http.js.map +1 -0
  174. package/dist/errors-registry.d.ts +11 -0
  175. package/dist/errors-registry.d.ts.map +1 -0
  176. package/dist/errors-registry.js +554 -0
  177. package/dist/errors-registry.js.map +1 -0
  178. package/dist/errors.d.ts +58 -0
  179. package/dist/errors.d.ts.map +1 -0
  180. package/dist/errors.js +30 -0
  181. package/dist/errors.js.map +1 -0
  182. package/dist/help.d.ts +6 -0
  183. package/dist/help.d.ts.map +1 -0
  184. package/dist/help.js +100 -0
  185. package/dist/help.js.map +1 -0
  186. package/dist/history.d.ts +15 -0
  187. package/dist/history.d.ts.map +1 -0
  188. package/dist/history.js +69 -0
  189. package/dist/history.js.map +1 -0
  190. package/dist/hubspot-auth.d.ts +53 -0
  191. package/dist/hubspot-auth.d.ts.map +1 -0
  192. package/dist/hubspot-auth.js +301 -0
  193. package/dist/hubspot-auth.js.map +1 -0
  194. package/dist/hubspot-developer-client.d.ts +10 -0
  195. package/dist/hubspot-developer-client.d.ts.map +1 -0
  196. package/dist/hubspot-developer-client.js +212 -0
  197. package/dist/hubspot-developer-client.js.map +1 -0
  198. package/dist/index.d.ts +5 -0
  199. package/dist/index.d.ts.map +1 -0
  200. package/dist/index.js +4 -0
  201. package/dist/index.js.map +1 -0
  202. package/dist/init/templates.d.ts +18 -0
  203. package/dist/init/templates.d.ts.map +1 -0
  204. package/dist/init/templates.js +239 -0
  205. package/dist/init/templates.js.map +1 -0
  206. package/dist/load-env.d.ts +16 -0
  207. package/dist/load-env.d.ts.map +1 -0
  208. package/dist/load-env.js +69 -0
  209. package/dist/load-env.js.map +1 -0
  210. package/dist/machine-id.d.ts +3 -0
  211. package/dist/machine-id.d.ts.map +1 -0
  212. package/dist/machine-id.js +41 -0
  213. package/dist/machine-id.js.map +1 -0
  214. package/dist/paths.d.ts +4 -0
  215. package/dist/paths.d.ts.map +1 -0
  216. package/dist/paths.js +19 -0
  217. package/dist/paths.js.map +1 -0
  218. package/dist/prompt.d.ts +43 -0
  219. package/dist/prompt.d.ts.map +1 -0
  220. package/dist/prompt.js +379 -0
  221. package/dist/prompt.js.map +1 -0
  222. package/dist/reporter/human.d.ts +28 -0
  223. package/dist/reporter/human.d.ts.map +1 -0
  224. package/dist/reporter/human.js +126 -0
  225. package/dist/reporter/human.js.map +1 -0
  226. package/dist/reporter/index.d.ts +14 -0
  227. package/dist/reporter/index.d.ts.map +1 -0
  228. package/dist/reporter/index.js +37 -0
  229. package/dist/reporter/index.js.map +1 -0
  230. package/dist/reporter/json.d.ts +43 -0
  231. package/dist/reporter/json.d.ts.map +1 -0
  232. package/dist/reporter/json.js +146 -0
  233. package/dist/reporter/json.js.map +1 -0
  234. package/dist/reporter/style.d.ts +34 -0
  235. package/dist/reporter/style.d.ts.map +1 -0
  236. package/dist/reporter/style.js +97 -0
  237. package/dist/reporter/style.js.map +1 -0
  238. package/dist/reporter/types.d.ts +41 -0
  239. package/dist/reporter/types.d.ts.map +1 -0
  240. package/dist/reporter/types.js +2 -0
  241. package/dist/reporter/types.js.map +1 -0
  242. package/dist/result.d.ts +4 -0
  243. package/dist/result.d.ts.map +1 -0
  244. package/dist/result.js +2 -0
  245. package/dist/result.js.map +1 -0
  246. package/dist/services/account-store.d.ts +31 -0
  247. package/dist/services/account-store.d.ts.map +1 -0
  248. package/dist/services/account-store.js +135 -0
  249. package/dist/services/account-store.js.map +1 -0
  250. package/dist/services/app-paths.d.ts +25 -0
  251. package/dist/services/app-paths.d.ts.map +1 -0
  252. package/dist/services/app-paths.js +34 -0
  253. package/dist/services/app-paths.js.map +1 -0
  254. package/dist/services/cloudflare-auth.d.ts +83 -0
  255. package/dist/services/cloudflare-auth.d.ts.map +1 -0
  256. package/dist/services/cloudflare-auth.js +30 -0
  257. package/dist/services/cloudflare-auth.js.map +1 -0
  258. package/dist/services/cloudflare-kv.d.ts +45 -0
  259. package/dist/services/cloudflare-kv.d.ts.map +1 -0
  260. package/dist/services/cloudflare-kv.js +151 -0
  261. package/dist/services/cloudflare-kv.js.map +1 -0
  262. package/dist/services/command-history.d.ts +29 -0
  263. package/dist/services/command-history.d.ts.map +1 -0
  264. package/dist/services/command-history.js +62 -0
  265. package/dist/services/command-history.js.map +1 -0
  266. package/dist/services/control-plane.d.ts +32 -0
  267. package/dist/services/control-plane.d.ts.map +1 -0
  268. package/dist/services/control-plane.js +57 -0
  269. package/dist/services/control-plane.js.map +1 -0
  270. package/dist/services/env-loader.d.ts +18 -0
  271. package/dist/services/env-loader.d.ts.map +1 -0
  272. package/dist/services/env-loader.js +34 -0
  273. package/dist/services/env-loader.js.map +1 -0
  274. package/dist/services/http.d.ts +19 -0
  275. package/dist/services/http.d.ts.map +1 -0
  276. package/dist/services/http.js +9 -0
  277. package/dist/services/http.js.map +1 -0
  278. package/dist/services/live.d.ts +16 -0
  279. package/dist/services/live.d.ts.map +1 -0
  280. package/dist/services/live.js +26 -0
  281. package/dist/services/live.js.map +1 -0
  282. package/dist/services/machine-id.d.ts +18 -0
  283. package/dist/services/machine-id.d.ts.map +1 -0
  284. package/dist/services/machine-id.js +39 -0
  285. package/dist/services/machine-id.js.map +1 -0
  286. package/dist/services/reporter.d.ts +55 -0
  287. package/dist/services/reporter.d.ts.map +1 -0
  288. package/dist/services/reporter.js +49 -0
  289. package/dist/services/reporter.js.map +1 -0
  290. package/dist/state-store.d.ts +39 -0
  291. package/dist/state-store.d.ts.map +1 -0
  292. package/dist/state-store.js +89 -0
  293. package/dist/state-store.js.map +1 -0
  294. package/dist/telemetry.d.ts +13 -0
  295. package/dist/telemetry.d.ts.map +1 -0
  296. package/dist/telemetry.js +129 -0
  297. package/dist/telemetry.js.map +1 -0
  298. package/dist/tenant-state.d.ts +69 -0
  299. package/dist/tenant-state.d.ts.map +1 -0
  300. package/dist/tenant-state.js +161 -0
  301. package/dist/tenant-state.js.map +1 -0
  302. package/package.json +38 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * In-process event bus for `hs-x dev` unified output.
3
+ *
4
+ * Three lanes:
5
+ * - frontend: logs from card iframe (via @hs-x/sdk-ui `logger` → /__hsx/log)
6
+ * - backend: stdout/stderr from local handler process (e.g. wrangler dev) — lane wired later
7
+ * - request: inbound proxied request summaries from local dev-proxy receiver — lane wired later
8
+ *
9
+ * Subscribers (the reporter renderer) interleave events by arrival order.
10
+ */
11
+ export type DevLane = 'frontend' | 'backend' | 'request';
12
+ export type DevLevel = 'debug' | 'info' | 'warn' | 'error';
13
+ export interface DevEvent {
14
+ readonly lane: DevLane;
15
+ readonly level: DevLevel;
16
+ readonly ts: number;
17
+ readonly msg: string;
18
+ readonly source?: string;
19
+ readonly fields?: Record<string, unknown>;
20
+ }
21
+ export type DevEventListener = (event: DevEvent) => void;
22
+ export interface DevEventBus {
23
+ emit(event: DevEvent): void;
24
+ subscribe(listener: DevEventListener): () => void;
25
+ }
26
+ export declare function createDevEventBus(): DevEventBus;
27
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/dev/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AACzD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI,CAAC;CACnD;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAmB/C"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * In-process event bus for `hs-x dev` unified output.
3
+ *
4
+ * Three lanes:
5
+ * - frontend: logs from card iframe (via @hs-x/sdk-ui `logger` → /__hsx/log)
6
+ * - backend: stdout/stderr from local handler process (e.g. wrangler dev) — lane wired later
7
+ * - request: inbound proxied request summaries from local dev-proxy receiver — lane wired later
8
+ *
9
+ * Subscribers (the reporter renderer) interleave events by arrival order.
10
+ */
11
+ export function createDevEventBus() {
12
+ const listeners = new Set();
13
+ return {
14
+ emit(event) {
15
+ for (const listener of listeners) {
16
+ try {
17
+ listener(event);
18
+ }
19
+ catch {
20
+ // A subscriber throwing should not stop other subscribers from receiving the event.
21
+ }
22
+ }
23
+ },
24
+ subscribe(listener) {
25
+ listeners.add(listener);
26
+ return () => {
27
+ listeners.delete(listener);
28
+ };
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/dev/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqBH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,OAAO;QACL,IAAI,CAAC,KAAK;YACR,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC;oBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAClB,CAAC;gBAAC,MAAM,CAAC;oBACP,oFAAoF;gBACtF,CAAC;YACH,CAAC;QACH,CAAC;QACD,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * HS-X dev sidecar HTTP server.
3
+ *
4
+ * Separate from HubSpot's `ui-extensions-dev-server` — we own this. Hosts the
5
+ * frontend logger ingest endpoint, and will host other dev-only routes
6
+ * (request inspector, etc.) as they land.
7
+ *
8
+ * Routes:
9
+ * POST /__hsx/log — single log or batched array. CORS open for localhost callers.
10
+ * GET /__hsx/health
11
+ */
12
+ import type { DevEventBus } from './event-bus.js';
13
+ export interface DevLogServer {
14
+ readonly port: number;
15
+ readonly url: string;
16
+ close(): Promise<void>;
17
+ }
18
+ export interface DevLogServerOptions {
19
+ readonly bus: DevEventBus;
20
+ /** 0 picks a free port. Provide a stable value if the bundle hard-codes it. */
21
+ readonly port?: number;
22
+ readonly host?: string;
23
+ /** Cap on a single POST body to prevent runaway accumulators. */
24
+ readonly maxBodyBytes?: number;
25
+ }
26
+ interface IncomingLog {
27
+ readonly level?: string;
28
+ readonly msg?: string;
29
+ readonly ts?: number;
30
+ readonly source?: string;
31
+ readonly fields?: Record<string, unknown>;
32
+ }
33
+ /**
34
+ * Envelope POSTed by the deployed Cloudflare Worker per handled request.
35
+ * The shape mirrors what the runtime's logger collector emits in
36
+ * `packages/runtime/src/index.ts`.
37
+ */
38
+ export interface TelemetryEnvelope {
39
+ readonly request?: {
40
+ readonly method?: string;
41
+ readonly path?: string;
42
+ readonly url?: string;
43
+ readonly status?: number;
44
+ readonly durationMs?: number;
45
+ readonly capabilityId?: string;
46
+ readonly portalId?: string;
47
+ };
48
+ readonly logs?: ReadonlyArray<IncomingLog>;
49
+ }
50
+ export declare function startDevLogServer(opts: DevLogServerOptions): Promise<DevLogServer>;
51
+ export {};
52
+ //# sourceMappingURL=log-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-server.d.ts","sourceRoot":"","sources":["../../src/dev/log-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;CAC5C;AAKD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBxF"}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * HS-X dev sidecar HTTP server.
3
+ *
4
+ * Separate from HubSpot's `ui-extensions-dev-server` — we own this. Hosts the
5
+ * frontend logger ingest endpoint, and will host other dev-only routes
6
+ * (request inspector, etc.) as they land.
7
+ *
8
+ * Routes:
9
+ * POST /__hsx/log — single log or batched array. CORS open for localhost callers.
10
+ * GET /__hsx/health
11
+ */
12
+ import { createServer } from 'node:http';
13
+ const DEFAULT_MAX_BODY_BYTES = 256 * 1024;
14
+ const ALLOWED_LEVELS = new Set(['debug', 'info', 'warn', 'error']);
15
+ export async function startDevLogServer(opts) {
16
+ const { bus, host = '127.0.0.1', port = 0, maxBodyBytes = DEFAULT_MAX_BODY_BYTES } = opts;
17
+ const server = createServer((req, res) => {
18
+ handle(req, res, { bus, maxBodyBytes });
19
+ });
20
+ await new Promise((resolve, reject) => {
21
+ server.once('error', reject);
22
+ server.listen(port, host, () => {
23
+ server.off('error', reject);
24
+ resolve();
25
+ });
26
+ });
27
+ const address = server.address();
28
+ const boundPort = typeof address === 'object' && address ? address.port : port;
29
+ return {
30
+ port: boundPort,
31
+ url: `http://${host}:${boundPort}`,
32
+ close: () => closeServer(server),
33
+ };
34
+ }
35
+ function handle(req, res, ctx) {
36
+ applyCors(req, res);
37
+ if (req.method === 'OPTIONS') {
38
+ res.statusCode = 204;
39
+ res.end();
40
+ return;
41
+ }
42
+ if (req.method === 'GET' && req.url === '/__hsx/health') {
43
+ res.statusCode = 200;
44
+ res.setHeader('Content-Type', 'application/json');
45
+ res.end('{"ok":true}');
46
+ return;
47
+ }
48
+ if (req.method === 'POST' && req.url === '/__hsx/log') {
49
+ void readJsonBody(req, ctx.maxBodyBytes).then((result) => {
50
+ if (result.kind === 'error') {
51
+ const status = result.reason === 'BODY_TOO_LARGE' ? 413 : 400;
52
+ res.writeHead(status, { 'Content-Type': 'application/json' });
53
+ res.end(JSON.stringify({ error: result.reason }));
54
+ return;
55
+ }
56
+ const logs = normalizeBody(result.body);
57
+ for (const log of logs) {
58
+ ingestOne(ctx.bus, log);
59
+ }
60
+ res.statusCode = 204;
61
+ res.end();
62
+ });
63
+ return;
64
+ }
65
+ if (req.method === 'POST' && req.url === '/__hsx/event') {
66
+ // Telemetry ingest from the deployed Cloudflare Worker. The Worker POSTs
67
+ // `{request:{...}, logs:[...]}` after each handled request. Today this is
68
+ // unauthenticated; the threat model is "anyone who guesses the random
69
+ // trycloudflare URL within the dev session's TTL can inject log lines into
70
+ // the developer's terminal." Mitigated by: 127.0.0.1 bind for the
71
+ // origin server, fresh tunnel URL per session, short TTL, capped body
72
+ // size. Not safe against an attacker who can observe the tunnel URL.
73
+ //
74
+ // To harden: distribute a per-session HMAC key. The runtime's existing
75
+ // `signRuntimeDevProxyRequest` primitive is the right signing scheme, but
76
+ // the key-distribution channel is unresolved — schema docs in
77
+ // packages/types/src/schemas/index.ts explicitly exclude signing secrets
78
+ // from `DevOverrideRegistration` (the public read model). Options:
79
+ // (a) extend `DevOverrideRegisterRequest` with `telemetryHmacKey` and
80
+ // have the control plane stash it on the runtime-internal record
81
+ // only (never echo on the public registration shape);
82
+ // (b) encode the key in the `telemetryUrl` (fragment or query param)
83
+ // so it travels with the existing field and never needs to be
84
+ // stored on the control-plane side;
85
+ // (c) tie telemetry signing to the existing runtime `signingSecret`
86
+ // (currently only used inbound, and itself not yet wired through
87
+ // deployment config — would need that plumbing first).
88
+ // Pick one before shipping public dev sessions or running on shared
89
+ // tunnels.
90
+ void readJsonBody(req, ctx.maxBodyBytes).then((result) => {
91
+ if (result.kind === 'error') {
92
+ const status = result.reason === 'BODY_TOO_LARGE' ? 413 : 400;
93
+ res.writeHead(status, { 'Content-Type': 'application/json' });
94
+ res.end(JSON.stringify({ error: result.reason }));
95
+ return;
96
+ }
97
+ const envelope = result.body;
98
+ if (envelope && typeof envelope === 'object') {
99
+ ingestEnvelope(ctx.bus, envelope);
100
+ }
101
+ res.statusCode = 204;
102
+ res.end();
103
+ });
104
+ return;
105
+ }
106
+ res.statusCode = 404;
107
+ res.end();
108
+ }
109
+ function applyCors(req, res) {
110
+ // Dev-only sidecar. HubSpot iframe origin varies per portal, so reflect.
111
+ const origin = req.headers.origin ?? '*';
112
+ res.setHeader('Access-Control-Allow-Origin', origin);
113
+ res.setHeader('Vary', 'Origin');
114
+ res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
115
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
116
+ }
117
+ async function readJsonBody(req, maxBytes) {
118
+ // Drain the body fully before deciding — throwing mid-iteration on some
119
+ // runtimes (Bun's node:http compat) interferes with writing the response.
120
+ let received = 0;
121
+ let overflowed = false;
122
+ const chunks = [];
123
+ for await (const chunk of req) {
124
+ const buf = chunk;
125
+ received += buf.length;
126
+ if (received > maxBytes) {
127
+ overflowed = true;
128
+ continue;
129
+ }
130
+ chunks.push(buf);
131
+ }
132
+ if (overflowed)
133
+ return { kind: 'error', reason: 'BODY_TOO_LARGE' };
134
+ if (chunks.length === 0)
135
+ return { kind: 'ok', body: null };
136
+ const text = Buffer.concat(chunks).toString('utf8');
137
+ try {
138
+ return { kind: 'ok', body: JSON.parse(text) };
139
+ }
140
+ catch {
141
+ return { kind: 'error', reason: 'INVALID_JSON' };
142
+ }
143
+ }
144
+ function normalizeBody(body) {
145
+ if (Array.isArray(body))
146
+ return body;
147
+ if (body && typeof body === 'object')
148
+ return [body];
149
+ return [];
150
+ }
151
+ function ingestEnvelope(bus, envelope) {
152
+ const req = envelope.request;
153
+ if (req) {
154
+ const path = req.path ?? (req.url ? safePath(req.url) : '/');
155
+ const method = req.method ?? 'GET';
156
+ const status = typeof req.status === 'number' ? req.status : 0;
157
+ const duration = typeof req.durationMs === 'number' ? `${req.durationMs}ms` : '';
158
+ const summary = `${method.padEnd(4, ' ')} ${path} ${String(status).padStart(3, ' ')}${duration ? ` ${duration}` : ''}`;
159
+ const level = status >= 500 ? 'error' : status >= 400 ? 'warn' : 'info';
160
+ bus.emit({
161
+ lane: 'request',
162
+ level,
163
+ ts: Date.now(),
164
+ msg: summary,
165
+ ...(req.capabilityId ? { source: req.capabilityId } : {}),
166
+ });
167
+ }
168
+ if (envelope.logs) {
169
+ for (const log of envelope.logs) {
170
+ const event = {
171
+ lane: 'backend',
172
+ level: ALLOWED_LEVELS.has(log.level) ? log.level : 'info',
173
+ ts: typeof log.ts === 'number' ? log.ts : Date.now(),
174
+ msg: typeof log.msg === 'string' ? log.msg : '',
175
+ ...(typeof log.source === 'string' ? { source: log.source } : {}),
176
+ ...(log.fields ? { fields: log.fields } : {}),
177
+ };
178
+ if (event.msg)
179
+ bus.emit(event);
180
+ }
181
+ }
182
+ }
183
+ function safePath(url) {
184
+ try {
185
+ return new URL(url).pathname;
186
+ }
187
+ catch {
188
+ return url;
189
+ }
190
+ }
191
+ function ingestOne(bus, log) {
192
+ const level = ALLOWED_LEVELS.has(log.level) ? log.level : 'info';
193
+ const msg = typeof log.msg === 'string' ? log.msg : '';
194
+ if (!msg)
195
+ return;
196
+ const event = {
197
+ lane: 'frontend',
198
+ level,
199
+ ts: typeof log.ts === 'number' ? log.ts : Date.now(),
200
+ msg,
201
+ ...(typeof log.source === 'string' ? { source: log.source } : {}),
202
+ ...(log.fields ? { fields: log.fields } : {}),
203
+ };
204
+ bus.emit(event);
205
+ }
206
+ function closeServer(server) {
207
+ return new Promise((resolve, reject) => {
208
+ server.close((err) => {
209
+ if (err)
210
+ reject(err);
211
+ else
212
+ resolve();
213
+ });
214
+ });
215
+ }
216
+ //# sourceMappingURL=log-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-server.js","sourceRoot":"","sources":["../../src/dev/log-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAA0D,YAAY,EAAE,MAAM,WAAW,CAAC;AA4CjG,MAAM,sBAAsB,GAAG,GAAG,GAAG,IAAI,CAAC;AAC1C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAyB;IAC/D,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,WAAW,EAAE,IAAI,GAAG,CAAC,EAAE,YAAY,GAAG,sBAAsB,EAAE,GAAG,IAAI,CAAC;IAE1F,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAE/E,OAAO;QACL,IAAI,EAAE,SAAS;QACf,GAAG,EAAE,UAAU,IAAI,IAAI,SAAS,EAAE;QAClC,KAAK,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CACb,GAAoB,EACpB,GAAmB,EACnB,GAA+C;IAE/C,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEpB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,eAAe,EAAE,CAAC;QACxD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACvB,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;QACtD,KAAK,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACvD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC9D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC1B,CAAC;YACD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC;QACxD,yEAAyE;QACzE,0EAA0E;QAC1E,sEAAsE;QACtE,2EAA2E;QAC3E,kEAAkE;QAClE,sEAAsE;QACtE,qEAAqE;QACrE,EAAE;QACF,uEAAuE;QACvE,0EAA0E;QAC1E,8DAA8D;QAC9D,yEAAyE;QACzE,mEAAmE;QACnE,wEAAwE;QACxE,uEAAuE;QACvE,4DAA4D;QAC5D,uEAAuE;QACvE,oEAAoE;QACpE,0CAA0C;QAC1C,sEAAsE;QACtE,uEAAuE;QACvE,6DAA6D;QAC7D,oEAAoE;QACpE,WAAW;QACX,KAAK,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACvD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC9D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAgC,CAAC;YACzD,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC7C,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpC,CAAC;YACD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;IACrB,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,SAAS,CAAC,GAAoB,EAAE,GAAmB;IAC1D,yEAAyE;IACzE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;IACzC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;IACrD,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;IACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;AAChE,CAAC;AAMD,KAAK,UAAU,YAAY,CAAC,GAAoB,EAAE,QAAgB;IAChE,wEAAwE;IACxE,0EAA0E;IAC1E,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAe,CAAC;QAC5B,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC;QACvB,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;YACxB,UAAU,GAAG,IAAI,CAAC;YAClB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACnD,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAqB,CAAC;IACtD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,IAAmB,CAAC,CAAC;IACnE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,cAAc,CAAC,GAAgB,EAAE,QAA2B;IACnE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC;IAC7B,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,MAAM,QAAQ,GACZ,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACzH,MAAM,KAAK,GAAa,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAClF,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,SAAS;YACf,KAAK;YACL,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,GAAG,EAAE,OAAO;YACZ,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChC,MAAM,KAAK,GAAsC;gBAC/C,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,KAAiB,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,KAAkB,CAAC,CAAC,CAAC,MAAM;gBACnF,EAAE,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;gBACpD,GAAG,EAAE,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC/C,GAAG,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C,CAAC;YACF,IAAI,KAAK,CAAC,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAgB,EAAE,GAAgB;IACnD,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,KAAiB,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,KAAkB,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3F,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,MAAM,KAAK,GAAsC;QAC/C,IAAI,EAAE,UAAU;QAChB,KAAK;QACL,EAAE,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;QACpD,GAAG;QACH,GAAG,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACnB,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAChB,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Drives the HubSpot dev-session handshake end-to-end:
3
+ * 1. Translate project → IR
4
+ * 2. Start PortManagerServer
5
+ * 3. setup + start ui-extensions-dev-server
6
+ * 4. Register dev session
7
+ * 5. Heartbeat every 30s
8
+ * 6. cleanup() tears everything down (call on SIGINT / Esc)
9
+ *
10
+ * See docs/phase-1.5/spike-ui-extension-dev-session.md.
11
+ */
12
+ export interface DevSessionStart {
13
+ readonly accountId: number;
14
+ readonly projectDir: string;
15
+ /** Optional whitelist — only these node UIDs are registered. */
16
+ readonly selectedNodeUids?: readonly string[];
17
+ /** Called every successful heartbeat (used by the request-log renderer). */
18
+ readonly onHeartbeat?: (info: {
19
+ at: Date;
20
+ sessionId: number;
21
+ }) => void;
22
+ }
23
+ export interface DevSessionHandle {
24
+ readonly sessionId: number;
25
+ readonly ports: ReadonlyArray<{
26
+ serverId: string;
27
+ port: number;
28
+ }>;
29
+ readonly nodeUids: readonly string[];
30
+ cleanup(): Promise<void>;
31
+ }
32
+ export declare function startDevSession(input: DevSessionStart): Promise<DevSessionHandle>;
33
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/dev/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACxE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAID,wBAAsB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmHvF"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Drives the HubSpot dev-session handshake end-to-end:
3
+ * 1. Translate project → IR
4
+ * 2. Start PortManagerServer
5
+ * 3. setup + start ui-extensions-dev-server
6
+ * 4. Register dev session
7
+ * 5. Heartbeat every 30s
8
+ * 6. cleanup() tears everything down (call on SIGINT / Esc)
9
+ *
10
+ * See docs/phase-1.5/spike-ui-extension-dev-session.md.
11
+ */
12
+ import { readFile } from 'node:fs/promises';
13
+ import { join } from 'node:path';
14
+ import { createDevSessionsClient } from '@hs-x/hubspot-cli';
15
+ import { loadDevStack } from './compat-shim.js';
16
+ const HEARTBEAT_INTERVAL_MS = 30_000;
17
+ export async function startDevSession(input) {
18
+ const stack = await loadDevStack();
19
+ if (!stack.getAccountConfig(input.accountId)) {
20
+ throw new DevSessionStartError('HSX_E_DEV_SESSION_NO_HUBSPOT_ACCOUNT', `HubSpot CLI config has no account ${input.accountId}. Run \`hs accounts auth\` or \`hs-x connect\`.`);
21
+ }
22
+ const projectConfigRaw = await readFile(join(input.projectDir, 'hsproject.json'), 'utf8');
23
+ const projectConfig = JSON.parse(projectConfigRaw);
24
+ const ir = await stack.translateForLocalDev({
25
+ projectSourceDir: join(input.projectDir, projectConfig.srcDir),
26
+ platformVersion: projectConfig.platformVersion,
27
+ accountId: input.accountId,
28
+ }, {});
29
+ let nodesByUid = ir.intermediateNodesIndexedByUid;
30
+ if (input.selectedNodeUids && input.selectedNodeUids.length > 0) {
31
+ const allowed = new Set(input.selectedNodeUids);
32
+ nodesByUid = Object.fromEntries(Object.entries(nodesByUid).filter(([uid]) => allowed.has(uid)));
33
+ if (Object.keys(nodesByUid).length === 0) {
34
+ throw new DevSessionStartError('HSX_E_DEV_SESSION_NO_NODES', 'None of the selected nodes were found in the project IR.');
35
+ }
36
+ }
37
+ await stack.startPortManagerServer();
38
+ try {
39
+ await stack.uie.setup({
40
+ components: nodesByUid,
41
+ profileData: ir.profileData,
42
+ logger: stack.logger,
43
+ urls: {
44
+ api: stack.getHubSpotApiOrigin(),
45
+ web: stack.getHubSpotWebsiteOrigin(),
46
+ },
47
+ });
48
+ await stack.uie.start({
49
+ accountId: input.accountId,
50
+ projectConfig: projectConfig,
51
+ requestPorts: stack.requestPorts,
52
+ });
53
+ const activeServers = await stack.getActiveServers();
54
+ const ports = Object.entries(activeServers).map(([serverId, port]) => ({
55
+ serverId,
56
+ port,
57
+ }));
58
+ const client = await createDevSessionsClient({
59
+ accountId: input.accountId,
60
+ });
61
+ const { sessionId } = await client.register({ ports });
62
+ const heartbeat = setInterval(async () => {
63
+ try {
64
+ await client.heartbeat({ sessionId });
65
+ input.onHeartbeat?.({ at: new Date(), sessionId });
66
+ }
67
+ catch {
68
+ // Best-effort. The next heartbeat will retry; if the session is dead the
69
+ // user will notice and can restart.
70
+ }
71
+ }, HEARTBEAT_INTERVAL_MS);
72
+ let cleanedUp = false;
73
+ const cleanup = async () => {
74
+ if (cleanedUp)
75
+ return;
76
+ cleanedUp = true;
77
+ clearInterval(heartbeat);
78
+ const errors = [];
79
+ try {
80
+ await client.delete({ sessionId });
81
+ }
82
+ catch (e) {
83
+ errors.push(`delete: ${e.message}`);
84
+ }
85
+ try {
86
+ await stack.uie.cleanup();
87
+ }
88
+ catch (e) {
89
+ errors.push(`uie cleanup: ${e.message}`);
90
+ }
91
+ try {
92
+ await stack.stopPortManagerServer();
93
+ }
94
+ catch (e) {
95
+ errors.push(`port manager: ${e.message}`);
96
+ }
97
+ if (errors.length > 0) {
98
+ throw new DevSessionCleanupError(errors.join('; '));
99
+ }
100
+ };
101
+ return {
102
+ sessionId,
103
+ ports,
104
+ nodeUids: Object.keys(nodesByUid),
105
+ cleanup,
106
+ };
107
+ }
108
+ catch (error) {
109
+ try {
110
+ await stack.stopPortManagerServer();
111
+ }
112
+ catch {
113
+ // best-effort
114
+ }
115
+ throw error;
116
+ }
117
+ }
118
+ class DevSessionStartError extends Error {
119
+ code;
120
+ constructor(code, message) {
121
+ super(message);
122
+ this.name = 'DevSessionStartError';
123
+ this.code = code;
124
+ }
125
+ }
126
+ class DevSessionCleanupError extends Error {
127
+ constructor(message) {
128
+ super(message);
129
+ this.name = 'DevSessionCleanupError';
130
+ }
131
+ }
132
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/dev/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Renders dev event-bus events to stderr as interleaved, timestamped lanes.
3
+ *
4
+ * 14:03:21.480 frontend info logger.info hello from the card
5
+ * 14:03:21.418 backend info fetched contact 12345
6
+ * 14:03:21.412 request ok POST /actions/sync-contact 200 142ms
7
+ *
8
+ * The lane prefix tells the developer which surface emitted the line; the
9
+ * level color matches conventions used elsewhere in the reporter.
10
+ */
11
+ import type { DevEventBus } from './event-bus.js';
12
+ export interface DevStreamRendererOptions {
13
+ readonly bus: DevEventBus;
14
+ readonly stderr?: NodeJS.WritableStream;
15
+ readonly env?: NodeJS.ProcessEnv;
16
+ readonly isTTY?: boolean;
17
+ }
18
+ export interface DevStreamRenderer {
19
+ stop(): void;
20
+ }
21
+ export declare function startDevStreamRenderer(opts: DevStreamRendererOptions): DevStreamRenderer;
22
+ //# sourceMappingURL=stream-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-renderer.d.ts","sourceRoot":"","sources":["../../src/dev/stream-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAY,WAAW,EAAY,MAAM,gBAAgB,CAAC;AAEtE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,IAAI,IAAI,CAAC;CACd;AAQD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CAaxF"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Renders dev event-bus events to stderr as interleaved, timestamped lanes.
3
+ *
4
+ * 14:03:21.480 frontend info logger.info hello from the card
5
+ * 14:03:21.418 backend info fetched contact 12345
6
+ * 14:03:21.412 request ok POST /actions/sync-contact 200 142ms
7
+ *
8
+ * The lane prefix tells the developer which surface emitted the line; the
9
+ * level color matches conventions used elsewhere in the reporter.
10
+ */
11
+ import { detectColor, detectUnicode, makeStyle } from '../reporter/style.js';
12
+ const LANE_LABEL = {
13
+ frontend: 'frontend',
14
+ backend: 'backend ',
15
+ request: 'request ',
16
+ };
17
+ export function startDevStreamRenderer(opts) {
18
+ const stderr = opts.stderr ?? process.stderr;
19
+ const env = opts.env ?? process.env;
20
+ const isTTY = opts.isTTY ?? Boolean(stderr.isTTY);
21
+ const style = makeStyle(detectColor(env, isTTY), detectUnicode(env));
22
+ const unsubscribe = opts.bus.subscribe((event) => {
23
+ stderr.write(`${formatLine(event, style)}\n`);
24
+ });
25
+ return {
26
+ stop: unsubscribe,
27
+ };
28
+ }
29
+ function formatLine(event, style) {
30
+ const ts = style.dim(formatTimestamp(event.ts));
31
+ const lane = paintLane(event.lane, style);
32
+ const level = paintLevel(event.level, style);
33
+ const source = event.source ? `${style.dim(event.source)} ` : '';
34
+ return ` ${ts} ${lane} ${level} ${source}${event.msg}`;
35
+ }
36
+ function formatTimestamp(ts) {
37
+ const d = new Date(ts);
38
+ const hh = String(d.getHours()).padStart(2, '0');
39
+ const mm = String(d.getMinutes()).padStart(2, '0');
40
+ const ss = String(d.getSeconds()).padStart(2, '0');
41
+ const ms = String(d.getMilliseconds()).padStart(3, '0');
42
+ return `${hh}:${mm}:${ss}.${ms}`;
43
+ }
44
+ function paintLane(lane, style) {
45
+ const label = LANE_LABEL[lane];
46
+ if (lane === 'frontend')
47
+ return style.orange(label);
48
+ if (lane === 'backend')
49
+ return style.green(label);
50
+ return style.dim(label);
51
+ }
52
+ function paintLevel(level, style) {
53
+ const padded = level.padEnd(5, ' ');
54
+ switch (level) {
55
+ case 'error':
56
+ return style.red(padded);
57
+ case 'warn':
58
+ return style.yellow(padded);
59
+ case 'debug':
60
+ return style.dim(padded);
61
+ default:
62
+ return style.dim(padded);
63
+ }
64
+ }
65
+ //# sourceMappingURL=stream-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-renderer.js","sourceRoot":"","sources":["../../src/dev/stream-renderer.ts"],"names":[],"mappings":"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"}