Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .knowledge/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ docsets:
Zip archive:
https://bahnhub.tech.rz.db.de/artifactory/pipeship-generic-stage-dev-local/docs-as-code/latest/pipeship-docs.tar.gz
sources:
- type: zip
- type: archive
url: >-
https://bahnhub.tech.rz.db.de/artifactory/pipeship-generic-stage-dev-local/docs-as-code/latest/pipeship-docs.tar.gz
- id: local-docs
name: Local Documentation
description: "Local documentation: ./docs"
sources:
- type: local_folder
paths:
- ./docs
62 changes: 37 additions & 25 deletions packages/core/src/__tests__/path-calculator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { describe, test, expect, beforeEach, afterEach } from "vitest";
import { promises as fs } from "node:fs";
import { join, resolve, isAbsolute } from "node:path";
import { join, resolve } from "node:path";
import { tmpdir } from "node:os";
import {
calculateLocalPath,
Expand Down Expand Up @@ -34,6 +34,8 @@ describe("Path Calculation", () => {

describe("calculateLocalPath", () => {
test("should handle absolute paths", () => {
// Even with absolute source paths, calculateLocalPath should return
// the standard docset directory for consistency
const docset: DocsetConfig = {
id: "test",
name: "Test",
Expand All @@ -46,11 +48,14 @@ describe("Path Calculation", () => {
};

const result = calculateLocalPath(docset, configPath);
expect(result).toBe("/absolute/path/to/docs");
expect(isAbsolute(result)).toBe(true);
// Should return .knowledge/docsets/{id}, not the source path
const expected = join(tempDir, ".knowledge", "docsets", "test");
expect(result).toBe(expected);
});

test("should resolve relative paths from project root", () => {
test("should resolve relative paths to standard docset directory", () => {
// For local_folder, calculateLocalPath should return the standard
// docset directory .knowledge/docsets/{id} where symlinks will be created
const docset: DocsetConfig = {
id: "test",
name: "Test",
Expand All @@ -63,10 +68,12 @@ describe("Path Calculation", () => {
};

const result = calculateLocalPath(docset, configPath);
expect(result).toBe("docs");
const expected = join(tempDir, ".knowledge", "docsets", "test");
expect(result).toBe(expected);
});

test("should resolve parent directory paths", () => {
test("should resolve parent directory paths to standard docset directory", () => {
// Even with parent directory paths, should return standard docset directory
const docset: DocsetConfig = {
id: "test",
name: "Test",
Expand All @@ -79,10 +86,12 @@ describe("Path Calculation", () => {
};

const result = calculateLocalPath(docset, configPath);
expect(result).toBe("../shared-docs");
const expected = join(tempDir, ".knowledge", "docsets", "test");
expect(result).toBe(expected);
});

test("should normalize complex relative paths", () => {
test("should normalize complex relative paths to standard docset directory", () => {
// Even with complex paths, should return standard docset directory
const docset: DocsetConfig = {
id: "test",
name: "Test",
Expand All @@ -95,7 +104,8 @@ describe("Path Calculation", () => {
};

const result = calculateLocalPath(docset, configPath);
expect(result).toBe("guides");
const expected = join(tempDir, ".knowledge", "docsets", "test");
expect(result).toBe(expected);
});

test("should handle invalid config path gracefully", () => {
Expand All @@ -115,6 +125,7 @@ describe("Path Calculation", () => {
});

test("should handle multiple paths in local_folder source", () => {
// Uses the docset id for the directory, not the source paths
const docset: DocsetConfig = {
id: "multi-docs",
name: "Multiple Documentation",
Expand All @@ -127,7 +138,8 @@ describe("Path Calculation", () => {
};

const result = calculateLocalPath(docset, configPath);
expect(result).toBe("docs");
const expected = join(tempDir, ".knowledge", "docsets", "multi-docs");
expect(result).toBe(expected);
});

test("should handle git repo without optional fields", () => {
Expand Down Expand Up @@ -272,16 +284,15 @@ describe("Path Calculation", () => {
],
};

// Calculate path
// Calculate path - should return standard docset directory
const calculatedPath = calculateLocalPath(docset, configPath);

// Should return relative path
expect(calculatedPath).toBe("docs");
// Should return .knowledge/docsets/{id} path
const expected = join(tempDir, ".knowledge", "docsets", "test");
expect(calculatedPath).toBe(expected);

// Validate actual path exists (resolve relative to project root)
const absolutePath = resolve(tempDir, calculatedPath);
const pathExists = await validatePath(absolutePath);
expect(pathExists).toBe(true);
// The docset directory won't exist until init is run,
// but the path calculation should be consistent
});

test("should handle complex nested directory structure", async () => {
Expand Down Expand Up @@ -314,14 +325,15 @@ describe("Path Calculation", () => {

const result = calculateLocalPath(docset, projectConfig);

// Should return relative path
expect(result).toBe("src/components");

// Validate actual path exists
const projectRoot = join(tempDir, "project");
const absolutePath = resolve(projectRoot, result);
const validated = await validatePath(absolutePath);
expect(validated).toBe(true);
// Should return standard docset directory
const expected = join(
tempDir,
"project",
".knowledge",
"docsets",
"components",
);
expect(result).toBe(expected);
});
});
});
24 changes: 7 additions & 17 deletions packages/core/src/paths/calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@
* Path calculation utilities
*/

import {
resolve,
dirname,
isAbsolute,
join,
normalize,
relative,
} from "node:path";
import { dirname, join, normalize, relative } from "node:path";
import { promises as fs } from "node:fs";
import * as fsSync from "node:fs";
import * as pathModule from "node:path";
Expand Down Expand Up @@ -42,27 +35,24 @@ export function calculateLocalPath(
}

if (primarySource.type === "local_folder") {
// For local folders, return relative path from project root
// For local folders, use standardized path: .knowledge/docsets/{id}
// This ensures consistency with git_repo and archive types,
// and prevents accidentally modifying source directories during init
if (!primarySource.paths || primarySource.paths.length === 0) {
throw new Error(
`Local folder source for docset '${docset.id}' has no paths configured`,
);
}
// Validate that at least one path is configured
const firstPath = primarySource.paths[0];
if (!firstPath) {
throw new Error(
`Local folder source for docset '${docset.id}' has empty path`,
);
}

if (isAbsolute(firstPath)) {
// If absolute path, return as-is
return normalize(firstPath);
}

// If relative path, resolve from project root and return relative
const resolvedPath = resolve(projectRoot, firstPath);
return relative(projectRoot, resolvedPath) || ".";
// Return the standard docset directory, symlinks will be created there
return join(configDir, "docsets", docset.id);
}

if (primarySource.type === "git_repo") {
Expand Down
Loading