diff --git a/package.json b/package.json index a273a6f..7241401 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "srcpack", - "version": "0.1.10", + "version": "0.1.13", "description": "Zero-config CLI for bundling code into LLM-optimized context files", "keywords": [ "llm", @@ -54,7 +54,8 @@ "files": [ "dist", "src", - "schema.json" + "LICENSE", + "README.md" ], "scripts": { "build": "bun build ./src/cli.ts ./src/index.ts --outdir ./dist --target node && tsc", diff --git a/src/cli.ts b/src/cli.ts index bfd9a07..0479f41 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -197,7 +197,7 @@ Options: for (const { name, outfile, result } of outputs) { const fileCount = result.index.length; const lineCount = sumLines(result); - const outPath = join(root, outfile); + const outPath = resolve(root, outfile); const nameCol = name.padEnd(maxNameLen); const filesCol = formatNumber(fileCount).padStart(maxFilesLen); @@ -213,8 +213,9 @@ Options: } else { await mkdir(dirname(outPath), { recursive: true }); await writeFile(outPath, result.content); + const displayPath = relative(process.cwd(), outPath); console.log( - ` ${nameCol} ${filesCol} ${plural(fileCount, "file")} ${linesCol} ${plural(lineCount, "line")} → ${outfile}`, + ` ${nameCol} ${filesCol} ${plural(fileCount, "file")} ${linesCol} ${plural(lineCount, "line")} → ${displayPath}`, ); } } @@ -358,7 +359,7 @@ async function handleGdriveUpload( for (let i = 0; i < toUpload.length; i++) { const output = toUpload[i]!; - const filePath = join(root, output.outfile); + const filePath = resolve(root, output.outfile); uploadSpinner.text = `Uploading ${output.name}... (${i + 1}/${toUpload.length})`; const result = await uploadFile(filePath, uploadConfig); results.push(result); diff --git a/tests/e2e/cli.test.ts b/tests/e2e/cli.test.ts index ecdfbee..2cdc5b7 100644 --- a/tests/e2e/cli.test.ts +++ b/tests/e2e/cli.test.ts @@ -1,5 +1,7 @@ -import { join } from "node:path"; -import { describe, expect, test } from "bun:test"; +import { mkdir, rm, writeFile } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { tmpdir } from "node:os"; +import { describe, expect, test, afterEach } from "bun:test"; const CLI_PATH = join(import.meta.dir, "../../src/cli.ts"); const FIXTURE_PATH = join(import.meta.dir, "../fixtures/sample-project"); @@ -114,4 +116,36 @@ describe("cli", () => { expect(result.stderr).toContain("Unknown bundle: unknown"); }); }); + + describe("absolute outDir with custom root", () => { + const tempRoot = join(tmpdir(), `srcpack-test-${Date.now()}`); + const tempOutDir = join(tmpdir(), `srcpack-out-${Date.now()}`); + + afterEach(async () => { + await rm(tempRoot, { recursive: true, force: true }); + await rm(tempOutDir, { recursive: true, force: true }); + }); + + test("should write to absolute outDir when root is also specified", async () => { + // Setup: create temp project with config using absolute outDir + await mkdir(join(tempRoot, "src"), { recursive: true }); + await writeFile(join(tempRoot, "src/index.ts"), "export const x = 1;"); + await writeFile( + join(tempRoot, "srcpack.config.ts"), + `export default { + outDir: ${JSON.stringify(tempOutDir)}, + bundles: { app: "src/**/*" }, + };`, + ); + + const result = await runCli([], { cwd: tempRoot }); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("app"); + + // Verify file was written to absolute outDir, not joined with root + const outFile = Bun.file(join(tempOutDir, "app.txt")); + expect(await outFile.exists()).toBe(true); + }); + }); });