@@ -41,6 +41,90 @@ export interface DlxBinaryResult {
4141 spawnPromise : ReturnType < typeof spawn >
4242}
4343
44+ /**
45+ * Metadata structure for cached binaries (.dlx-metadata.json).
46+ * Unified schema shared across TypeScript (dlxBinary) and C++ (socket_macho_decompress).
47+ *
48+ * Core Fields (present in all implementations):
49+ * - version: Schema version (currently "1.0.0")
50+ * - cache_key: First 16 chars of SHA-512 hash (matches directory name)
51+ * - timestamp: Unix timestamp in milliseconds
52+ * - checksum: Full hash of cached binary (SHA-512 for C++, SHA-256 for TypeScript)
53+ * - checksum_algorithm: "sha512" or "sha256"
54+ * - platform: "darwin" | "linux" | "win32"
55+ * - arch: "x64" | "arm64"
56+ * - size: Size of cached binary in bytes
57+ * - source: Origin information
58+ * - type: "download" (from URL) or "decompression" (from embedded binary)
59+ * - url: Download URL (if type is "download")
60+ * - path: Source binary path (if type is "decompression")
61+ *
62+ * Extra Fields (implementation-specific):
63+ * - For C++ decompression:
64+ * - compressed_size: Size of compressed data in bytes
65+ * - compression_algorithm: Brotli level (numeric)
66+ * - compression_ratio: original_size / compressed_size
67+ *
68+ * Example (TypeScript download):
69+ * ```json
70+ * {
71+ * "version": "1.0.0",
72+ * "cache_key": "a1b2c3d4e5f67890",
73+ * "timestamp": 1730332800000,
74+ * "checksum": "sha256-abc123...",
75+ * "checksum_algorithm": "sha256",
76+ * "platform": "darwin",
77+ * "arch": "arm64",
78+ * "size": 15000000,
79+ * "source": {
80+ * "type": "download",
81+ * "url": "https://example.com/binary"
82+ * }
83+ * }
84+ * ```
85+ *
86+ * Example (C++ decompression):
87+ * ```json
88+ * {
89+ * "version": "1.0.0",
90+ * "cache_key": "0123456789abcdef",
91+ * "timestamp": 1730332800000,
92+ * "checksum": "sha512-def456...",
93+ * "checksum_algorithm": "sha512",
94+ * "platform": "darwin",
95+ * "arch": "arm64",
96+ * "size": 13000000,
97+ * "source": {
98+ * "type": "decompression",
99+ * "path": "/usr/local/bin/socket"
100+ * },
101+ * "extra": {
102+ * "compressed_size": 1700000,
103+ * "compression_algorithm": 3,
104+ * "compression_ratio": 7.647
105+ * }
106+ * }
107+ * ```
108+ *
109+ * @internal This interface documents the metadata file format.
110+ */
111+ export interface DlxMetadata {
112+ version : string
113+ cache_key : string
114+ timestamp : number
115+ checksum : string
116+ checksum_algorithm : string
117+ platform : string
118+ arch : string
119+ size : number
120+ source ?: {
121+ type : 'download' | 'decompression'
122+ url ?: string
123+ path ?: string
124+ }
125+ extra ?: Record < string , unknown >
126+ }
127+
44128/**
45129 * Get metadata file path for a cached binary.
46130 */
@@ -153,20 +237,32 @@ async function downloadBinaryFile(
153237
154238/**
155239 * Write metadata for a cached binary.
240+ * Uses unified schema shared with C++ decompressor and CLI dlxBinary.
241+ * Schema documentation: See DlxMetadata interface in this file (exported).
242+ * Core fields: version, cache_key, timestamp, checksum, checksum_algorithm, platform, arch, size, source
243+ * Note: This implementation uses SHA-256 checksums instead of SHA-512.
156244 */
157245async function writeMetadata (
158246 cacheEntryPath : string ,
247+ cacheKey : string ,
159248 url : string ,
160249 checksum : string ,
250+ size : number ,
161251) : Promise < void > {
162252 const metaPath = getMetadataPath ( cacheEntryPath )
163253 const metadata = {
164- arch : os . arch ( ) ,
254+ version : '1.0.0' ,
255+ cache_key : cacheKey ,
256+ timestamp : Date . now ( ) ,
165257 checksum,
258+ checksum_algorithm : 'sha256' ,
166259 platform : os . platform ( ) ,
167- timestamp : Date . now ( ) ,
168- url,
169- version : '1.0.0' ,
260+ arch : os . arch ( ) ,
261+ size,
262+ source : {
263+ type : 'download' ,
264+ url,
265+ } ,
170266 }
171267 await fs . writeFile ( metaPath , JSON . stringify ( metadata , null , 2 ) )
172268}
@@ -325,7 +421,16 @@ export async function dlxBinary(
325421
326422 // Download the binary.
327423 computedChecksum = await downloadBinaryFile ( url , binaryPath , checksum )
328- await writeMetadata ( cacheEntryDir , url , computedChecksum || '' )
424+
425+ // Get file size for metadata.
426+ const stats = await fs . stat ( binaryPath )
427+ await writeMetadata (
428+ cacheEntryDir ,
429+ cacheKey ,
430+ url ,
431+ computedChecksum || '' ,
432+ stats . size ,
433+ )
329434 }
330435
331436 // Execute the binary.
@@ -431,7 +536,16 @@ export async function downloadBinary(
431536
432537 // Download the binary.
433538 const computedChecksum = await downloadBinaryFile ( url , binaryPath , checksum )
434- await writeMetadata ( cacheEntryDir , url , computedChecksum || '' )
539+
540+ // Get file size for metadata.
541+ const stats = await fs . stat ( binaryPath )
542+ await writeMetadata (
543+ cacheEntryDir ,
544+ cacheKey ,
545+ url ,
546+ computedChecksum || '' ,
547+ stats . size ,
548+ )
435549 downloaded = true
436550 }
437551
@@ -537,6 +651,14 @@ export async function listDlxCache(): Promise<
537651 continue
538652 }
539653
654+ const metaObj = metadata as Record < string , unknown >
655+
656+ // Get URL from unified schema (source.url) or legacy schema (url).
657+ // Allow empty URL for backward compatibility with partial metadata.
658+ const source = metaObj [ 'source' ] as Record < string , unknown > | undefined
659+ const url =
660+ ( source ?. [ 'url' ] as string ) || ( metaObj [ 'url' ] as string ) || ''
661+
540662 // Find the binary file in the directory.
541663 // eslint-disable-next-line no-await-in-loop
542664 const files = await fs . readdir ( entryPath )
@@ -547,15 +669,14 @@ export async function listDlxCache(): Promise<
547669 // eslint-disable-next-line no-await-in-loop
548670 const binaryStats = await fs . stat ( binaryPath )
549671
550- const metaObj = metadata as Record < string , unknown >
551672 results . push ( {
552673 age : now - ( ( metaObj [ 'timestamp' ] as number ) || 0 ) ,
553674 arch : ( metaObj [ 'arch' ] as string ) || 'unknown' ,
554675 checksum : ( metaObj [ 'checksum' ] as string ) || '' ,
555676 name : binaryFile ,
556677 platform : ( metaObj [ 'platform' ] as string ) || 'unknown' ,
557678 size : binaryStats . size ,
558- url : ( metaObj [ 'url' ] as string ) || '' ,
679+ url,
559680 } )
560681 }
561682 } catch { }
0 commit comments