fix: auto-detect data directory in monorepo without DATA_DIR env var (#117)
- getDataDir() now detects monorepo by checking for ../docker-compose.yml - DATA_DIR env var removed from .env and .env.example (no longer needed for local dev) - Docker compose files explicitly set DATA_DIR=/app/data for containers - Updated tests for monorepo detection logic
This commit is contained in:
@@ -23,12 +23,24 @@ const migrationsFolder = resolve(__dirname, "../../drizzle");
|
||||
|
||||
/**
|
||||
* Get the data directory path.
|
||||
* Checks DATA_DIR env var first, then falls back to resolve(cwd, "data").
|
||||
* This ensures local dev (`cd backend && npm run dev`) and Docker both
|
||||
* use the same directory when DATA_DIR is set.
|
||||
*
|
||||
* Resolution order:
|
||||
* 1. DATA_DIR env var (set by docker-compose for containers)
|
||||
* 2. Monorepo detection: if ../docker-compose.yml exists, we're in backend/
|
||||
* subdirectory → use ../data (project root's data folder)
|
||||
* 3. Fallback: resolve(cwd, "data") (running from project root or standalone)
|
||||
*/
|
||||
export function getDataDir(cwd: string = process.cwd()): string {
|
||||
return process.env.DATA_DIR ? resolve(process.env.DATA_DIR) : resolve(cwd, "data");
|
||||
// Docker containers set DATA_DIR explicitly
|
||||
if (process.env.DATA_DIR) return resolve(process.env.DATA_DIR);
|
||||
|
||||
// Local dev: detect if we're in backend/ subdirectory of the monorepo
|
||||
if (existsSync(resolve(cwd, "..", "docker-compose.yml"))) {
|
||||
return resolve(cwd, "..", "data");
|
||||
}
|
||||
|
||||
// Default: data/ relative to cwd (running from project root)
|
||||
return resolve(cwd, "data");
|
||||
}
|
||||
|
||||
/** Build the database URL from a path */
|
||||
|
||||
@@ -156,9 +156,9 @@ describe("Database Client Utilities", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("should use DATA_DIR env var when set", () => {
|
||||
process.env.DATA_DIR = "/custom/data";
|
||||
expect(getDataDir()).toBe("/custom/data");
|
||||
it("should use DATA_DIR env var when set (Docker)", () => {
|
||||
process.env.DATA_DIR = "/app/data";
|
||||
expect(getDataDir()).toBe("/app/data");
|
||||
});
|
||||
|
||||
it("should resolve relative DATA_DIR to absolute", () => {
|
||||
@@ -168,12 +168,22 @@ describe("Database Client Utilities", () => {
|
||||
expect(result).toMatch(/\/data$/);
|
||||
});
|
||||
|
||||
it("should fall back to cwd/data when DATA_DIR is not set", () => {
|
||||
it("should detect monorepo and use ../data when in backend/ subdir", () => {
|
||||
delete process.env.DATA_DIR;
|
||||
expect(getDataDir("/app")).toBe("/app/data");
|
||||
// Tests run from backend/ which has ../docker-compose.yml
|
||||
const result = getDataDir();
|
||||
// Should resolve to the project root's data/ folder, not backend/data/
|
||||
expect(result).toMatch(/\/data$/);
|
||||
expect(result).not.toMatch(/backend\/data$/);
|
||||
});
|
||||
|
||||
it("should use DATA_DIR even when cwd is provided", () => {
|
||||
it("should fall back to cwd/data when not in monorepo", () => {
|
||||
delete process.env.DATA_DIR;
|
||||
// Use a directory that has no ../docker-compose.yml
|
||||
expect(getDataDir("/tmp")).toBe("/tmp/data");
|
||||
});
|
||||
|
||||
it("should prefer DATA_DIR over monorepo detection", () => {
|
||||
process.env.DATA_DIR = "/override/data";
|
||||
expect(getDataDir("/app")).toBe("/override/data");
|
||||
});
|
||||
@@ -190,27 +200,27 @@ describe("Database Client Utilities", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("should return correct paths based on cwd", () => {
|
||||
delete process.env.DATA_DIR;
|
||||
it("should return correct paths with DATA_DIR set", () => {
|
||||
process.env.DATA_DIR = "/app/data";
|
||||
const paths = getDbPaths("/app");
|
||||
expect(paths.dataDir).toBe("/app/data");
|
||||
expect(paths.dbPath).toBe("/app/data/medassist-ng.db");
|
||||
expect(paths.url).toBe("file:/app/data/medassist-ng.db");
|
||||
});
|
||||
|
||||
it("should return correct paths without DATA_DIR in non-monorepo dir", () => {
|
||||
delete process.env.DATA_DIR;
|
||||
const paths = getDbPaths("/tmp");
|
||||
expect(paths.dataDir).toBe("/tmp/data");
|
||||
expect(paths.dbPath).toBe("/tmp/data/medassist-ng.db");
|
||||
});
|
||||
|
||||
it("should use process.cwd() by default", () => {
|
||||
delete process.env.DATA_DIR;
|
||||
const paths = getDbPaths();
|
||||
expect(paths.dataDir).toContain("data");
|
||||
expect(paths.dbPath).toContain("medassist-ng.db");
|
||||
});
|
||||
|
||||
it("should respect DATA_DIR env var", () => {
|
||||
process.env.DATA_DIR = "/custom/data";
|
||||
const paths = getDbPaths("/app");
|
||||
expect(paths.dataDir).toBe("/custom/data");
|
||||
expect(paths.dbPath).toBe("/custom/data/medassist-ng.db");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ensureDataDirectory", () => {
|
||||
|
||||
Reference in New Issue
Block a user