@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.
- package/README.md +1001 -0
- package/dist/account-store.d.ts +51 -0
- package/dist/account-store.d.ts.map +1 -0
- package/dist/account-store.js +138 -0
- package/dist/account-store.js.map +1 -0
- package/dist/bin/hs-x.d.ts +3 -0
- package/dist/bin/hs-x.d.ts.map +1 -0
- package/dist/bin/hs-x.js +47 -0
- package/dist/bin/hs-x.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +595 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli-error.d.ts +36 -0
- package/dist/cli-error.d.ts.map +1 -0
- package/dist/cli-error.js +40 -0
- package/dist/cli-error.js.map +1 -0
- package/dist/cloudflare-auth.d.ts +25 -0
- package/dist/cloudflare-auth.d.ts.map +1 -0
- package/dist/cloudflare-auth.js +251 -0
- package/dist/cloudflare-auth.js.map +1 -0
- package/dist/cloudflare-kv.d.ts +23 -0
- package/dist/cloudflare-kv.d.ts.map +1 -0
- package/dist/cloudflare-kv.js +101 -0
- package/dist/cloudflare-kv.js.map +1 -0
- package/dist/cloudflare-oauth-store.d.ts +16 -0
- package/dist/cloudflare-oauth-store.d.ts.map +1 -0
- package/dist/cloudflare-oauth-store.js +80 -0
- package/dist/cloudflare-oauth-store.js.map +1 -0
- package/dist/cloudflare-oauth.d.ts +82 -0
- package/dist/cloudflare-oauth.d.ts.map +1 -0
- package/dist/cloudflare-oauth.js +336 -0
- package/dist/cloudflare-oauth.js.map +1 -0
- package/dist/cloudflare-pointer.d.ts +13 -0
- package/dist/cloudflare-pointer.d.ts.map +1 -0
- package/dist/cloudflare-pointer.js +46 -0
- package/dist/cloudflare-pointer.js.map +1 -0
- package/dist/command-history.d.ts +7 -0
- package/dist/command-history.d.ts.map +1 -0
- package/dist/command-history.js +34 -0
- package/dist/command-history.js.map +1 -0
- package/dist/commands/account.d.ts +7 -0
- package/dist/commands/account.d.ts.map +1 -0
- package/dist/commands/account.js +315 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/api.d.ts +36 -0
- package/dist/commands/api.d.ts.map +1 -0
- package/dist/commands/api.js +521 -0
- package/dist/commands/api.js.map +1 -0
- package/dist/commands/completion.d.ts +7 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +121 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/connect.d.ts +7 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +1123 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/control-plane-read.d.ts +22 -0
- package/dist/commands/control-plane-read.d.ts.map +1 -0
- package/dist/commands/control-plane-read.js +350 -0
- package/dist/commands/control-plane-read.js.map +1 -0
- package/dist/commands/deploy-promote.d.ts +14 -0
- package/dist/commands/deploy-promote.d.ts.map +1 -0
- package/dist/commands/deploy-promote.js +105 -0
- package/dist/commands/deploy-promote.js.map +1 -0
- package/dist/commands/deploy.d.ts +18 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +2764 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +913 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +258 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/flags.d.ts +22 -0
- package/dist/commands/flags.d.ts.map +1 -0
- package/dist/commands/flags.js +185 -0
- package/dist/commands/flags.js.map +1 -0
- package/dist/commands/help-command.d.ts +13 -0
- package/dist/commands/help-command.d.ts.map +1 -0
- package/dist/commands/help-command.js +482 -0
- package/dist/commands/help-command.js.map +1 -0
- package/dist/commands/history.d.ts +6 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +42 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +233 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link.d.ts +26 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +441 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/login.d.ts +8 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +381 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/migrate.d.ts +8 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +258 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/rollback.d.ts +21 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/rollback.js +301 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/secrets.d.ts +7 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +230 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +241 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/unlink.d.ts +21 -0
- package/dist/commands/unlink.d.ts.map +1 -0
- package/dist/commands/unlink.js +83 -0
- package/dist/commands/unlink.js.map +1 -0
- package/dist/commands/update.d.ts +11 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +154 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +9 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +39 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -0
- package/dist/control-plane-fetch.d.ts +34 -0
- package/dist/control-plane-fetch.d.ts.map +1 -0
- package/dist/control-plane-fetch.js +73 -0
- package/dist/control-plane-fetch.js.map +1 -0
- package/dist/control-plane-loader.d.ts +16 -0
- package/dist/control-plane-loader.d.ts.map +1 -0
- package/dist/control-plane-loader.js +24 -0
- package/dist/control-plane-loader.js.map +1 -0
- package/dist/dev/compat-shim.d.ts +40 -0
- package/dist/dev/compat-shim.d.ts.map +1 -0
- package/dist/dev/compat-shim.js +65 -0
- package/dist/dev/compat-shim.js.map +1 -0
- package/dist/dev/event-bus.d.ts +27 -0
- package/dist/dev/event-bus.d.ts.map +1 -0
- package/dist/dev/event-bus.js +32 -0
- package/dist/dev/event-bus.js.map +1 -0
- package/dist/dev/log-server.d.ts +52 -0
- package/dist/dev/log-server.d.ts.map +1 -0
- package/dist/dev/log-server.js +216 -0
- package/dist/dev/log-server.js.map +1 -0
- package/dist/dev/session-manager.d.ts +33 -0
- package/dist/dev/session-manager.d.ts.map +1 -0
- package/dist/dev/session-manager.js +132 -0
- package/dist/dev/session-manager.js.map +1 -0
- package/dist/dev/stream-renderer.d.ts +22 -0
- package/dist/dev/stream-renderer.d.ts.map +1 -0
- package/dist/dev/stream-renderer.js +65 -0
- package/dist/dev/stream-renderer.js.map +1 -0
- package/dist/dev/tunnel.d.ts +40 -0
- package/dist/dev/tunnel.d.ts.map +1 -0
- package/dist/dev/tunnel.js +139 -0
- package/dist/dev/tunnel.js.map +1 -0
- package/dist/effect-http.d.ts +10 -0
- package/dist/effect-http.d.ts.map +1 -0
- package/dist/effect-http.js +38 -0
- package/dist/effect-http.js.map +1 -0
- package/dist/errors-registry.d.ts +11 -0
- package/dist/errors-registry.d.ts.map +1 -0
- package/dist/errors-registry.js +554 -0
- package/dist/errors-registry.js.map +1 -0
- package/dist/errors.d.ts +58 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/help.d.ts +6 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +100 -0
- package/dist/help.js.map +1 -0
- package/dist/history.d.ts +15 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +69 -0
- package/dist/history.js.map +1 -0
- package/dist/hubspot-auth.d.ts +53 -0
- package/dist/hubspot-auth.d.ts.map +1 -0
- package/dist/hubspot-auth.js +301 -0
- package/dist/hubspot-auth.js.map +1 -0
- package/dist/hubspot-developer-client.d.ts +10 -0
- package/dist/hubspot-developer-client.d.ts.map +1 -0
- package/dist/hubspot-developer-client.js +212 -0
- package/dist/hubspot-developer-client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/init/templates.d.ts +18 -0
- package/dist/init/templates.d.ts.map +1 -0
- package/dist/init/templates.js +239 -0
- package/dist/init/templates.js.map +1 -0
- package/dist/load-env.d.ts +16 -0
- package/dist/load-env.d.ts.map +1 -0
- package/dist/load-env.js +69 -0
- package/dist/load-env.js.map +1 -0
- package/dist/machine-id.d.ts +3 -0
- package/dist/machine-id.d.ts.map +1 -0
- package/dist/machine-id.js +41 -0
- package/dist/machine-id.js.map +1 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +19 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompt.d.ts +43 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +379 -0
- package/dist/prompt.js.map +1 -0
- package/dist/reporter/human.d.ts +28 -0
- package/dist/reporter/human.d.ts.map +1 -0
- package/dist/reporter/human.js +126 -0
- package/dist/reporter/human.js.map +1 -0
- package/dist/reporter/index.d.ts +14 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +37 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/reporter/json.d.ts +43 -0
- package/dist/reporter/json.d.ts.map +1 -0
- package/dist/reporter/json.js +146 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/reporter/style.d.ts +34 -0
- package/dist/reporter/style.d.ts.map +1 -0
- package/dist/reporter/style.js +97 -0
- package/dist/reporter/style.js.map +1 -0
- package/dist/reporter/types.d.ts +41 -0
- package/dist/reporter/types.d.ts.map +1 -0
- package/dist/reporter/types.js +2 -0
- package/dist/reporter/types.js.map +1 -0
- package/dist/result.d.ts +4 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +2 -0
- package/dist/result.js.map +1 -0
- package/dist/services/account-store.d.ts +31 -0
- package/dist/services/account-store.d.ts.map +1 -0
- package/dist/services/account-store.js +135 -0
- package/dist/services/account-store.js.map +1 -0
- package/dist/services/app-paths.d.ts +25 -0
- package/dist/services/app-paths.d.ts.map +1 -0
- package/dist/services/app-paths.js +34 -0
- package/dist/services/app-paths.js.map +1 -0
- package/dist/services/cloudflare-auth.d.ts +83 -0
- package/dist/services/cloudflare-auth.d.ts.map +1 -0
- package/dist/services/cloudflare-auth.js +30 -0
- package/dist/services/cloudflare-auth.js.map +1 -0
- package/dist/services/cloudflare-kv.d.ts +45 -0
- package/dist/services/cloudflare-kv.d.ts.map +1 -0
- package/dist/services/cloudflare-kv.js +151 -0
- package/dist/services/cloudflare-kv.js.map +1 -0
- package/dist/services/command-history.d.ts +29 -0
- package/dist/services/command-history.d.ts.map +1 -0
- package/dist/services/command-history.js +62 -0
- package/dist/services/command-history.js.map +1 -0
- package/dist/services/control-plane.d.ts +32 -0
- package/dist/services/control-plane.d.ts.map +1 -0
- package/dist/services/control-plane.js +57 -0
- package/dist/services/control-plane.js.map +1 -0
- package/dist/services/env-loader.d.ts +18 -0
- package/dist/services/env-loader.d.ts.map +1 -0
- package/dist/services/env-loader.js +34 -0
- package/dist/services/env-loader.js.map +1 -0
- package/dist/services/http.d.ts +19 -0
- package/dist/services/http.d.ts.map +1 -0
- package/dist/services/http.js +9 -0
- package/dist/services/http.js.map +1 -0
- package/dist/services/live.d.ts +16 -0
- package/dist/services/live.d.ts.map +1 -0
- package/dist/services/live.js +26 -0
- package/dist/services/live.js.map +1 -0
- package/dist/services/machine-id.d.ts +18 -0
- package/dist/services/machine-id.d.ts.map +1 -0
- package/dist/services/machine-id.js +39 -0
- package/dist/services/machine-id.js.map +1 -0
- package/dist/services/reporter.d.ts +55 -0
- package/dist/services/reporter.d.ts.map +1 -0
- package/dist/services/reporter.js +49 -0
- package/dist/services/reporter.js.map +1 -0
- package/dist/state-store.d.ts +39 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +89 -0
- package/dist/state-store.js.map +1 -0
- package/dist/telemetry.d.ts +13 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +129 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tenant-state.d.ts +69 -0
- package/dist/tenant-state.d.ts.map +1 -0
- package/dist/tenant-state.js +161 -0
- package/dist/tenant-state.js.map +1 -0
- 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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"}
|