@saptools/cf-inspector 0.4.8 → 0.4.11

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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DebuggerHandle, SessionStatus } from '@saptools/cf-debugger';
2
2
 
3
- type CfInspectorErrorCode = "INVALID_ARGUMENT" | "INVALID_BREAKPOINT" | "INVALID_REMOTE_ROOT" | "INVALID_EXPRESSION" | "INVALID_HIT_COUNT" | "INVALID_PAUSE_TYPE" | "BREAKPOINT_DID_NOT_BIND" | "INSPECTOR_DISCOVERY_FAILED" | "INSPECTOR_CONNECTION_FAILED" | "CDP_REQUEST_FAILED" | "BREAKPOINT_NOT_HIT" | "UNRELATED_PAUSE" | "UNRELATED_PAUSE_TIMEOUT" | "EVALUATION_FAILED" | "MISSING_TARGET" | "ABORTED";
3
+ type CfInspectorErrorCode = "INVALID_ARGUMENT" | "INVALID_BREAKPOINT" | "INVALID_REMOTE_ROOT" | "INVALID_EXPRESSION" | "SETUP_EVAL_FAILED" | "INVALID_HIT_COUNT" | "INVALID_PAUSE_TYPE" | "BREAKPOINT_DID_NOT_BIND" | "INSPECTOR_DISCOVERY_FAILED" | "INSPECTOR_CONNECTION_FAILED" | "CDP_REQUEST_FAILED" | "BREAKPOINT_NOT_HIT" | "UNRELATED_PAUSE" | "UNRELATED_PAUSE_TIMEOUT" | "EVALUATION_FAILED" | "MISSING_TARGET" | "ABORTED";
4
4
  declare class CfInspectorError extends Error {
5
5
  readonly code: CfInspectorErrorCode;
6
6
  readonly detail?: string;
@@ -117,6 +117,7 @@ interface InspectorConnectOptions {
117
117
  readonly port: number;
118
118
  readonly host?: string;
119
119
  readonly connectTimeoutMs?: number;
120
+ readonly targetIndex?: number;
120
121
  }
121
122
 
122
123
  declare function parseBreakpointSpec(input: string): BreakpointLocation;
@@ -264,6 +265,7 @@ declare function resume(session: InspectorSession): Promise<void>;
264
265
  declare function setPauseOnExceptions(session: InspectorSession, state: PauseOnExceptionsState): Promise<void>;
265
266
  declare function evaluateOnFrame(session: InspectorSession, callFrameId: string, expression: string): Promise<CdpEvalResult>;
266
267
  declare function evaluateGlobal(session: InspectorSession, expression: string): Promise<CdpEvalResult>;
268
+ declare function runSetupEvals(session: InspectorSession, expressions: readonly string[]): Promise<void>;
267
269
  declare function listScripts(session: InspectorSession): readonly ScriptInfo[];
268
270
  declare function validateExpression(session: InspectorSession, expression: string): Promise<void>;
269
271
  declare function getProperties(session: InspectorSession, objectId: string): Promise<readonly CdpProperty[]>;
@@ -338,9 +340,9 @@ interface TunnelTarget {
338
340
  }
339
341
  interface OpenedTunnel {
340
342
  readonly localPort: number;
341
- readonly handle: DebuggerHandle;
343
+ readonly handle?: DebuggerHandle;
342
344
  dispose(): Promise<void>;
343
345
  }
344
346
  declare function openCfTunnel(target: TunnelTarget): Promise<OpenedTunnel>;
345
347
 
346
- export { type BreakpointHandle, type BreakpointLocation, type CallFrameInfo, type CaptureSnapshotOptions, type CapturedExpression, CfInspectorError, type CfInspectorErrorCode, type DebuggerState, type ExceptionSnapshot, type FrameSnapshot, type InspectorConnectOptions, type InspectorSession, type InspectorTarget, type LogpointConditionOptions, type LogpointEvent, type LogpointStopReason, type LogpointStreamOptions, type LogpointStreamResult, type OpenedTunnel, type PauseEvent, type PauseOnExceptionsState, type RemoteRootSetting, type ResolvedLocation, type ScopeInfo, type ScopeSnapshot, type ScriptInfo, type SetBreakpointInput, type SnapshotCaptureResult, type SnapshotResult, type TunnelTarget, type VariableSnapshot, type WaitForPauseOptions, type WalkStackOptions, type WatchEvent, buildBreakpointUrlRegex, buildHitCountedCondition, buildLogpointCondition, captureException, captureSnapshot, connectInspector, discoverInspectorTargets, evaluateGlobal, evaluateOnFrame, fetchInspectorVersion, getProperties, listScripts, openCfTunnel, parseBreakpointSpec, parseRemoteRoot, removeBreakpoint, resume, setBreakpoint, setPauseOnExceptions, streamLogpoint, validateExpression, waitForPause, walkStack };
348
+ export { type BreakpointHandle, type BreakpointLocation, type CallFrameInfo, type CaptureSnapshotOptions, type CapturedExpression, CfInspectorError, type CfInspectorErrorCode, type DebuggerState, type ExceptionSnapshot, type FrameSnapshot, type InspectorConnectOptions, type InspectorSession, type InspectorTarget, type LogpointConditionOptions, type LogpointEvent, type LogpointStopReason, type LogpointStreamOptions, type LogpointStreamResult, type OpenedTunnel, type PauseEvent, type PauseOnExceptionsState, type RemoteRootSetting, type ResolvedLocation, type ScopeInfo, type ScopeSnapshot, type ScriptInfo, type SetBreakpointInput, type SnapshotCaptureResult, type SnapshotResult, type TunnelTarget, type VariableSnapshot, type WaitForPauseOptions, type WalkStackOptions, type WatchEvent, buildBreakpointUrlRegex, buildHitCountedCondition, buildLogpointCondition, captureException, captureSnapshot, connectInspector, discoverInspectorTargets, evaluateGlobal, evaluateOnFrame, fetchInspectorVersion, getProperties, listScripts, openCfTunnel, parseBreakpointSpec, parseRemoteRoot, removeBreakpoint, resume, runSetupEvals, setBreakpoint, setPauseOnExceptions, streamLogpoint, validateExpression, waitForPause, walkStack };
package/dist/index.js CHANGED
@@ -723,6 +723,20 @@ async function evaluateGlobal(session, expression) {
723
723
  silent: true
724
724
  });
