# Bootstrap System API Documentation ## Overview This document describes the internal API of the NIP Bootstrap System. This is intended for developers who want to understand or extend the bootstrap functionality. ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Bootstrap Coordinator │ │ (bootstrap.nim) │ └────────────────────┬────────────────────────────────────────┘ │ ┌────────────┼────────────┬──────────────┐ │ │ │ │ ▼ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Recipe │ │Download │ │Install │ │ Tool │ │ Manager │ │ Manager │ │ Manager │ │ Adapters │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ``` ## Module: recipe_parser.nim Parses and validates KDL recipe files. ### Types #### `PlatformArch` ```nim type PlatformArch* = enum paX86_64 = "x86_64" paAarch64 = "aarch64" paArmv7 = "armv7" ``` Supported CPU architectures. #### `RecipeBinary` ```nim type RecipeBinary* = object name*: string url*: string checksum*: string # Format: "blake2b-" size*: int64 # bytes executable*: bool ``` Represents a standalone binary file. #### `RecipeArchive` ```nim type RecipeArchive* = object name*: string url*: string checksum*: string size*: int64 extractTo*: string ``` Represents a compressed archive. #### `RecipePlatform` ```nim type RecipePlatform* = object arch*: PlatformArch os*: string # "linux", "bsd", etc. binaries*: seq[RecipeBinary] archives*: seq[RecipeArchive] ``` Platform-specific binaries and archives. #### `RecipeDependency` ```nim type RecipeDependency* = object name*: string kind*: string # "system", "nip", "optional" version*: string # Optional version requirement required*: bool ``` System or package dependency. #### `RecipeInstall` ```nim type RecipeInstall* = object script*: string # Path to installation script verifyScript*: string # Path to verification script postInstall*: string # Optional post-install script ``` Installation script configuration. #### `RecipeMetadata` ```nim type RecipeMetadata* = object author*: string license*: string updated*: string # ISO date homepage*: string issues*: string ``` Recipe metadata. #### `Recipe` ```nim type Recipe* = object name*: string version*: string description*: string toolType*: string # "nix", "pkgsrc", "gentoo" platforms*: seq[RecipePlatform] dependencies*: seq[RecipeDependency] install*: RecipeInstall metadata*: RecipeMetadata ``` Complete recipe definition. ### Procedures #### `parseRecipe` ```nim proc parseRecipe*(kdlContent: string): Option[Recipe] ``` Parse a recipe from KDL string content. **Parameters:** - `kdlContent` - KDL recipe content as string **Returns:** - `Option[Recipe]` - Parsed recipe or none if parsing fails **Example:** ```nim let content = readFile("minimal-nix.kdl") let recipeOpt = parseRecipe(content) if recipeOpt.isSome(): let recipe = recipeOpt.get() echo recipe.name ``` #### `parseRecipeFile` ```nim proc parseRecipeFile*(filePath: string): Option[Recipe] ``` Parse a recipe from a file. **Parameters:** - `filePath` - Path to recipe file **Returns:** - `Option[Recipe]` - Parsed recipe or none if parsing fails **Example:** ```nim let recipeOpt = parseRecipeFile("recipes/nix/minimal-nix.kdl") ``` #### `validateRecipe` ```nim proc validateRecipe*(recipe: Recipe): tuple[valid: bool, errors: seq[string]] ``` Validate a recipe structure. **Parameters:** - `recipe` - Recipe to validate **Returns:** - Tuple of (valid, errors) where valid is true if recipe is valid **Example:** ```nim let (valid, errors) = validateRecipe(recipe) if not valid: for error in errors: echo "Error: ", error ``` #### `selectPlatform` ```nim proc selectPlatform*(recipe: Recipe, targetArch: PlatformArch, targetOs: string = "linux"): Option[RecipePlatform] ``` Select appropriate platform from recipe. **Parameters:** - `recipe` - Recipe to select from - `targetArch` - Target architecture - `targetOs` - Target OS (default: "linux") **Returns:** - `Option[RecipePlatform]` - Selected platform or none **Example:** ```nim let platformOpt = selectPlatform(recipe, paX86_64, "linux") ``` #### `getCurrentPlatform` ```nim proc getCurrentPlatform*(): tuple[arch: PlatformArch, os: string] ``` Detect current system platform. **Returns:** - Tuple of (arch, os) **Example:** ```nim let (arch, os) = getCurrentPlatform() echo "Running on: ", arch, "/", os ``` ## Module: recipe_manager.nim Manages recipe fetching, caching, and loading. ### Types #### `RecipeManager` ```nim type RecipeManager* = ref object repoUrl*: string localCache*: string recipes*: Table[string, Recipe] lastUpdate*: Time ``` Manages recipe repository and caching. #### `RecipeFetchResult` ```nim type RecipeFetchResult* = object success*: bool message*: string recipesUpdated*: int ``` Result of recipe fetch operation. ### Procedures #### `newRecipeManager` ```nim proc newRecipeManager*(repoUrl: string = DefaultRepoUrl, cacheDir: string = ""): RecipeManager ``` Create a new RecipeManager. **Parameters:** - `repoUrl` - Git repository URL (default: NexusToolKit repo) - `cacheDir` - Cache directory (default: XDG cache) **Returns:** - `RecipeManager` instance **Example:** ```nim let manager = newRecipeManager() ``` #### `fetchRecipes` ```nim proc fetchRecipes*(rm: RecipeManager): RecipeFetchResult ``` Fetch or update recipes from Git repository. **Parameters:** - `rm` - RecipeManager instance **Returns:** - `RecipeFetchResult` with status and message **Example:** ```nim let result = manager.fetchRecipes() if result.success: echo "Updated ", result.recipesUpdated, " recipes" ``` #### `loadRecipe` ```nim proc loadRecipe*(rm: RecipeManager, toolType: string): Option[Recipe] ``` Load and parse recipe for a tool type. **Parameters:** - `rm` - RecipeManager instance - `toolType` - Tool type ("nix", "pkgsrc", "gentoo") **Returns:** - `Option[Recipe]` - Loaded recipe or none **Example:** ```nim let recipeOpt = manager.loadRecipe("nix") if recipeOpt.isSome(): let recipe = recipeOpt.get() echo "Loaded: ", recipe.name ``` #### `hasRecipe` ```nim proc hasRecipe*(rm: RecipeManager, toolType: string): bool ``` Check if recipe exists for a tool type. **Parameters:** - `rm` - RecipeManager instance - `toolType` - Tool type to check **Returns:** - `bool` - True if recipe exists **Example:** ```nim if manager.hasRecipe("nix"): echo "Nix recipe available" ``` #### `listAvailableRecipes` ```nim proc listAvailableRecipes*(rm: RecipeManager): seq[string] ``` List all available recipe tool types. **Parameters:** - `rm` - RecipeManager instance **Returns:** - Sequence of tool type strings **Example:** ```nim for toolType in manager.listAvailableRecipes(): echo "Available: ", toolType ``` ## Module: download_manager.nim Manages file downloads with verification. ### Types #### `DownloadResult` ```nim type DownloadResult* = object success*: bool filePath*: string message*: string bytesDownloaded*: int64 duration*: Duration ``` Result of download operation. #### `DownloadManager` ```nim type DownloadManager* = ref object cacheDir*: string maxRetries*: int timeout*: Duration client*: HttpClient ``` Manages file downloads. ### Procedures #### `newDownloadManager` ```nim proc newDownloadManager*(cacheDir: string = ""): DownloadManager ``` Create a new DownloadManager. **Parameters:** - `cacheDir` - Cache directory (default: XDG cache) **Returns:** - `DownloadManager` instance **Example:** ```nim let manager = newDownloadManager() defer: manager.close() ``` #### `close` ```nim proc close*(dm: DownloadManager) ``` Close the download manager and cleanup resources. **Parameters:** - `dm` - DownloadManager instance **Example:** ```nim manager.close() ``` #### `downloadFile` ```nim proc downloadFile*(dm: DownloadManager, url: string, destPath: string, expectedChecksum: string = ""): DownloadResult ``` Download a file with checksum verification. **Parameters:** - `dm` - DownloadManager instance - `url` - Download URL (HTTPS) - `destPath` - Destination file path - `expectedChecksum` - Expected Blake2b checksum (optional) **Returns:** - `DownloadResult` with status and details **Example:** ```nim let result = manager.downloadFile( "https://example.com/file", "/tmp/file", "blake2b-abc123..." ) if result.success: echo "Downloaded: ", result.bytesDownloaded, " bytes" ``` #### `verifyChecksum` ```nim proc verifyChecksum*(filePath: string, expectedChecksum: string): bool ``` Verify file checksum using Blake2b. **Parameters:** - `filePath` - Path to file - `expectedChecksum` - Expected checksum in format "blake2b-" **Returns:** - `bool` - True if checksum matches **Example:** ```nim if verifyChecksum("/tmp/file", "blake2b-abc123..."): echo "Checksum verified" ``` #### `getCachedFile` ```nim proc getCachedFile*(dm: DownloadManager, filename: string): string ``` Get path to cached file. **Parameters:** - `dm` - DownloadManager instance - `filename` - Filename **Returns:** - Full path to cached file **Example:** ```nim let path = manager.getCachedFile("nix-build") ``` ## Module: installation_manager.nim Manages tool installation and rollback. ### Types #### `InstallState` ```nim type InstallState* = enum isNotStarted = "not_started" isFetching = "fetching" isDownloading = "downloading" isVerifying = "verifying" isExtracting = "extracting" isInstalling = "installing" isVerifyingInstall = "verifying_install" isComplete = "complete" isFailed = "failed" ``` Installation state. #### `InstallResult` ```nim type InstallResult* = object success*: bool toolPath*: string version*: string message*: string errors*: seq[string] warnings*: seq[string] installTime*: Duration ``` Result of installation operation. #### `InstallationManager` ```nim type InstallationManager* = ref object toolsDir*: string tempDir*: string backupDir*: string ``` Manages tool installation. ### Procedures #### `newInstallationManager` ```nim proc newInstallationManager*(toolsDir: string = ""): InstallationManager ``` Create a new InstallationManager. **Parameters:** - `toolsDir` - Tools directory (default: XDG data) **Returns:** - `InstallationManager` instance **Example:** ```nim let manager = newInstallationManager() ``` #### `extractArchive` ```nim proc extractArchive*(im: InstallationManager, archivePath: string, destDir: string): tuple[success: bool, message: string] ``` Extract archive to destination directory. **Parameters:** - `im` - InstallationManager instance - `archivePath` - Path to archive file - `destDir` - Destination directory **Returns:** - Tuple of (success, message) **Example:** ```nim let (success, msg) = manager.extractArchive( "/tmp/archive.tar.xz", "/opt/tool" ) ``` #### `executeScript` ```nim proc executeScript*(im: InstallationManager, scriptPath: string, workDir: string, env: Table[string, string] = initTable[string, string]()): tuple[success: bool, output: string] ``` Execute installation script. **Parameters:** - `im` - InstallationManager instance - `scriptPath` - Path to script - `workDir` - Working directory - `env` - Environment variables **Returns:** - Tuple of (success, output) **Example:** ```nim let env = {"INSTALL_DIR": "/opt/tool"}.toTable let (success, output) = manager.executeScript( "install.sh", "/opt/tool", env ) ``` #### `verifyInstallation` ```nim proc verifyInstallation*(im: InstallationManager, toolType: string, verifyScript: string, toolPath: string): tuple[success: bool, message: string] ``` Verify tool installation. **Parameters:** - `im` - InstallationManager instance - `toolType` - Tool type - `verifyScript` - Path to verification script - `toolPath` - Tool installation path **Returns:** - Tuple of (success, message) **Example:** ```nim let (success, msg) = manager.verifyInstallation( "nix", "verify.sh", "/opt/nix" ) ``` #### `backupTool` ```nim proc backupTool*(im: InstallationManager, toolType: string): bool ``` Backup existing tool installation. **Parameters:** - `im` - InstallationManager instance - `toolType` - Tool type **Returns:** - `bool` - True if backup succeeded **Example:** ```nim if manager.backupTool("nix"): echo "Backup created" ``` #### `rollback` ```nim proc rollback*(im: InstallationManager, toolType: string): bool ``` Rollback failed installation. **Parameters:** - `im` - InstallationManager instance - `toolType` - Tool type **Returns:** - `bool` - True if rollback succeeded **Example:** ```nim if not installSuccess: discard manager.rollback("nix") ``` ## Module: bootstrap.nim Main bootstrap coordinator. ### Types #### `BuildToolType` ```nim type BuildToolType* = enum bttNix = "nix" bttPkgsrc = "pkgsrc" bttGentoo = "gentoo" ``` Supported build tool types. #### `BootstrapResult` ```nim type BootstrapResult* = object success*: bool toolPath*: string message*: string errors*: seq[string] warnings*: seq[string] ``` Result of bootstrap operation. ### Procedures #### `isToolInstalled` ```nim proc isToolInstalled*(toolType: BuildToolType): bool ``` Check if a build tool is installed in NIP's directory. **Parameters:** - `toolType` - Tool type to check **Returns:** - `bool` - True if installed **Example:** ```nim if isToolInstalled(bttNix): echo "Nix is installed" ``` #### `isSystemToolAvailable` ```nim proc isSystemToolAvailable*(toolType: BuildToolType): bool ``` Check if tool is available on the system. **Parameters:** - `toolType` - Tool type to check **Returns:** - `bool` - True if available **Example:** ```nim if isSystemToolAvailable(bttNix): echo "Nix is available on system" ``` #### `handleMissingTool` ```nim proc handleMissingTool*(toolType: BuildToolType, autoBootstrap: bool = false): bool ``` Handle missing build tool - prompt user or auto-bootstrap. **Parameters:** - `toolType` - Tool type - `autoBootstrap` - Auto-install without prompting **Returns:** - `bool` - True if tool is now available **Example:** ```nim if not isToolInstalled(bttNix): if handleMissingTool(bttNix, autoBootstrap = true): echo "Nix installed successfully" ``` #### `installMinimalTools` ```nim proc installMinimalTools*(toolType: BuildToolType): BootstrapResult ``` Install minimal build tools for the specified type. **Parameters:** - `toolType` - Tool type to install **Returns:** - `BootstrapResult` with status and details **Example:** ```nim let result = installMinimalTools(bttNix) if result.success: echo "Installed to: ", result.toolPath ``` ## Usage Examples ### Complete Installation Flow ```nim import nimpak/build/[bootstrap, recipe_manager, download_manager, installation_manager] # Initialize managers let recipeManager = newRecipeManager() let downloadManager = newDownloadManager() let installManager = newInstallationManager() defer: downloadManager.close() # Fetch recipes let fetchResult = recipeManager.fetchRecipes() if not fetchResult.success: echo "Failed to fetch recipes" quit(1) # Load recipe let recipeOpt = recipeManager.loadRecipe("nix") if recipeOpt.isNone(): echo "Recipe not found" quit(1) let recipe = recipeOpt.get() # Select platform let (arch, os) = getCurrentPlatform() let platformOpt = selectPlatform(recipe, arch, os) if platformOpt.isNone(): echo "Platform not supported" quit(1) let platform = platformOpt.get() # Download binaries for binary in platform.binaries: let destPath = downloadManager.getCachedFile(binary.name) let result = downloadManager.downloadFile(binary.url, destPath, binary.checksum) if not result.success: echo "Download failed: ", result.message quit(1) # Install let toolDir = "/opt/nix" let env = {"INSTALL_DIR": toolDir}.toTable let (success, output) = installManager.executeScript( recipe.install.script, toolDir, env ) if success: echo "Installation successful" else: echo "Installation failed: ", output ``` ## Error Handling All procedures that can fail return either: - `Option[T]` - Use `isSome()` and `get()` to check and extract - `tuple[success: bool, ...]` - Check `success` field - `Result` object with `success` field Always check return values and handle errors appropriately. ## Thread Safety The bootstrap system is not thread-safe. Do not use the same manager instances from multiple threads. ## See Also - [Bootstrap Guide](bootstrap-guide.md) - User documentation - [Recipe Authoring Guide](../recipes/AUTHORING-GUIDE.md) - Creating recipes - [Source Build Guide](source-build-guide.md) - Building from source