dax
dax copied to clipboard
By default, print out debug information when error was encountered
Simple code such:
await $`false`;
Throws totally unhelpful error message like
Uncaught Error: Exited with code: 1
at CommandChild.pipedStdoutBuffer (file:///Users/krzkaczor/Workspace/spark/spark-alm-planner/node_modules/.pnpm/[email protected]/node_modules/dax-sh/esm/mod.js:8625:19)
(often even stack trace is not helpful).
I think the default behaviour should be to throw an error with command name that was executed and at least few final lines of stderr and stdout.
For reference, this is what bun/shell will do (output and error code both parts of the responses):
Hey @krzkaczor, hope you're doing well!
I think this is?
https://github.com/dsherret/dax/issues/150 https://github.com/dsherret/dax/issues/172
The stack trace right now is not helpful due to a v8 bug.
Hey David, long time no talk ;)
Yeah it's definitely related to those tickets, I decided to create another ticket because I think this behaviour should be a default. Feel free to close this if you think the other tickets are enough.
I came up with the following to work around this. It works decently well, although you lose out on the text, json, etc. helpers on CommandBuilder since they essentially spawn internally. Would be nice if this was somehow built in to dax.
Usage:
const result = await exec($`some-command`);
const json = result.stdoutJson;
Implementation:
export async function exec(
commandBuilder: CommandBuilder,
captureOutput = true,
): Promise<CommandResult> {
if (captureOutput) {
commandBuilder = commandBuilder
.noThrow()
.quiet()
.captureCombined();
}
const output = await commandBuilder.spawn();
if (output.code !== 0) {
const outputText = captureOutput
? output.combined
.split('\n')
.map((l) => `${' '.repeat(4)}${l}`)
.join('\n')
: '';
throw new Error(`Failed to execute command\n${outputText}`);
}
return output;
}
@dsherret Any advice on how to move forward with building something into dax itself to help deal with this? I'd like to use it more broadly, but it can be really painful to trace errors when using it in a lot of different files and contexts.
It would slow everything down and make it act differently. I think we need something like https://github.com/denoland/deno/issues/7586
@dsherret - I can't say I fully understand the scope of the problem here. I presume https://github.com/denoland/deno/issues/7586 has to do with supporting pipes ala deno_task_shell?
Did some further experimenting and it seems using Error.captureStackTrace (from v8 in node/deno) can help a bit here as well. For example, the following retains more of the stack trace.
async function captureAsyncStackTrace<T>(fn: () => Promise<T>) {
try {
return await fn()
} catch (error) {
Error.captureStackTrace(error as Error);
throw error;
}
}
async function main() {
await captureAsyncStackTrace(() => $`cmd-does-not-exist`.text());
}
await main();
I'm wondering if we could incorporate the Error.captureStackTrace to the Command.then, etc. to do this automatically?