725
725
  }
726
+ async function runSetupEvals(session, expressions) {
727
+ for (const expression of expressions) {
728
+ const result = await evaluateGlobal(session, expression);
729
+ if (result.exceptionDetails !== void 0) {
730
+ throw new CfInspectorError(
731
+ "SETUP_EVAL_FAILED",
732
+ exceptionDetailsMessage(result, "setup evaluation failed")
733
+ );
734
+ }
735
+ }
736
+ }
737
+ function exceptionDetailsMessage(result, fallback) {
738
+ return typeof result.exceptionDetails?.exception?.description === "string" ? result.exceptionDetails.exception.description : typeof result.exceptionDetails?.text === "string" ? result.exceptionDetails.text : fallback;
739
+ }
726
740
  function listScripts(session) {
727
741
  return [...session.scripts.values()];
728
742
  }
@@ -1004,11 +1018,12 @@ async function connectInspector(options) {
1004
1018
  const host = options.host ?? DEFAULT_HOST;
1005
1019
  const connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
1006
1020
  const targets = await discoverInspectorTargets(host, options.port, connectTimeoutMs);
1007
- const target = targets[0];
1021
+ const targetIndex = options.targetIndex ?? 0;
1022
+ const target = targets[targetIndex];
1008
1023
  if (!target) {
1009
1024
  throw new CfInspectorError(
1010
1025
  "INSPECTOR_DISCOVERY_FAILED",
1011
- `No inspector targets available on ${host}:${options.port.toString()}`
1026
+ `No inspector target at index ${targetIndex.toString()} on ${host}:${options.port.toString()} (available: ${targets.length.toString()})`
1012
1027
  );
1013
1028
  }
1014
1029
  const client = await CdpClient.connect({
@@ -1871,15 +1886,54 @@ async function openCfTunnel(target) {
1871
1886
  ...target.signal === void 0 ? {} : { signal: target.signal },
1872
1887
  ...target.onStatus === void 0 ? {} : { onStatus: target.onStatus }
1873
1888
  };
1874
- const handle = await startDebugger(opts);
1889
+ try {
1890
+ const handle = await startDebugger(opts);
1891
+ return {
1892
+ localPort: handle.session.localPort,
1893
+ handle,
1894
+ dispose: async () => {
1895
+ await handle.dispose();
1896
+ }
1897
+ };
1898
+ } catch (err) {
1899
+ return reuseExistingTunnelOrThrow(err, target.onStatus);
1900
+ }
1901
+ }
1902
+ function reuseExistingTunnelOrThrow(err, onStatus) {
1903
+ if (!isSessionAlreadyRunningError(err)) {
1904
+ throw err;
1905
+ }
1906
+ const message = err instanceof Error ? err.message : String(err);
1907
+ const port = extractExistingTunnelPort(message);
1908
+ if (port === void 0) {
1909
+ throw err;
1910
+ }
1911
+ const warning = `Reusing existing tunnel on port ${port.toString()}`;
1912
+ onStatus?.("ready", warning);
1875
1913
  return {
1876
- localPort: handle.session.localPort,
1877
- handle,
1878
- dispose: async () => {
1879
- await handle.dispose();
1880
- }
1914
+ localPort: port,
1915
+ dispose: () => Promise.resolve()
1881
1916
  };
1882
1917
  }
1918
+ function isSessionAlreadyRunningError(err) {
1919
+ if (typeof err !== "object" || err === null) {
1920
+ return false;
1921
+ }
1922
+ const code = err.code;
1923
+ return code === "SESSION_ALREADY_RUNNING";
1924
+ }
1925
+ function extractExistingTunnelPort(message) {
1926
+ const match = /on port (\d+)/i.exec(message);
1927
+ if (match === null) {
1928
+ return void 0;
1929
+ }
1930
+ const rawPort = match[1];
1931
+ if (rawPort === void 0) {
1932
+ return void 0;
1933
+ }
1934
+ const port = Number.parseInt(rawPort, 10);
1935
+ return Number.isNaN(port) ? void 0 : port;
1936
+ }
1883
1937
  export {
1884
1938
  CfInspectorError,
1885
1939
  buildBreakpointUrlRegex,
@@ -1899,6 +1953,7 @@ export {
1899
1953
  parseRemoteRoot,
1900
1954
  removeBreakpoint,
1901
1955
  resume,
1956
+ runSetupEvals,
1902
1957
  setBreakpoint,
1903
1958
  setPauseOnExceptions,
1904
1959
  streamLogpoint,