fix(cli): default dev mode db to <repo>/.kandev-dev/data (#664)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import path from "node:path";
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { resolveDevBackendEnv } from "./dev";
|
||||
|
||||
describe("resolveDevBackendEnv", () => {
|
||||
const originalTaskId = process.env.KANDEV_TASK_ID;
|
||||
const originalDbPath = process.env.KANDEV_DATABASE_PATH;
|
||||
const originalMock = process.env.KANDEV_MOCK_AGENT;
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env.KANDEV_TASK_ID;
|
||||
delete process.env.KANDEV_DATABASE_PATH;
|
||||
delete process.env.KANDEV_MOCK_AGENT;
|
||||
vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreEnv("KANDEV_TASK_ID", originalTaskId);
|
||||
restoreEnv("KANDEV_DATABASE_PATH", originalDbPath);
|
||||
restoreEnv("KANDEV_MOCK_AGENT", originalMock);
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("defaults to <repo>/.kandev-dev/data/kandev.db in a plain shell", () => {
|
||||
const repoRoot = "/tmp/repo";
|
||||
const { dbPath, extra } = resolveDevBackendEnv(repoRoot);
|
||||
|
||||
expect(dbPath).toBe(path.join(repoRoot, ".kandev-dev", "data", "kandev.db"));
|
||||
expect(extra.KANDEV_HOME_DIR).toBe(path.join(repoRoot, ".kandev-dev"));
|
||||
expect(extra.KANDEV_DATABASE_PATH).toBe("");
|
||||
});
|
||||
|
||||
it("honors an explicit KANDEV_DATABASE_PATH override in a plain shell", () => {
|
||||
process.env.KANDEV_DATABASE_PATH = "/tmp/custom.db";
|
||||
|
||||
const { dbPath, extra } = resolveDevBackendEnv("/tmp/repo");
|
||||
|
||||
expect(dbPath).toBe("/tmp/custom.db");
|
||||
expect(extra.KANDEV_DATABASE_PATH).toBe("/tmp/custom.db");
|
||||
expect(extra.KANDEV_HOME_DIR).toBeUndefined();
|
||||
});
|
||||
|
||||
it("ignores a leaked KANDEV_DATABASE_PATH when running inside a kandev task", () => {
|
||||
process.env.KANDEV_TASK_ID = "fake-task-id";
|
||||
process.env.KANDEV_DATABASE_PATH = "/parent/kandev.db";
|
||||
const repoRoot = "/tmp/repo";
|
||||
|
||||
const { dbPath, extra } = resolveDevBackendEnv(repoRoot);
|
||||
|
||||
expect(dbPath).toBe(path.join(repoRoot, ".kandev-dev", "data", "kandev.db"));
|
||||
expect(extra.KANDEV_HOME_DIR).toBe(path.join(repoRoot, ".kandev-dev"));
|
||||
expect(extra.KANDEV_DATABASE_PATH).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
function restoreEnv(name: string, value: string | undefined): void {
|
||||
if (value === undefined) {
|
||||
delete process.env[name];
|
||||
} else {
|
||||
process.env[name] = value;
|
||||
}
|
||||
}
|
||||
+27
-15
@@ -72,25 +72,28 @@ type DevBackendEnv = {
|
||||
extra: Record<string, string>;
|
||||
};
|
||||
|
||||
// Computes the dev-mode backend env. When invoked from inside a kandev task
|
||||
// workspace, force-relocates the entire kandev root to <repo>/.kandev-dev so
|
||||
// dev state is isolated from the user's production ~/.kandev. In a normal
|
||||
// shell, preserves the existing override-friendly behavior (honor an
|
||||
// explicit KANDEV_DATABASE_PATH, otherwise default to a repo-local db).
|
||||
function resolveDevBackendEnv(repoRoot: string): DevBackendEnv {
|
||||
// Computes the dev-mode backend env. Dev mode always roots kandev under
|
||||
// <repo>/.kandev-dev so state is isolated from the user's production ~/.kandev
|
||||
// and so `make clean-db` (which removes .kandev-dev/) matches what `make dev`
|
||||
// writes.
|
||||
//
|
||||
// When invoked from inside a kandev task workspace, any KANDEV_DATABASE_PATH
|
||||
// is assumed to be leaked from the parent backend and is ignored. In a normal
|
||||
// shell, an explicit KANDEV_DATABASE_PATH is honored as an escape hatch.
|
||||
export function resolveDevBackendEnv(repoRoot: string): DevBackendEnv {
|
||||
const baseExtra: Record<string, string> = {
|
||||
KANDEV_MOCK_AGENT: process.env.KANDEV_MOCK_AGENT || "true",
|
||||
KANDEV_DEBUG_PPROF_ENABLED: "true",
|
||||
};
|
||||
const devHome = devKandevHome(repoRoot);
|
||||
// Display only; the backend derives its own DB path from KANDEV_HOME_DIR
|
||||
// via ResolvedDataDir(). Both resolve to the same location.
|
||||
const devDbPath = path.join(devHome, "data", "kandev.db");
|
||||
|
||||
if (isInsideKandevTask(repoRoot)) {
|
||||
const devHome = devKandevHome(repoRoot);
|
||||
// Display only; the backend derives its own DB path from KANDEV_HOME_DIR
|
||||
// via ResolvedDataDir(). Both resolve to the same location.
|
||||
const dbPath = path.join(devHome, "data", "kandev.db");
|
||||
console.log("[kandev] task workspace detected → using local dev state");
|
||||
return {
|
||||
dbPath,
|
||||
dbPath: devDbPath,
|
||||
extra: {
|
||||
...baseExtra,
|
||||
KANDEV_HOME_DIR: devHome,
|
||||
@@ -100,10 +103,19 @@ function resolveDevBackendEnv(repoRoot: string): DevBackendEnv {
|
||||
};
|
||||
}
|
||||
|
||||
const dbPath =
|
||||
process.env.KANDEV_DATABASE_PATH || path.join(repoRoot, "apps", "backend", "kandev.db");
|
||||
const override = process.env.KANDEV_DATABASE_PATH;
|
||||
if (override) {
|
||||
return {
|
||||
dbPath: override,
|
||||
extra: { ...baseExtra, KANDEV_DATABASE_PATH: override },
|
||||
};
|
||||
}
|
||||
return {
|
||||
dbPath,
|
||||
extra: { ...baseExtra, KANDEV_DATABASE_PATH: dbPath },
|
||||
dbPath: devDbPath,
|
||||
extra: {
|
||||
...baseExtra,
|
||||
KANDEV_HOME_DIR: devHome,
|
||||
KANDEV_DATABASE_PATH: "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user