A modern, maintainable dotfiles management system built with TypeScript and Bun.
- Multi-platform support (Arch Linux, Ubuntu)
- Template-based installation profiles (headless, desktop, personal)
- Intelligent symlink management with automatic backups
- Comprehensive error handling and logging
- Idempotent operations for safe re-runs
- Bun runtime
- Linux environment (Arch or Ubuntu)
# Clone the repository
git clone https://github.com/yourusername/dotfiles.git
cd dotfiles
# Install dependencies
bun install
# Build the project
bun run build# Run with default settings (headless template)
bun start
# Run in interactive mode
bun start -- -i
# Specify a platform
bun start -- --arch
bun start -- --ubuntu
# Combine flags
bun start -- -i --arch# Run in development mode with auto-reload
bun run dev
# Type checking
bun run check
# Format code
bun run format
# Lint code
bun run lintThis project uses Vitest as the standard testing framework. All tests should be written using Vitest.
# Run all tests once
bun run test
# Run tests in watch mode (re-runs on file changes)
bun run test:watch
# Run tests with coverage
bun run test -- --coverageTests are located in the tests/ directory and follow the pattern *.test.ts. Here's how to write tests with Vitest:
import { describe, it, expect, beforeEach, vi } from "vitest";
import { YourClass } from "../../../src/your-module";
describe("YourClass", () => {
let instance: YourClass;
beforeEach(() => {
instance = new YourClass();
vi.clearAllMocks();
});
it("should do something", () => {
const result = instance.doSomething();
expect(result).toBe("expected value");
});
});// Mock a function
const mockFn = vi.fn(() => "mocked return value");
// Mock a module
vi.mock("fs/promises", () => ({
readFile: vi.fn(),
writeFile: vi.fn(),
}));
// Mock implementation
mockFn.mockImplementation(() => "new implementation");
// Assertions
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith("expected argument");
expect(mockFn).toHaveBeenCalledTimes(1);it("should handle async operations", async () => {
const result = await instance.asyncMethod();
expect(result).toBe("expected value");
});
it("should handle promise rejections", async () => {
await expect(instance.failingMethod()).rejects.toThrow("Expected error");
});The project uses vitest.config.ts for test configuration:
- Tests are located in
tests/**/*.test.ts - Node environment is used for testing
- Coverage reports are generated with v8 provider
- Global test utilities are available (no need to import
describe,it,expect)
- Use descriptive test names: Test names should clearly describe what is being tested
- Follow AAA pattern: Arrange, Act, Assert
- Mock external dependencies: Use
vi.mock()to isolate units under test - Clean up after tests: Use
beforeEachandafterEachto reset state - Test both success and error cases: Ensure comprehensive coverage
- Use TypeScript: All tests should be written in TypeScript with proper typing
src/- Source codeconfig/- Configuration managementplatform/- Platform-specific handlerspackage/- Package managementsymlink/- Symlink managementsudo/- Sudo permission managementlogger/- Logging systemorchestrator/- Main orchestrationtypes/- TypeScript type definitions
Configuration files are stored in the config/ directory:
templates/- Template definitionsheadless.json- Headless server templatedesktop.json- Desktop environment templatepersonal.json- Personal configuration template
packages.json- Package definitions for different platformssymlinks.json- Symlink mapping definitionspost-install.json- Post-installation tasks
MIT