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 lint
This 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 -- --coverage
Tests 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
beforeEach
andafterEach
to 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