⚡ Zero-dependency plcbundle library exclusively for Bun
at main 8.8 kB view raw
1/** 2 * Type definitions for plcbundle library 3 * 4 * This module contains all TypeScript type definitions used throughout 5 * the plcbundle library. 6 * 7 * @module 8 */ 9 10/** 11 * Metadata for a single bundle in the repository. 12 * 13 * Contains information about the bundle's contents, hashes for verification, 14 * and temporal boundaries. 15 */ 16export interface BundleMetadata { 17 /** Sequential number identifying this bundle (e.g., 1, 2, 3...) */ 18 bundle_number: number; 19 20 /** ISO 8601 timestamp of the first operation in this bundle */ 21 start_time: string; 22 23 /** ISO 8601 timestamp of the last operation in this bundle */ 24 end_time: string; 25 26 /** Total number of PLC operations contained in this bundle */ 27 operation_count: number; 28 29 /** Number of unique DIDs referenced in this bundle */ 30 did_count: number; 31 32 /** Chain hash linking this bundle to its predecessor */ 33 hash: string; 34 35 /** SHA-256 hash of the uncompressed JSONL content */ 36 content_hash: string; 37 38 /** Chain hash of the previous bundle (empty string for genesis bundle) */ 39 parent: string; 40 41 /** SHA-256 hash of the compressed .jsonl.zst file */ 42 compressed_hash: string; 43 44 /** Size of the compressed bundle file in bytes */ 45 compressed_size: number; 46 47 /** Size of the uncompressed JSONL content in bytes */ 48 uncompressed_size: number; 49 50 /** Cursor for fetching subsequent operations (end_time of previous bundle) */ 51 cursor: string; 52 53 /** ISO 8601 timestamp when this bundle was created */ 54 created_at: string; 55} 56 57/** 58 * Index file containing metadata for all bundles in a repository. 59 * 60 * This is the main entry point for discovering available bundles. 61 * Located at `plc_bundles.json` in the repository root. 62 */ 63export interface BundleIndex { 64 /** Version of the index format (currently "1.0") */ 65 version: string; 66 67 /** Bundle number of the most recent bundle */ 68 last_bundle: number; 69 70 /** ISO 8601 timestamp when the index was last updated */ 71 updated_at: string; 72 73 /** Total size of all compressed bundles in bytes */ 74 total_size_bytes: number; 75 76 /** Array of metadata for each bundle, sorted by bundle_number */ 77 bundles: BundleMetadata[]; 78} 79 80/** 81 * A single PLC operation as stored in bundles. 82 * 83 * Operations represent changes to DID documents in the PLC directory. 84 */ 85export interface Operation { 86 /** Decentralized Identifier (DID) this operation applies to */ 87 did: string; 88 89 /** Content Identifier (CID) of this operation */ 90 cid: string; 91 92 /** The actual operation data containing DID document changes */ 93 operation: any; 94 95 /** ISO 8601 timestamp when this operation was created */ 96 createdAt: string; 97 98 /** Additional fields that may be present in operations */ 99 [key: string]: any; 100} 101 102/** 103 * Callback function called for each operation during processing. 104 * 105 * @param op - The operation being processed 106 * @param position - Zero-based position of the operation within its bundle 107 * @param bundleNum - The bundle number being processed 108 * @param line - The raw JSONL line (for getting size without re-serializing) 109 */ 110export type ProcessCallback = ( 111 op: Operation, 112 position: number, 113 bundleNum: number, 114 line: string 115) => void | Promise<void>; 116 117/** 118 * Statistics collected during bundle processing. 119 * 120 * Tracks the number of operations and bytes processed. 121 */ 122export interface ProcessStats { 123 /** Total number of operations processed */ 124 totalOps: number; 125 126 /** Number of operations that matched criteria (if applicable) */ 127 matchCount: number; 128 129 /** Total bytes of operation data processed */ 130 totalBytes: number; 131 132 /** Bytes of data for matched operations (if applicable) */ 133 matchedBytes: number; 134} 135 136/** 137 * Unified options for processing bundles. 138 * 139 * Supports both callback functions (single-threaded) and module paths (multi-threaded). 140 */ 141export interface ProcessOptions { 142 /** 143 * Number of worker threads (default: 1). 144 * If > 1, requires `module` instead of passing callback directly. 145 */ 146 threads?: number; 147 148 /** 149 * Path to module exporting a `detect` or default function. 150 * Required when threads > 1. The module should export: 151 * ```ts 152 * export function detect({ op }) { return [...labels]; } 153 * ``` 154 */ 155 module?: string; 156 157 /** 158 * Suppress all console output from the detect script (default: false). 159 * 160 * When enabled, console.log, console.error, etc. from the detect function 161 * are silenced. Progress reporting and final statistics are still shown. 162 * 163 * @example 164 * ```ts 165 * await bundle.processBundles(1, 10, { 166 * module: './noisy-detect.ts', 167 * silent: true // Suppress debug output 168 * }); 169 * ``` 170 */ 171 silent?: boolean; 172 173 /** 174 * Output matches immediately without buffering or sorting (default: false). 175 * 176 * When enabled, matches are output as soon as they're found rather than 177 * being collected, sorted, and output at the end. Useful for: 178 * - Real-time streaming output 179 * - Reducing memory usage with large result sets 180 * - Early access to results 181 * 182 * Note: With flush enabled, matches may be out of chronological order 183 * when using multiple threads. 184 * 185 * @example 186 * ```ts 187 * await bundle.processBundles(1, 100, { 188 * module: './detect.ts', 189 * threads: 4, 190 * flush: true, 191 * onMatch: (match) => { 192 * console.log(`Found: ${match.bundle}/${match.position}`); 193 * } 194 * }); 195 * ``` 196 */ 197 flush?: boolean; 198 199 /** 200 * Progress callback invoked periodically during processing. 201 * 202 * Called approximately every 10,000 operations to report current 203 * processing statistics. 204 * 205 * @param stats - Current processing statistics 206 * 207 * @example 208 * ```ts 209 * await bundle.processBundles(1, 100, callback, { 210 * onProgress: (stats) => { 211 * console.log(`${stats.totalOps} operations processed`); 212 * } 213 * }); 214 * ``` 215 */ 216 onProgress?: (stats: ProcessStats) => void; 217 218 /** 219 * Match callback invoked for each match when flush mode is enabled. 220 * 221 * Only called when `flush: true`. Receives match objects as they're 222 * found, without waiting for sorting. Ignored in non-flush mode. 223 * 224 * @param match - The match object with bundle, position, cid, size, and labels 225 * 226 * @example 227 * ```ts 228 * await bundle.processBundles(1, 100, { 229 * module: './detect.ts', 230 * flush: true, 231 * onMatch: (match) => { 232 * // Output immediately 233 * console.log(`${match.bundle},${match.position},${match.labels}`); 234 * } 235 * }); 236 * ``` 237 */ 238 onMatch?: (match: any) => void; 239} 240 241/** 242 * Options for cloning bundles from a remote repository. 243 * 244 * Controls download behavior, verification, and progress reporting. 245 */ 246export interface CloneOptions { 247 /** Number of parallel download threads (default: 4) */ 248 threads?: number; 249 250 /** 251 * Bundle selection specification. 252 * 253 * Can be: 254 * - A single bundle number: `"42"` 255 * - A range: `"1-100"` 256 * - Undefined to clone all available bundles 257 */ 258 bundles?: string; 259 260 /** Whether to verify SHA-256 hashes of downloaded bundles (default: true) */ 261 verify?: boolean; 262 263 /** 264 * Function to check if cloning should stop (for graceful shutdown). 265 * 266 * @returns `true` if cloning should stop, `false` to continue 267 */ 268 shouldStop?: () => boolean; 269 270 /** 271 * Callback invoked to report download progress. 272 * 273 * @param stats - Current download statistics 274 */ 275 onProgress?: (stats: CloneStats) => void; 276} 277 278/** 279 * Statistics collected during bundle cloning. 280 * 281 * Tracks download progress, including successes, skips, and failures. 282 */ 283export interface CloneStats { 284 /** Total number of bundles to download */ 285 totalBundles: number; 286 287 /** Number of bundles successfully downloaded in this session */ 288 downloadedBundles: number; 289 290 /** Number of bundles skipped (already existed and verified) */ 291 skippedBundles: number; 292 293 /** Number of bundles that failed to download */ 294 failedBundles: number; 295 296 /** Total bytes to download across all bundles */ 297 totalBytes: number; 298 299 /** Bytes downloaded so far (including skipped bundles) */ 300 downloadedBytes: number; 301} 302 303/** 304 * Result of chain verification. 305 * 306 * Contains overall validity status and detailed information about 307 * any issues found in the bundle chain. 308 */ 309export interface ChainVerificationResult { 310 /** Whether the entire chain is valid */ 311 valid: boolean; 312 313 /** Total number of bundles verified */ 314 totalBundles: number; 315 316 /** Number of bundles that passed verification */ 317 validBundles: number; 318 319 /** Number of bundles that failed verification */ 320 invalidBundles: number; 321 322 /** Detailed errors for each invalid bundle */ 323 errors: Array<{ 324 bundleNum: number; 325 errors: string[]; 326 }>; 327}