show what the commands are actually saying
Install, uninstall and purge narrated what the platform was doing and hid what it was running. Every spawn captured stdout and stderr, held them, and surfaced the last 600 characters only if the exit code was non-zero. That is enough to explain a crash and useless for the two things people want while watching an install: knowing a slow step is still moving, and seeing the warning a command prints on its way to exiting 0. The second is not hypothetical — `db:push` reported success on a machine where it created no tables. Its output was captured, discarded because the exit code was fine, and the failure surfaced minutes later as 42P01 in a sidecar log. Whatever drizzle said about that push, nobody ever read it. `runLogged` streams both pipes as they arrive, so they interleave the way they do in a terminal. Following only stdout would have been silent for exactly the commands worth watching: git writes everything to stderr, drizzle-kit writes progress there and results to stdout. Two pieces of noise control, because a log nobody can read is not an improvement: `git clone` gets `--progress` instead of `--quiet` (git says nothing when it thinks it has no terminal, and that is the step where a slow link looks like a hang) with per-percent rewrites collapsed to the last fragment per chunk; and drizzle's spinner, which is eight lines saying the same thing with a different braille glyph, collapses to the first — otherwise "Changes applied" scrolls past underneath it. Steps and output share ONE ordered list rather than two. Their order relative to each other is the whole information: "which step was this output from" is the only question the log exists to answer. Output renders dimmer and indented under the step that produced it. Verified by running a real purge and reinstall: the clone's object counts, the barrel generation naming both plugins, drizzle's push, then "schema: applied in 2029ms (1 table verified)". tsgo clean, frontend builds, 873 pass / 7 fail unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -205,14 +205,19 @@ pluginsRouter.post('/:appName/disable', async (ctx) => {
|
||||
|
||||
// `userId` is the caller, threaded through so install can pin the new tile to THEIR dock rather than
|
||||
// guessing at the owner. Only install uses it; the others take it and ignore it so the map stays one shape.
|
||||
type VerbFn = (appName: string, onStep: (s: string) => Promise<void>, userId: number) => Promise<PluginActionResult>;
|
||||
type VerbFn = (
|
||||
appName: string,
|
||||
onStep: (s: string) => Promise<void>,
|
||||
userId: number,
|
||||
onLog: (line: string) => Promise<void>,
|
||||
) => Promise<PluginActionResult>;
|
||||
|
||||
const VERBS = {
|
||||
install: (appName, onStep, userId) => installPlugin(appName, onStep, userId),
|
||||
uninstall: (appName, onStep) => uninstallPlugin(appName, onStep),
|
||||
install: (appName, onStep, userId, onLog) => installPlugin(appName, onStep, userId, onLog),
|
||||
uninstall: (appName, onStep, _userId, onLog) => uninstallPlugin(appName, onStep, onLog),
|
||||
enable: (appName, onStep) => setPluginRunning(appName, true, onStep),
|
||||
disable: (appName, onStep) => setPluginRunning(appName, false, onStep),
|
||||
purge: (appName, onStep) => purgePlugin(appName, onStep),
|
||||
purge: (appName, onStep, _userId, onLog) => purgePlugin(appName, onStep, onLog),
|
||||
// `satisfies` rather than an annotation: an annotation would widen the keys to `string`, which turns
|
||||
// `isVerb` into a guard that proves nothing and lets an unknown verb index the map.
|
||||
} satisfies Record<string, VerbFn>;
|
||||
@@ -244,7 +249,15 @@ pluginsRouter.post('/:appName/:verb/stream', async (ctx) => {
|
||||
|
||||
let result: PluginActionResult;
|
||||
try {
|
||||
result = await VERBS[verb](appName, async (step) => send('step', { step }), userId);
|
||||
result = await VERBS[verb](
|
||||
appName,
|
||||
async (step) => send('step', { step }),
|
||||
userId,
|
||||
// Raw output from whatever the step is running — `git clone`, `db:push`, a package manager.
|
||||
// A separate event so the client can render it as what it is: the command talking, not the
|
||||
// platform reporting.
|
||||
async (line) => send('log', { line }),
|
||||
);
|
||||
} catch (err) {
|
||||
result = { ok: false, appName, steps: [], error: err instanceof Error ? err.message : String(err) };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user