(opts: CodeGetOptions, deps: TestDeps = {})
| 3189 | * half-written artifact. |
| 3190 | */ |
| 3191 | export async function runCodeGet(opts: CodeGetOptions, deps: TestDeps = {}): Promise<CliTestCode> { |
| 3192 | // Dry-run: no fetch, no fs. Print the canned shape to stdout and, if |
| 3193 | // the user passed `--out`, log on stderr what would have been written. |
| 3194 | // We deliberately do NOT validate the `--out` path here in dry-run — |
| 3195 | // a missing-parent path is a real-mode failure mode; in dry-run the |
| 3196 | // point is "show me the shape, no side effects." |
| 3197 | if (opts.dryRun) { |
| 3198 | const stderr = deps.stderr ?? ((line: string) => process.stderr.write(`${line}\n`)); |
| 3199 | const out = makeOutput(opts.output, deps); |
| 3200 | const client = makeClient(opts, deps); |
| 3201 | const code = await client.get<CliTestCode>(`/tests/${encodeURIComponent(opts.testId)}/code`); |
| 3202 | if (opts.out !== undefined) { |
| 3203 | const bytes = isPresignedCodeUrl(code.code) ? '<presigned-stream>' : `${code.code.length}`; |
| 3204 | stderr(`[dry-run] would write code body (${bytes} bytes) to ${opts.out}`); |
| 3205 | } |
| 3206 | if (opts.output === 'json') { |
| 3207 | out.print(code); |
| 3208 | } else { |
| 3209 | await out.writeChunk(code.code); |
| 3210 | } |
| 3211 | return code; |
| 3212 | } |
| 3213 | |
| 3214 | const fileSink = opts.out !== undefined ? openOutputFile(opts.out) : null; |
| 3215 | const out = fileSink ? makeFileOutput(opts.output, fileSink) : makeOutput(opts.output, deps); |
| 3216 | const client = makeClient(opts, deps); |
| 3217 | |
| 3218 | try { |
| 3219 | const code = await client.get<CliTestCode>(`/tests/${encodeURIComponent(opts.testId)}/code`); |
| 3220 | |
| 3221 | if (opts.output === 'json') { |
| 3222 | out.print(code); |
| 3223 | } else if (isPresignedCodeUrl(code.code)) { |
| 3224 | // Text mode: dump the source body. JSON consumers want the wire |
| 3225 | // shape; humans (and agents shelling out via `> file.ts`) want |
| 3226 | // ready-to-edit code. Stream chunk-wise so a multi-MB generated |
| 3227 | // suite doesn't sit in memory waiting for the full download. |
| 3228 | // `writeChunk` awaits the rawStdout drain promise so a slow |
| 3229 | // downstream consumer (a file on a slow disk, an NFS mount, |
| 3230 | // or a piped `gzip`) pauses the upstream reader rather than |
| 3231 | // letting chunks accumulate in V8's heap. |
| 3232 | await streamPresignedBody(code.code, out, deps); |
| 3233 | } else if (code.code === '' || code.code === null) { |
| 3234 | // P2-10: draft test with no code yet — empty body would produce |
| 3235 | // silent empty stdout. Print a friendly hint to stderr instead so |
| 3236 | // the operator knows what happened, and keep exit 0. |
| 3237 | const stderrFn = deps.stderr ?? ((line: string) => process.stderr.write(`${line}\n`)); |
| 3238 | stderrFn('(no code generated yet — run the test first)'); |
| 3239 | } else { |
| 3240 | await out.writeChunk(code.code); |
| 3241 | } |
| 3242 | |
| 3243 | if (fileSink) await closeOutputFile(fileSink); |
| 3244 | return code; |
| 3245 | } catch (err) { |
| 3246 | if (fileSink) await closeOutputFile(fileSink).catch(() => undefined); |
| 3247 | throw err; |
| 3248 | } |
no test coverage detected