@saptools/cf-inspector 0.4.10 → 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/README.md +2 -0
- package/dist/cli.js +37 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,7 @@ cf-inspector snapshot --port 9229 \
|
|
|
94
94
|
| `--condition <expr>` | Only pause when this JS expression evaluates truthy in the paused frame. Errors in the condition are silently treated as `false` by V8 |
|
|
95
95
|
| `--hit-count <n>` | Skip the first N − 1 hits and only pause on the Nth (combines with `--condition` via logical AND) |
|
|
96
96
|
| `--capture <expr,…>` | Top-level comma-separated expressions to evaluate in the paused frame; nested commas inside objects, arrays, calls, or strings are preserved. Object results are materialized to JSON strings when serializable, with fallback to CDP descriptions for non-serializable values |
|
|
97
|
+
| `--setup-eval <expr>` | Repeatable, order-preserving global expression evaluated inside the inspected process before breakpoint setup. It can mutate runtime state, so use it only in controlled debug sessions |
|
|
97
98
|
| `--stack-depth <n>` | Walk this many call frames per hit (default: `1`, top frame only). When `> 1`, the result includes a `stack` array |
|
|
98
99
|
| `--stack-captures <expr,…>` | Expressions to evaluate on each call frame in the captured stack |
|
|
99
100
|
| `--timeout <seconds>` | How long to wait for the breakpoint to hit (default: `30`) |
|
|
@@ -203,6 +204,7 @@ Each event is a `WatchEvent`:
|
|
|
203
204
|
| `--port <number>` | Local port the inspector or tunnel listens on |
|
|
204
205
|
| `--bp <file:line>` | **Required.** Source location to capture on (repeatable) |
|
|
205
206
|
| `--capture <expr,…>` | Top-level comma-separated expressions to evaluate per hit |
|
|
207
|
+
| `--setup-eval <expr>` | Repeatable, order-preserving global expression evaluated inside the inspected process before breakpoint setup. It can mutate runtime state, so use it only in controlled debug sessions |
|
|
206
208
|
| `--condition <expr>` | Only emit hits where this expression evaluates truthy |
|
|
207
209
|
| `--hit-count <n>` | Start emitting once the line has been hit N or more times |
|
|
208
210
|
| `--remote-root <value>` | Path-mapping anchor (same DSL as `snapshot`) |
|
package/dist/cli.js
CHANGED
|
@@ -1124,6 +1124,20 @@ async function evaluateGlobal(session, expression) {
|
|
|
1124
1124
|
silent: true
|
|
1125
1125
|
});
|
|
1126
1126
|
}
|
|
1127
|
+
async function runSetupEvals(session, expressions) {
|
|
1128
|
+
for (const expression of expressions) {
|
|
1129
|
+
const result = await evaluateGlobal(session, expression);
|
|
1130
|
+
if (result.exceptionDetails !== void 0) {
|
|
1131
|
+
throw new CfInspectorError(
|
|
1132
|
+
"SETUP_EVAL_FAILED",
|
|
1133
|
+
exceptionDetailsMessage(result, "setup evaluation failed")
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
function exceptionDetailsMessage(result, fallback) {
|
|
1139
|
+
return typeof result.exceptionDetails?.exception?.description === "string" ? result.exceptionDetails.exception.description : typeof result.exceptionDetails?.text === "string" ? result.exceptionDetails.text : fallback;
|
|
1140
|
+
}
|
|
1127
1141
|
function listScripts(session) {
|
|
1128
1142
|
return [...session.scripts.values()];
|
|
1129
1143
|
}
|
|
@@ -2711,8 +2725,10 @@ function prepareSnapshotCommand(opts, target) {
|
|
|
2711
2725
|
const condition = opts.condition !== void 0 && opts.condition.trim().length > 0 ? opts.condition.trim() : void 0;
|
|
2712
2726
|
const hitCount = parsePositiveInt(opts.hitCount, "--hit-count");
|
|
2713
2727
|
const stackDepth = parsePositiveInt(opts.stackDepth, "--stack-depth");
|
|
2728
|
+
const setupEvals = parseSetupEvals(opts.setupEval);
|
|
2714
2729
|
return {
|
|
2715
2730
|
target,
|
|
2731
|
+
setupEvals,
|
|
2716
2732
|
breakpoints: opts.bp.map((spec) => parseBreakpointSpec(spec)),
|
|
2717
2733
|
captures: parseCaptureList(opts.capture),
|
|
2718
2734
|
remoteRoot: parseRemoteRoot(opts.remoteRoot),
|
|
@@ -2726,6 +2742,12 @@ function prepareSnapshotCommand(opts, target) {
|
|
|
2726
2742
|
}
|
|
2727
2743
|
async function runSnapshotCommand(command, opts, reportProgress) {
|
|
2728
2744
|
return await withSession(command.target, async (session) => {
|
|
2745
|
+
if (command.setupEvals.length > 0) {
|
|
2746
|
+
const setupCount = command.setupEvals.length;
|
|
2747
|
+
reportProgress?.(`Running ${setupCount.toString()} setup ${setupCount === 1 ? "evaluation" : "evaluations"}...`);
|
|
2748
|
+
await runSetupEvals(session, command.setupEvals);
|
|
2749
|
+
reportProgress?.("Setup evaluation complete.");
|
|
2750
|
+
}
|
|
2729
2751
|
if (command.condition !== void 0) {
|
|
2730
2752
|
reportProgress?.("Validating the breakpoint condition...");
|
|
2731
2753
|
await validateExpression(session, command.condition);
|
|
@@ -2808,6 +2830,10 @@ async function resumeAfterSnapshot(session, snapshot, pausedStartedAt, reportPro
|
|
|
2808
2830
|
return withPausedDuration(snapshot, null);
|
|
2809
2831
|
}
|
|
2810
2832
|
}
|
|
2833
|
+
function parseSetupEvals(raw) {
|
|
2834
|
+
const values = Array.isArray(raw) ? raw : [];
|
|
2835
|
+
return values.filter((expr) => typeof expr === "string" && expr.trim().length > 0).map((expr) => expr.trim());
|
|
2836
|
+
}
|
|
2811
2837
|
|
|
2812
2838
|
// src/cli/commands/watch.ts
|
|
2813
2839
|
import { performance as performance5 } from "perf_hooks";
|
|
@@ -2841,8 +2867,10 @@ function prepareWatchCommand(opts, target) {
|
|
|
2841
2867
|
const hitCount = parsePositiveInt(opts.hitCount, "--hit-count");
|
|
2842
2868
|
const stackDepth = parsePositiveInt(opts.stackDepth, "--stack-depth");
|
|
2843
2869
|
const condition = opts.condition !== void 0 && opts.condition.trim().length > 0 ? opts.condition.trim() : void 0;
|
|
2870
|
+
const setupEvals = parseSetupEvals2(opts.setupEval);
|
|
2844
2871
|
return {
|
|
2845
2872
|
target,
|
|
2873
|
+
setupEvals,
|
|
2846
2874
|
breakpoints: opts.bp.map((spec) => parseBreakpointSpec(spec)),
|
|
2847
2875
|
captures: parseCaptureList(opts.capture),
|
|
2848
2876
|
remoteRoot: parseRemoteRoot(opts.remoteRoot),
|
|
@@ -2857,6 +2885,9 @@ function prepareWatchCommand(opts, target) {
|
|
|
2857
2885
|
};
|
|
2858
2886
|
}
|
|
2859
2887
|
async function runWatchLoop(session, command, opts, signal) {
|
|
2888
|
+
if (command.setupEvals.length > 0) {
|
|
2889
|
+
await runSetupEvals(session, command.setupEvals);
|
|
2890
|
+
}
|
|
2860
2891
|
if (command.condition !== void 0) {
|
|
2861
2892
|
await validateExpression(session, command.condition);
|
|
2862
2893
|
}
|
|
@@ -3030,6 +3061,10 @@ function writeWatchSummary(reason, emitted, json) {
|
|
|
3030
3061
|
`
|
|
3031
3062
|
);
|
|
3032
3063
|
}
|
|
3064
|
+
function parseSetupEvals2(raw) {
|
|
3065
|
+
const values = Array.isArray(raw) ? raw : [];
|
|
3066
|
+
return values.filter((expr) => typeof expr === "string" && expr.trim().length > 0).map((expr) => expr.trim());
|
|
3067
|
+
}
|
|
3033
3068
|
|
|
3034
3069
|
// src/cli/program.ts
|
|
3035
3070
|
function applyTargetOptions(cmd, options = {}) {
|
|
@@ -3057,7 +3092,7 @@ function registerSnapshot(program) {
|
|
|
3057
3092
|
applyTargetOptions(
|
|
3058
3093
|
program.command("snapshot").description("Set a breakpoint, wait for it to hit, capture expressions, and resume"),
|
|
3059
3094
|
{ includeTimeout: false }
|
|
3060
|
-
).option("--bp <file:line>", "Breakpoint location (repeatable; first hit wins), e.g. src/handler.ts:42", collectStrings, []).option("--capture <expr,\u2026>", "Top-level comma-separated expressions to evaluate in the paused frame").option("--timeout <seconds>", "How long to wait for the breakpoint to hit (default: 30)").option("--max-value-length <chars>", "Maximum characters per captured value before truncation (default: 4096)").option("--remote-root <value>", "Path-mapping anchor: literal path or regex:<pattern> / /pattern/flags").option("--condition <expr>", "Only pause when this JS expression evaluates truthy in the paused frame").option("--hit-count <n>", "Only pause after the breakpoint has been hit N or more times").option("--stack-depth <n>", "Walk this many call frames when capturing (default: 1, only top frame)").option("--stack-captures <expr,\u2026>", "Expressions to evaluate on each call frame in the stack").option("--include-scopes", "Include expanded paused-frame scopes in the snapshot").option("--no-json", "Print a human-readable summary instead of JSON").option("--quiet", "Suppress progress messages on stderr").option("--keep-paused", "Skip Debugger.resume after capture; Node may resume when this CLI disconnects").option("--fail-on-unmatched-pause", "Fail immediately if the target pauses somewhere else").action(async (opts) => {
|
|
3095
|
+
).option("--bp <file:line>", "Breakpoint location (repeatable; first hit wins), e.g. src/handler.ts:42", collectStrings, []).option("--capture <expr,\u2026>", "Top-level comma-separated expressions to evaluate in the paused frame").option("--setup-eval <expr>", "Evaluate a global setup expression before breakpoint setup (repeatable)", collectStrings, []).option("--timeout <seconds>", "How long to wait for the breakpoint to hit (default: 30)").option("--max-value-length <chars>", "Maximum characters per captured value before truncation (default: 4096)").option("--remote-root <value>", "Path-mapping anchor: literal path or regex:<pattern> / /pattern/flags").option("--condition <expr>", "Only pause when this JS expression evaluates truthy in the paused frame").option("--hit-count <n>", "Only pause after the breakpoint has been hit N or more times").option("--stack-depth <n>", "Walk this many call frames when capturing (default: 1, only top frame)").option("--stack-captures <expr,\u2026>", "Expressions to evaluate on each call frame in the stack").option("--include-scopes", "Include expanded paused-frame scopes in the snapshot").option("--no-json", "Print a human-readable summary instead of JSON").option("--quiet", "Suppress progress messages on stderr").option("--keep-paused", "Skip Debugger.resume after capture; Node may resume when this CLI disconnects").option("--fail-on-unmatched-pause", "Fail immediately if the target pauses somewhere else").action(async (opts) => {
|
|
3061
3096
|
await handleSnapshot(opts);
|
|
3062
3097
|
});
|
|
3063
3098
|
}
|
|
@@ -3072,7 +3107,7 @@ function registerWatch(program) {
|
|
|
3072
3107
|
applyTargetOptions(
|
|
3073
3108
|
program.command("watch").description("Stream a snapshot per breakpoint hit (multi-shot watch); resume between hits"),
|
|
3074
3109
|
{ includeTimeout: false }
|
|
3075
|
-
).option("--bp <file:line>", "Breakpoint location (repeatable), e.g. src/handler.ts:42", collectStrings, []).option("--capture <expr,\u2026>", "Top-level comma-separated expressions to evaluate per hit").option("--condition <expr>", "Only emit hits where this JS expression evaluates truthy").option("--hit-count <n>", "Start emitting after the line has been hit N or more times").option("--remote-root <value>", "Path-mapping anchor: literal path or regex:<pattern> / /pattern/flags").option("--duration <seconds>", "Stop streaming after N seconds (default: run until SIGINT)").option("--max-events <n>", "Stop streaming after emitting N watch events").option("--timeout <seconds>", "How long to wait for the next hit before giving up (default: 30)").option("--max-value-length <chars>", "Maximum characters per captured value before truncation (default: 4096)").option("--stack-depth <n>", "Walk this many call frames per hit (default: 1)").option("--stack-captures <expr,\u2026>", "Expressions to evaluate on each call frame").option("--include-scopes", "Include expanded paused-frame scopes per hit").option("--no-json", "Print human-readable lines instead of JSON Lines").action(async (opts) => {
|
|
3110
|
+
).option("--bp <file:line>", "Breakpoint location (repeatable), e.g. src/handler.ts:42", collectStrings, []).option("--capture <expr,\u2026>", "Top-level comma-separated expressions to evaluate per hit").option("--setup-eval <expr>", "Evaluate a global setup expression before breakpoint setup (repeatable)", collectStrings, []).option("--condition <expr>", "Only emit hits where this JS expression evaluates truthy").option("--hit-count <n>", "Start emitting after the line has been hit N or more times").option("--remote-root <value>", "Path-mapping anchor: literal path or regex:<pattern> / /pattern/flags").option("--duration <seconds>", "Stop streaming after N seconds (default: run until SIGINT)").option("--max-events <n>", "Stop streaming after emitting N watch events").option("--timeout <seconds>", "How long to wait for the next hit before giving up (default: 30)").option("--max-value-length <chars>", "Maximum characters per captured value before truncation (default: 4096)").option("--stack-depth <n>", "Walk this many call frames per hit (default: 1)").option("--stack-captures <expr,\u2026>", "Expressions to evaluate on each call frame").option("--include-scopes", "Include expanded paused-frame scopes per hit").option("--no-json", "Print human-readable lines instead of JSON Lines").action(async (opts) => {
|
|
3076
3111
|
await handleWatch(opts);
|
|
3077
3112
|
});
|
|
3078
3113
|
}
|