feat(ipuaro): implement v0.1.0 foundation

- Project setup with tsup, vitest, ESM support
- Domain entities: Session, Project
- Value objects: FileData, FileAST, FileMeta, ChatMessage, ToolCall, ToolResult, UndoEntry
- Service interfaces: IStorage, ILLMClient, ITool, IIndexer, IToolRegistry
- Shared: Config (zod), IpuaroError, utils (hash, tokens), Result type
- CLI with placeholder commands (start, init, index)
- 91 unit tests with 100% coverage
- Fix package scope @puaros -> @samiyev in CLAUDE.md
This commit is contained in:
imfozilbek
2025-11-29 23:08:38 +05:00
parent 7f6180df37
commit 130a8c4f24
62 changed files with 4629 additions and 6 deletions

View File

@@ -0,0 +1,80 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
import { loadConfig, validateConfig, getConfigErrors } from "../../../../src/shared/config/loader.js"
import { DEFAULT_CONFIG } from "../../../../src/shared/constants/config.js"
import * as fs from "node:fs"
vi.mock("node:fs")
describe("config loader", () => {
beforeEach(() => {
vi.resetAllMocks()
})
afterEach(() => {
vi.restoreAllMocks()
})
describe("loadConfig", () => {
it("should return default config when no files exist", () => {
vi.mocked(fs.existsSync).mockReturnValue(false)
const config = loadConfig("/project")
expect(config).toEqual(DEFAULT_CONFIG)
})
it("should merge project config with defaults", () => {
vi.mocked(fs.existsSync).mockImplementation((path) => {
return path === "/project/.ipuaro.json"
})
vi.mocked(fs.readFileSync).mockReturnValue(
JSON.stringify({ llm: { model: "custom-model" } })
)
const config = loadConfig("/project")
expect(config.llm.model).toBe("custom-model")
expect(config.redis.host).toBe("localhost")
})
it("should handle invalid JSON gracefully", () => {
vi.mocked(fs.existsSync).mockReturnValue(true)
vi.mocked(fs.readFileSync).mockReturnValue("invalid json")
const config = loadConfig("/project")
expect(config).toEqual(DEFAULT_CONFIG)
})
})
describe("validateConfig", () => {
it("should return true for valid config", () => {
expect(validateConfig(DEFAULT_CONFIG)).toBe(true)
})
it("should return true for partial valid config", () => {
expect(validateConfig({ redis: { host: "redis.local" } })).toBe(true)
})
it("should return false for invalid config", () => {
expect(validateConfig({ redis: { port: "not a number" } })).toBe(false)
})
})
describe("getConfigErrors", () => {
it("should return empty array for valid config", () => {
const errors = getConfigErrors(DEFAULT_CONFIG)
expect(errors).toHaveLength(0)
})
it("should return errors for invalid config", () => {
const errors = getConfigErrors({
redis: { port: "invalid" },
})
expect(errors.length).toBeGreaterThan(0)
expect(errors[0]).toContain("redis.port")
})
})
})