{"version":3,"file":"index.cjs","names":["charset: string | undefined","requestHeaders: Record<string, string>","body: ReadableStream | string","content: string","Agent","result: Record<string, Record<string, boolean>>","fsPromises","host: string","hostPart: string","hostPortPart: string","Client","Socket","stream","tlsOptions: SecureContextOptions","fsPromises","Writable","agent: SocketAgent","fsPromises","certificates: string | undefined","os","Writable","headers: Record<string, string>","Writable","headers: Record<string, string>","fetchOptions: UndiciRequestInit","challenge: { realm?: string; service?: string; scope?: string }","detail: any"],"sources":["../lib/types/FileInfo.ts","../lib/http.ts","../lib/socket.ts","../lib/filter.ts","../lib/ssh.ts","../lib/util.ts","../lib/tls.ts","../lib/multiplexed-stream.ts","../lib/json-stream.ts","../lib/docker-client.ts","../lib/logs.ts","../lib/registry.ts"],"sourcesContent":["export class FileInfo {\n    name: string;\n    size: number;\n    mode: number;\n    mtime: Date;\n    linkTarget: string;\n\n    constructor(\n        name: string,\n        size: number,\n        mode: number,\n        mtime: Date,\n        linkTarget: string,\n    ) {\n        this.name = name;\n        this.size = size;\n        this.mode = mode;\n        this.mtime = mtime;\n        this.linkTarget = linkTarget;\n    }\n\n    static fromJSON(s: string): FileInfo {\n        const json = JSON.parse(s);\n        return new FileInfo(\n            json.name,\n            json.size,\n            json.mode,\n            new Date(json.mtime),\n            json.linkTarget,\n        );\n    }\n}\n","import type { IncomingMessage } from 'node:http';\nimport type { ReadableStream } from 'stream/web';\nimport { Agent, Response, fetch, upgrade } from 'undici';\nimport { Duplex } from 'stream';\n\n// Docker stream content type constants\nexport const DOCKER_RAW_STREAM = 'application/vnd.docker.raw-stream';\nexport const DOCKER_MULTIPLEXED_STREAM =\n    'application/vnd.docker.multiplexed-stream';\nexport const APPLICATION_JSON = 'application/json';\nexport const APPLICATION_NDJSON = 'application/x-ndjson';\n\n// Custom error class for 404 Not Found responses\nexport class NotFoundError extends Error {\n    constructor(message: string) {\n        super(message);\n        this.name = 'NotFoundError';\n    }\n}\n\n// Custom error class for 401 Unauthorized responses\nexport class UnauthorizedError extends Error {\n    constructor(message: string) {\n        super(message);\n        this.name = 'UnauthorizedError';\n    }\n}\n\n// Custom error class for 409 Conflict responses\nexport class ConflictError extends Error {\n    constructor(message: string) {\n        super(message);\n        this.name = 'ConflictError';\n    }\n}\n\n// Function to parse content-type header and extract charset parameter\nfunction _parseContentType(contentType?: string): {\n    type: string;\n    charset?: string;\n} {\n    if (!contentType) {\n        return { type: '' };\n    }\n\n    const parts = contentType.split(';').map((part) => part.trim());\n    const type = parts[0]?.toLowerCase() || '';\n\n    let charset: string | undefined;\n    for (let i = 1; i < parts.length; i++) {\n        const param = parts[i]?.toLowerCase() || '';\n        if (param.startsWith('charset=')) {\n            charset = param.split('=')[1];\n            break;\n        }\n    }\n\n    return { type, charset };\n}\n\n// Function to extract error message from response body\nfunction _getErrorMessageFromResp(\n    res: IncomingMessage,\n    body: string | undefined,\n): string | undefined {\n    const contentType = res.headers['content-type']?.toLowerCase();\n    if (contentType?.includes(APPLICATION_JSON) && body) {\n        const jsonBody = JSON.parse(body);\n        if (jsonBody.message) {\n            return jsonBody.message as string;\n        }\n    }\n    return res.statusMessage;\n}\n\n/**\n * HTTPClient provides HTTP communication capabilities over TCP sockets.\n * Supports GET, POST, and DELETE requests with query parameters and request bodies.\n * Handles chunked transfer encoding and provides streaming response callbacks.\n */\nexport class HTTPClient {\n    private agent: Agent;\n    private headers: Record<string, string>;\n    private baseUrl: string;\n\n    constructor(\n        agent: Agent,\n        userAgent: string,\n        headers?: Record<string, string>,\n    ) {\n        this.agent = agent;\n        this.headers = headers || {};\n        this.headers['User-Agent'] = userAgent;\n        this.baseUrl = 'http://localhost:2375';\n    }\n\n    close(): Promise<void> {\n        return this.agent.destroy();\n    }\n\n    // Method to send an HTTP request with method, URI and parameters\n    public sendHTTPRequest(\n        _method: string,\n        _uri: string,\n        _options?: {\n            params?: Record<string, any>;\n            data?: any;\n            callback?: (data: Buffer, encoding?: BufferEncoding) => void;\n            accept?: string;\n            headers?: Record<string, string>;\n        },\n    ): Promise<Response> {\n        throw new Error('sendHTTPRequest method not implemented');\n    }\n\n    private buildQueryString(params?: Record<string, any>): string {\n        if (!params || Object.keys(params).length === 0) {\n            return '';\n        }\n\n        const searchParams = new URLSearchParams();\n        Object.entries(params).forEach(([key, value]) => {\n            if (value !== undefined && value !== null) {\n                if (\n                    value &&\n                    typeof value === 'object' &&\n                    typeof value.toURLParameter === 'function'\n                ) {\n                    searchParams.append(key, value.toURLParameter());\n                } else {\n                    searchParams.append(key, String(value));\n                }\n            }\n        });\n\n        const queryString = searchParams.toString();\n        return queryString ? `?${queryString}` : '';\n    }\n\n    public async head(\n        uri: string,\n        params?: Record<string, any>,\n    ): Promise<Response> {\n        const queryString = this.buildQueryString(params);\n        return fetch(`${this.baseUrl}${uri}${queryString}`, {\n            method: 'HEAD',\n            headers: this.headers,\n            dispatcher: this.agent,\n        });\n    }\n\n    public async get(\n        uri: string,\n        accept: string,\n        params?: Record<string, any>,\n    ): Promise<Response> {\n        const queryString = this.buildQueryString(params);\n        return fetch(`${this.baseUrl}${uri}${queryString}`, {\n            method: 'GET',\n            headers: {\n                Accept: accept,\n                ...this.headers,\n            },\n            dispatcher: this.agent,\n        });\n    }\n\n    public getJSON<T>(uri: string, params?: Record<string, any>): Promise<T> {\n        return this.get(uri, APPLICATION_JSON, params).then((response) => {\n            if (response.status === 404) {\n                throw NotFoundError;\n            }\n            return response.json() as T;\n        });\n    }\n\n    public async post(\n        uri: string,\n        params?: Record<string, any>,\n        data?: object | ReadableStream,\n        headers?: Record<string, string>,\n    ): Promise<Response> {\n        const queryString = this.buildQueryString(params);\n        const requestHeaders: Record<string, string> = {\n            'Content-Type': APPLICATION_JSON,\n            ...headers,\n            ...this.headers,\n        };\n        let body: ReadableStream | string = '';\n        if (data) {\n            if (isReadableStream(data)) {\n                body = data;\n            } else {\n                body = JSON.stringify(data);\n            }\n        }\n\n        return fetch(`${this.baseUrl}${uri}${queryString}`, {\n            method: 'POST',\n            headers: requestHeaders,\n            body: body,\n            duplex: 'half',\n            dispatcher: this.agent,\n        });\n    }\n\n    public async put(\n        uri: string,\n        params: Record<string, any>,\n        data: object,\n        type: string,\n    ): Promise<Response> {\n        const queryString = this.buildQueryString(params);\n        return fetch(`${this.baseUrl}${uri}${queryString}`, {\n            method: 'PUT',\n            headers: {\n                'Content-Type': type,\n                ...this.headers,\n            },\n            body: JSON.stringify(data),\n            dispatcher: this.agent,\n        });\n    }\n\n    public async delete(\n        uri: string,\n        params?: Record<string, any>,\n    ): Promise<Response> {\n        const queryString = this.buildQueryString(params);\n        return fetch(`${this.baseUrl}${uri}${queryString}`, {\n            method: 'DELETE',\n            headers: this.headers,\n            dispatcher: this.agent,\n        });\n    }\n\n    public async upgrade(\n        uri: string,\n        params?: Record<string, any>,\n    ): Promise<Upgrade> {\n        const queryString = this.buildQueryString(params);\n        const { headers, socket } = await upgrade(\n            `${this.baseUrl}${uri}${queryString}`,\n            {\n                method: 'POST',\n                headers: this.headers,\n                dispatcher: this.agent,\n                protocol: 'tcp',\n            },\n        );\n        const header = headers['content-type'] || '';\n        let content: string;\n        if (Array.isArray(header)) {\n            content = header[0] || '';\n        } else {\n            content = header;\n        }\n\n        return {\n            content: content,\n            socket: socket,\n        };\n    }\n}\n\ninterface Upgrade {\n    content: string;\n    socket: Duplex;\n}\n\nfunction isReadableStream(data: any): data is ReadableStream {\n    return 'getReader' in data && typeof data.getReader === 'function';\n}\n","import { Agent } from 'undici';\nimport { type Socket } from 'node:net';\n\n/**\n * HTTP Agent that creates socket connections using a provided factory function.\n * This allows flexible socket creation strategies while supporting connection pooling.\n */\nexport class SocketAgent extends Agent {\n    constructor(createSocketFn: () => Socket) {\n        super({\n            connect: (options, callback) => {\n                const socket = createSocketFn();\n\n                socket.on('connect', () => {\n                    callback(null, socket);\n                });\n\n                socket.on('error', (err) => {\n                    callback(err, null);\n                });\n\n                return socket;\n            },\n        });\n    }\n}\n","export class Filter {\n    private data: Map<string, Set<string>> = new Map();\n    set(key: string, values: string[]): this {\n        this.data.set(key, new Set(values));\n        return this;\n    }\n\n    add(key: string, value: string): this {\n        if (!this.data.has(key)) {\n            this.data.set(key, new Set());\n        }\n        this.data.get(key)!.add(value);\n        return this;\n    }\n\n    get(key: string): string[] {\n        const values = this.data.get(key);\n        return values ? Array.from(values) : [];\n    }\n\n    has(key: string): boolean {\n        return this.data.has(key);\n    }\n\n    keys(): string[] {\n        return Array.from(this.data.keys());\n    }\n\n    toJSON(): Record<string, Record<string, boolean>> {\n        const result: Record<string, Record<string, boolean>> = {};\n\n        for (const [key, values] of this.data) {\n            result[key] = {};\n            for (const value of values) {\n                result[key][value] = true;\n            }\n        }\n\n        return result;\n    }\n\n    toURLParameter(): string {\n        return JSON.stringify(this.toJSON());\n    }\n}\n","import { Socket } from 'node:net';\nimport { promises as fsPromises } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { Client } from 'ssh2';\n\n/**\n * SSH connection utilities for Docker remote access\n */\nexport class SSH {\n    /**\n     * Get SSH private key from common locations\n     * @returns SSH private key buffer or undefined\n     */\n    private static async getPrivateKey(): Promise<Buffer | undefined> {\n        const keyPaths = [\n            join(homedir(), '.ssh', 'id_rsa'),\n            join(homedir(), '.ssh', 'id_ed25519'),\n            join(homedir(), '.ssh', 'id_ecdsa'),\n        ];\n\n        for (const keyPath of keyPaths) {\n            try {\n                return await fsPromises.readFile(keyPath);\n            } catch (err) {\n                // Continue to next key\n            }\n        }\n\n        return undefined;\n    }\n\n    /**\n     * Create a socket factory function for SSH connections that can be used with SocketAgent\n     * @param sshHost SSH host string (e.g., \"ssh://user@host:22/var/run/docker.sock\")\n     * @returns Function that creates new SSH socket connections\n     */\n    static async createSocketFactory(sshHost: string): Promise<() => Socket> {\n        // Preload the private key asynchronously\n        const privateKey = await SSH.getPrivateKey();\n\n        // Parse SSH connection parameters once\n        const sshUrl = sshHost.substring(6); // Remove \"ssh://\" prefix\n\n        let user = 'root'; // Default user\n        let host: string;\n        let port = 22; // Default SSH port\n        let socketPath = '/var/run/docker.sock'; // Default Docker socket path\n\n        // Parse user@host part\n        const atIndex = sshUrl.indexOf('@');\n        let hostPart: string;\n\n        if (atIndex !== -1) {\n            user = sshUrl.substring(0, atIndex);\n            hostPart = sshUrl.substring(atIndex + 1);\n        } else {\n            hostPart = sshUrl;\n        }\n\n        // Parse host:port/path part\n        const slashIndex = hostPart.indexOf('/');\n        let hostPortPart: string;\n\n        if (slashIndex !== -1) {\n            hostPortPart = hostPart.substring(0, slashIndex);\n            socketPath = hostPart.substring(slashIndex);\n        } else {\n            hostPortPart = hostPart;\n        }\n\n        // Parse host:port part\n        const colonIndex = hostPortPart.lastIndexOf(':');\n        if (colonIndex !== -1) {\n            host = hostPortPart.substring(0, colonIndex);\n            port = parseInt(hostPortPart.substring(colonIndex + 1)) || 22;\n        } else {\n            host = hostPortPart;\n        }\n\n        // Return factory function that creates new SSH connections\n        return () => {\n            const conn = new Client();\n            const sshStream = new Socket();\n\n            conn.on('ready', () => {\n                // Create a Unix socket connection through SSH\n                conn.openssh_forwardOutStreamLocal(\n                    socketPath,\n                    (err, stream) => {\n                        if (err) {\n                            conn.end();\n                            sshStream.emit(\n                                'error',\n                                new Error(\n                                    `Failed to create SSH tunnel to ${socketPath}: ${err.message}`,\n                                ),\n                            );\n                            return;\n                        }\n\n                        // Pipe the SSH stream to our socket wrapper\n                        stream.pipe(sshStream);\n                        sshStream.pipe(stream);\n\n                        // Handle SSH connection cleanup\n                        sshStream.on('close', () => {\n                            conn.end();\n                        });\n\n                        sshStream.emit('connect');\n                    },\n                );\n            });\n\n            conn.on('error', (err) => {\n                sshStream.emit(\n                    'error',\n                    new Error(\n                        `SSH connection failed to ${user}@${host}:${port}: ${err.message}`,\n                    ),\n                );\n            });\n\n            // Connect using SSH key authentication (preloaded key)\n            conn.connect({\n                host,\n                port,\n                username: user,\n                privateKey: privateKey,\n                tryKeyboard: true,\n            });\n\n            return sshStream;\n        };\n    }\n}\n","function isObject(value: unknown): value is object {\n    return value !== null && typeof value === 'object';\n}\n\nexport function isFileNotFoundError(error: unknown): boolean {\n    return isObject(error) && 'code' in error && error.code === 'ENOENT';\n}\n\nexport function getErrorMessage(error: unknown): string | undefined {\n    if (!error) {\n        return;\n    }\n    if (typeof error === 'string') {\n        return error;\n    }\n    if (error instanceof Error) {\n        return error.message;\n    }\n    if (\n        isObject(error) &&\n        'message' in error &&\n        typeof error.message === 'string'\n    ) {\n        return error.message;\n    }\n    return;\n}\n\nexport function parseIntWithDefault(\n    value: string | undefined,\n    defaultValue: number,\n): number {\n    if (value === undefined) {\n        return defaultValue;\n    }\n    const number = parseInt(value);\n    return Number.isNaN(number) ? defaultValue : number;\n}\n\nexport function parseDockerHost(\n    dockerHost: string,\n    defaultPort: number,\n): { host: string; port: number } {\n    const tcpAddress = dockerHost.substring(6); // Remove \"tcp://\" prefix\n    const [host, portStr] = tcpAddress.split(':');\n    if (!host) {\n        throw new Error(`Invalid Docker host: ${dockerHost}`);\n    }\n    const port = parseIntWithDefault(portStr, defaultPort);\n    return { host, port };\n}\n","import { promises as fsPromises } from 'node:fs';\nimport { join } from 'node:path';\nimport { getErrorMessage } from './util.js';\nimport type { SecureContextOptions } from 'node:tls';\n\n/**\n * TLS certificate utilities for secure Docker connections\n */\nexport class TLS {\n    /**\n     * Load TLS certificates from a directory\n     * @param certPath Path to directory containing ca.pem, cert.pem, and key.pem files\n     * @returns TLS options object for HTTPS agent\n     */\n    static async loadCertificates(\n        certPath: string,\n    ): Promise<SecureContextOptions> {\n        const tlsOptions: SecureContextOptions = {};\n\n        try {\n            // Load CA certificate\n            const caPath = join(certPath, 'ca.pem');\n            try {\n                tlsOptions.ca = await fsPromises.readFile(caPath);\n            } catch {\n                // CA certificate is optional\n            }\n\n            // Load client certificate\n            const certPemPath = join(certPath, 'cert.pem');\n            try {\n                tlsOptions.cert = await fsPromises.readFile(certPemPath);\n            } catch {\n                // Client certificate is optional\n            }\n\n            // Load client private key\n            const keyPath = join(certPath, 'key.pem');\n            try {\n                tlsOptions.key = await fsPromises.readFile(keyPath);\n            } catch {\n                // Private key is optional\n            }\n\n            return tlsOptions;\n        } catch (error) {\n            throw new Error(\n                `Failed to load TLS certificates from ${certPath}: ${getErrorMessage(error)}`,\n                { cause: error },\n            );\n        }\n    }\n}\n","import { Writable } from 'node:stream';\nimport stream from 'node:stream';\n\nexport function demultiplexStream(\n    stdout: NodeJS.WritableStream,\n    stderr: NodeJS.WritableStream,\n): stream.Writable {\n    let buffer = new Uint8Array(0);\n\n    return new Writable({\n        write(\n            chunk: any,\n            encoding: BufferEncoding,\n            cb: (error?: Error | null) => void,\n        ) {\n            try {\n                // Convert chunk to Uint8Array if needed\n                const data =\n                    chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);\n\n                // Append new chunk data to buffer\n                const newBuffer = new Uint8Array(buffer.length + data.length);\n                newBuffer.set(buffer, 0);\n                newBuffer.set(data, buffer.length);\n                buffer = newBuffer;\n\n                // Process complete messages from buffer\n                while (buffer.length >= 8) {\n                    // Read first byte for stream destination\n                    const streamType = buffer[0];\n\n                    // Read last 4 bytes as content size (big endian uint32)\n                    const contentSize =\n                        (buffer[4]! << 24) |\n                        (buffer[5]! << 16) |\n                        (buffer[6]! << 8) |\n                        buffer[7]!;\n\n                    // Check if we have enough data for the complete message\n                    if (buffer.length >= 8 + contentSize) {\n                        // Extract content\n                        const content = buffer.slice(8, 8 + contentSize);\n\n                        // Send to appropriate stream\n                        if (streamType === 1) {\n                            stdout.write(Buffer.from(content));\n                        } else if (streamType === 2) {\n                            stderr.write(Buffer.from(content));\n                        }\n                        // Ignore other stream types\n\n                        // Remove processed message from buffer\n                        buffer = buffer.slice(8 + contentSize);\n                    } else {\n                        // Not enough data for complete message, wait for more\n                        break;\n                    }\n                }\n                cb();\n            } catch (error) {\n                cb(error as Error);\n            }\n        },\n    });\n}\n","import type { Response } from 'undici';\n\n// jsonMessages processes a response stream with newline-delimited JSON messages and yields each parsed message.\nexport async function* jsonMessages<T>(\n    response: Response,\n): AsyncGenerator<T, void, undefined> {\n    if (!response.body) {\n        throw new Error('No response body');\n    }\n\n    // Extract charset from Content-Type header, default to utf-8\n    const contentType = response.headers.get('content-type') || '';\n    const charsetMatch = contentType.match(/charset=([^;]+)/i);\n    let charset = 'utf-8';\n    if (charsetMatch && charsetMatch[1]) {\n        charset = charsetMatch[1].trim();\n    }\n\n    const reader = response.body.getReader();\n    const decoder = new TextDecoder(charset);\n    let buffer = '';\n\n    try {\n        while (true) {\n            const { done, value } = await reader.read();\n\n            if (done) {\n                break;\n            }\n\n            buffer += decoder.decode(value, { stream: true });\n            const lines = buffer.split('\\n');\n            buffer = lines.pop() || ''; // Keep the last incomplete line in buffer\n\n            for (const line of lines) {\n                const trimmedLine = line.trim();\n                if (trimmedLine !== '') {\n                    try {\n                        yield JSON.parse(trimmedLine) as T;\n                    } catch (error) {\n                        console.warn(\n                            'Failed to parse JSON line:',\n                            trimmedLine,\n                            error,\n                        );\n                    }\n                }\n            }\n        }\n\n        // Process any remaining data in buffer\n        if (buffer.trim() !== '') {\n            try {\n                yield JSON.parse(buffer.trim()) as T;\n            } catch (error) {\n                console.warn('Failed to parse final JSON line:', buffer, error);\n            }\n        }\n    } finally {\n        reader.releaseLock();\n    }\n}\n","import { createConnection } from 'node:net';\nimport { promises as fsPromises } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { Agent } from 'undici';\nimport type { SecureContextOptions } from 'node:tls';\nimport { connect as tlsConnect } from 'node:tls';\nimport type { AuthConfig, JSONMessage, Platform } from './types/index.js';\nimport * as types from './types/index.js';\nimport {\n    APPLICATION_JSON,\n    APPLICATION_NDJSON,\n    DOCKER_MULTIPLEXED_STREAM,\n    DOCKER_RAW_STREAM,\n    HTTPClient,\n} from './http.js';\nimport { SocketAgent } from './socket.js';\nimport { Filter } from './filter.js';\nimport { SSH } from './ssh.js';\nimport { TLS } from './tls.js';\n\nimport * as stream from 'node:stream';\nimport { demultiplexStream } from './multiplexed-stream.js';\nimport {\n    getErrorMessage,\n    isFileNotFoundError,\n    parseDockerHost,\n} from './util.js';\nimport { WritableStream } from 'node:stream/web';\nimport { ReadableStream } from 'stream/web';\nimport { jsonMessages } from './json-stream.js';\nimport { Writable } from 'node:stream';\nimport * as os from 'node:os';\n\nexport class DockerClient {\n    private api: HTTPClient;\n\n    /**\n     * Create a new DockerClient instance\n     * You should use the static fromDockerHost or fromDockerConfig methods instead\n     * @param agent Undici agent for HTTP connections\n     * @param userAgent User agent string for requests (defaults to 'docker/node-sdk')\n     * @param headers Optional additional headers to include in requests\n     */\n    constructor(\n        agent: Agent,\n        userAgent: string = 'docker/node-sdk',\n        headers?: Record<string, string>,\n    ) {\n        this.api = new HTTPClient(agent, userAgent, headers);\n    }\n\n    /**\n     * Create a DockerClient instance from a Docker host string\n     * @param dockerHost Docker host string (e.g., \"unix:/var/run/docker.sock\", \"tcp://localhost:2376\", \"ssh://user@host[:port][/path/to/docker.sock]\", or \"/var/run/docker.sock\")\n     * @param certificates Optional path to directory containing TLS certificates (ca.pem, cert.pem, key.pem) for TCP connections\n     * @returns Promise that resolves to a connected DockerClient instance\n     */\n    static async fromDockerHost(\n        dockerHost: string,\n        certificates?: string | SecureContextOptions,\n        userAgent?: string,\n        headers?: Record<string, string>,\n    ): Promise<DockerClient> {\n        if (dockerHost.startsWith('unix:')) {\n            // Unix socket connection - use SocketAgent with socket creation function\n            const socketPath = dockerHost.substring(5); // Remove \"unix:\" prefix\n\n            try {\n                const agent = new SocketAgent(() =>\n                    createConnection(socketPath),\n                );\n                return new DockerClient(agent, userAgent, headers);\n            } catch (error) {\n                throw new Error(\n                    `Failed to create Docker client for ${dockerHost}: ${getErrorMessage(error)}`,\n                    { cause: error },\n                );\n            }\n        } else if (dockerHost.startsWith('npipe:')) {\n            // Windows name pipe connection - use SocketAgent with socket creation function\n            const socketPath = dockerHost.substring(6); // Remove \"npipe:\" prefix\n\n            try {\n                const agent = new SocketAgent(() =>\n                    createConnection(socketPath),\n                );\n                return new DockerClient(agent, userAgent, headers);\n            } catch (error) {\n                throw new Error(\n                    `Failed to create Docker client for ${dockerHost}: ${getErrorMessage(error)}`,\n                    { cause: error },\n                );\n            }\n        } else if (dockerHost.startsWith('tcp:')) {\n            // TCP connection - use SocketAgent with TCP socket creation function\n            const defaultPort = certificates ? 2376 : 2375; // Default ports: 2376 for TLS, 2375 for plain\n            const { host, port } = parseDockerHost(dockerHost, defaultPort);\n\n            try {\n                let agent: SocketAgent;\n\n                if (certificates) {\n                    if (typeof certificates === 'string') {\n                        // Use SocketAgent with TLS socket creation function\n                        const tlsOptions =\n                            await TLS.loadCertificates(certificates);\n                        agent = new SocketAgent(() =>\n                            tlsConnect({ host, port, ...tlsOptions }),\n                        );\n                    } else {\n                        // certificates is a SecureContextOptions type\n                        agent = new SocketAgent(() =>\n                            tlsConnect({ host, port, ...certificates }),\n                        );\n                    }\n                } else {\n                    // Use SocketAgent with plain TCP socket creation function\n                    agent = new SocketAgent(() =>\n                        createConnection({ host, port }),\n                    );\n                }\n\n                return new DockerClient(agent, userAgent, headers);\n            } catch (error) {\n                throw new Error(\n                    `Failed to create Docker client for ${dockerHost}: ${getErrorMessage(error)}`,\n                    { cause: error },\n                );\n            }\n        } else if (dockerHost.startsWith('ssh:')) {\n            // SSH connection - use SocketAgent with SSH socket creation function\n            try {\n                const socketFactory = await SSH.createSocketFactory(dockerHost);\n                const agent = new SocketAgent(socketFactory);\n                return new DockerClient(agent, userAgent, headers);\n            } catch (error) {\n                throw new Error(\n                    `Failed to create SSH Docker client for ${dockerHost}: ${getErrorMessage(error)}`,\n                    { cause: error },\n                );\n            }\n        } else {\n            try {\n                await fsPromises.access(dockerHost);\n                // File exists, treat it as a Unix socket\n                const agent = new SocketAgent(() =>\n                    createConnection(dockerHost),\n                );\n                return new DockerClient(agent, userAgent, headers);\n            } catch (error) {\n                // If file doesn't exist, fall through to original error handling\n            }\n\n            throw new Error(\n                `Unsupported Docker host format: ${dockerHost}. Must start with \"unix:\", \"tcp:\", \"ssh:\", or be a valid file path`,\n            );\n        }\n    }\n\n    /**\n     * Create a DockerClient instance from a Docker context name\n     * @param contextName Docker context name to search for, or uses DOCKER_CONTEXT env var if not provided\n     * @returns Promise that resolves to a connected DockerClient instance\n     */\n    static async fromDockerContext(\n        contextName?: string,\n        userAgent?: string,\n        headers?: Record<string, string>,\n    ): Promise<DockerClient> {\n        // Use DOCKER_CONTEXT environment variable if contextName not provided\n        const targetContext = contextName || process.env.DOCKER_CONTEXT;\n\n        if (!targetContext) {\n            throw new Error(\n                'No context name provided and DOCKER_CONTEXT environment variable is not set',\n            );\n        }\n\n        const configDir = process.env.DOCKER_CONFIG || homedir();\n        const contextsDir = join(configDir, '.docker', 'contexts', 'meta');\n        const tlsDir = join(configDir, '.docker', 'contexts', 'tls');\n\n        try {\n            // Read all directories in the contexts meta directory\n            const contextEntries = await fsPromises.readdir(contextsDir, {\n                withFileTypes: true,\n            });\n            const contextDirs = contextEntries\n                .filter((dirent) => dirent.isDirectory())\n                .map((dirent) => dirent.name);\n\n            for (const contextDir of contextDirs) {\n                const metaJsonPath = join(contextsDir, contextDir, 'meta.json');\n\n                try {\n                    const metaContent = await fsPromises.readFile(\n                        metaJsonPath,\n                        'utf8',\n                    );\n                    const meta = JSON.parse(metaContent);\n\n                    if (meta.Name === targetContext) {\n                        // Found matching context, extract endpoint\n                        if (\n                            meta.Endpoints &&\n                            meta.Endpoints.docker &&\n                            meta.Endpoints.docker.Host\n                        ) {\n                            const dockerHost = meta.Endpoints.docker.Host;\n                            let certificates: string | undefined = undefined;\n                            const tls = join(tlsDir, contextDir);\n                            try {\n                                await fsPromises.access(tls);\n                                certificates = tls;\n                            } catch {\n                                // TLS directory doesn't exist, certificates remain undefined\n                            }\n                            return await DockerClient.fromDockerHost(\n                                dockerHost,\n                                certificates,\n                                userAgent,\n                                headers,\n                            );\n                        } else {\n                            throw new Error(\n                                `Docker context '${targetContext}' found but has no valid Docker endpoint`,\n                            );\n                        }\n                    }\n                } catch (parseError) {\n                    // Skip invalid meta.json files or files that don't exist\n                }\n            }\n\n            throw new Error(`Docker context '${targetContext}' not found`);\n        } catch (error) {\n            if (isFileNotFoundError(error)) {\n                throw new Error(\n                    `Docker contexts directory not found: ${contextsDir}`,\n                    { cause: error },\n                );\n            }\n            throw error;\n        }\n    }\n\n    /**\n     * Create a DockerClient instance using the current context from Docker config\n     * Reads config.json from DOCKER_CONFIG env var or ~/.docker/config.json to get the currentContext and connects to it\n     * @returns Promise that resolves to a connected DockerClient instance\n     */\n    static async fromDockerConfig(\n        userAgent?: string,\n        headers?: Record<string, string>,\n    ): Promise<DockerClient> {\n        // Check for DOCKER_HOST environment variable first - takes precedence over config\n        if (process.env.DOCKER_HOST) {\n            return DockerClient.fromDockerHost(\n                process.env.DOCKER_HOST,\n                process.env.DOCKER_TLS_CERTDIR,\n                userAgent,\n                headers,\n            );\n        }\n\n        // Check for DOCKER_CONFIG environment variable, otherwise use default path\n        const configPath =\n            process.env.DOCKER_CONFIG ||\n            join(homedir(), '.docker', 'config.json');\n\n        try {\n            const configContent = await fsPromises.readFile(configPath, 'utf8');\n            const config = JSON.parse(configContent);\n\n            if (config.currentContext && config.currentContext !== 'default') {\n                // Use the specified current context\n                return await DockerClient.fromDockerContext(\n                    config.currentContext,\n                    userAgent,\n                    headers,\n                );\n            } else {\n                let dockerhost = 'unix:/var/run/docker.sock';\n                if (os.platform() === 'win32') {\n                    dockerhost = 'npipe:////./pipe/docker_engine';\n                }\n                // No current context specified, use default\n                return await DockerClient.fromDockerHost(\n                    dockerhost,\n                    undefined,\n                    userAgent,\n                    headers,\n                );\n            }\n        } catch (error) {\n            if (isFileNotFoundError(error)) {\n                // Config file doesn't exist, use default\n                return DockerClient.fromDockerHost('unix:/var/run/docker.sock');\n            } else if (error instanceof SyntaxError) {\n                throw new Error(\n                    `Invalid JSON in Docker config file: ${configPath}`,\n                    { cause: error },\n                );\n            }\n            throw error;\n        }\n    }\n\n    /**\n     * Close the Docker client connection\n     * @returns Promise that resolves when the connection is closed\n     */\n    public close(): Promise<void> {\n        return this.api.close();\n    }\n\n    // --- Authentication\n\n    /**\n     * Encode authentication credentials for registry access\n     * @param credentials Authentication credentials object\n     * @returns Base64 URL-safe encoded credentials string\n     */\n    public authCredentials(credentials: any): string {\n        const jsonString = JSON.stringify(credentials);\n        const base64 = Buffer.from(jsonString, 'utf8').toString('base64');\n        // Convert standard Base64 to URL and filename safe alphabet (RFC 4648)\n        return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n    }\n\n    // --- System API\n\n    /**\n     * Validate credentials for a registry and, if available, get an identity token for accessing the registry without password.\n     * Check auth configuration\n     * @param authConfig Authentication to check\n     */\n    public async systemAuth(\n        authConfig: types.AuthConfig,\n    ): Promise<types.SystemAuthResponse> {\n        const response = await this.api.post('/auth', authConfig, undefined, {\n            accept: APPLICATION_JSON,\n        });\n        return response.json() as Promise<types.SystemAuthResponse>;\n    }\n\n    /**\n     * Get data usage information\n     * @param type Object types, for which to compute and return data.\n     */\n    public async systemDataUsage(\n        type?: Array<'container' | 'image' | 'volume' | 'build-cache'>,\n    ): Promise<types.SystemDataUsageResponse> {\n        return this.api.getJSON<types.SystemDataUsageResponse>('/system/df', {\n            type: type,\n        });\n    }\n\n    /**\n     * Stream real-time events from the server.  Various objects within Docker report events when something happens to them.  Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, `update`, and `prune`  Images report these events: `create`, `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune`  Volumes report these events: `create`, `mount`, `unmount`, `destroy`, and `prune`  Networks report these events: `create`, `connect`, `disconnect`, `destroy`, `update`, `remove`, and `prune`  The Docker daemon reports these events: `reload`  Services report these events: `create`, `update`, and `remove`  Nodes report these events: `create`, `update`, and `remove`  Secrets report these events: `create`, `update`, and `remove`  Configs report these events: `create`, `update`, and `remove`  The Builder reports `prune` events\n     * Monitor events\n     * @param options\n     * @param options.since Show events created since this timestamp then stream new events.\n     * @param options.until Show events created until this timestamp then stop streaming.\n     * @param options.filters Filters to process on the event list. Available filters:  - 'config' config name or ID - 'container' container name or ID - 'daemon' daemon name or ID - 'event' event type - 'image' image name or ID - 'label' image or container label - 'network' network name or ID - 'node' node ID - 'plugin' plugin name or ID - 'scope' local or swarm - 'secret' secret name or ID - 'service' service name or ID - 'type' object to filter by, one of 'container', 'image', 'volume', 'network', 'daemon', 'plugin', 'node', 'service', 'secret' or 'config' - 'volume' volume name\n     */\n    public async *systemEvents(options?: {\n        since?: string;\n        until?: string;\n        filters?: Filter;\n    }): AsyncGenerator<types.EventMessage, void, undefined> {\n        const response = await this.api.get('/events', APPLICATION_NDJSON, {\n            params: options,\n        });\n        yield* jsonMessages<types.EventMessage>(response);\n    }\n\n    /**\n     * This is a dummy endpoint you can use to test if the server is accessible.\n     * @returns Promise that resolves when the connection is successful and returns API version\n     */\n    public async systemPing(): Promise<string> {\n        const response = await this.api.head('/_ping', {\n            accept: 'text/plain',\n        });\n        return response.headers.get('api-version')!;\n    }\n\n    /**\n     * Get system information\n     */\n    public async systemInfo(): Promise<types.SystemInfo> {\n        return this.api.getJSON<types.SystemInfo>('/info');\n    }\n\n    /**\n     * Returns the version of Docker that is running and various information about the system that Docker is running on.\n     * Get version\n     */\n    public async systemVersion(): Promise<types.SystemVersion> {\n        return this.api.getJSON<types.SystemVersion>('/version');\n    }\n\n    // --- Containers API\n\n    /**\n     * Get a tar archive of a resource in the filesystem of container id.\n     * Get an archive of a filesystem resource in a container\n     * @param id ID or name of the container\n     * @param path Resource in the container’s filesystem to archive.\n     * @param out stream to write container's filesystem content as a TAR archive\n     */\n    public async containerArchive(\n        id: string,\n        path: string,\n        out: WritableStream,\n    ): Promise<void> {\n        const response = await this.api.get(\n            `/containers/${id}/archive`,\n            'application/x-tar',\n            {\n                path: path,\n            },\n        );\n        await response.body?.pipeTo(out);\n    }\n\n    /**\n     * A response header `X-Docker-Container-Path-Stat` is returned, containing a base64 - encoded JSON object with some filesystem header information about the path.\n     * Get information about files in a container\n     * @param id ID or name of the container\n     * @param path Resource in the container’s filesystem to archive.\n     */\n    public async containerArchiveInfo(\n        id: string,\n        path: string,\n    ): Promise<types.FileInfo> {\n        const response = await this.api.head(`/containers/${id}/archive`, {\n            params: {\n                path: path,\n            },\n        });\n        const header = response.headers.get('x-docker-container-path-stat');\n        if (!header) {\n            throw new Error('X-Docker-Container-Path-Stat header not found');\n        }\n        const json = Buffer.from(header, 'base64').toString('utf-8');\n        return types.FileInfo.fromJSON(json);\n    }\n\n    /**\n     * Attach to a container to read its output or send it input. You can attach to the same container multiple times and you can reattach to containers that have been detached.  Either the `stream` or `logs` parameter must be `true` for this endpoint to do anything.  See the [documentation for the `docker attach` command](https://docs.docker.com/engine/reference/commandline/attach/) for more details.  ### Hijacking  This endpoint hijacks the HTTP connection to transport `stdin`, `stdout`, and `stderr` on the same socket.  This is the response from the daemon for an attach request:  ``` HTTP/1.1 200 OK Content-Type: application/vnd.docker.raw-stream  [STREAM] ```  After the headers and two new lines, the TCP connection can now be used for raw, bidirectional communication between the client and server.  To hint potential proxies about connection hijacking, the Docker client can also optionally send connection upgrade headers.  For example, the client sends this request to upgrade the connection:  ``` POST /containers/16253994b7c4/attach?stream=1&stdout=1 HTTP/1.1 Upgrade: tcp Connection: Upgrade ```  The Docker daemon will respond with a `101 UPGRADED` response, and will similarly follow with the raw stream:  ``` HTTP/1.1 101 UPGRADED Content-Type: application/vnd.docker.raw-stream Connection: Upgrade Upgrade: tcp  [STREAM] ```  ### Stream format  When the TTY setting is disabled in [`POST /containers/create`](#operation/ContainerCreate), the HTTP Content-Type header is set to application/vnd.docker.multiplexed-stream and the stream over the hijacked connected is multiplexed to separate out `stdout` and `stderr`. The stream consists of a series of frames, each containing a header and a payload.  The header contains the information which the stream writes (`stdout` or `stderr`). It also contains the size of the associated frame encoded in the last four bytes (`uint32`).  It is encoded on the first eight bytes like this:  ```go header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4} ```  `STREAM_TYPE` can be:  - 0: `stdin` (is written on `stdout`) - 1: `stdout` - 2: `stderr`  `SIZE1, SIZE2, SIZE3, SIZE4` are the four bytes of the `uint32` size encoded as big endian.  Following the header is the payload, which is the specified number of bytes of `STREAM_TYPE`.  The simplest way to implement this protocol is the following:  1. Read 8 bytes. 2. Choose `stdout` or `stderr` depending on the first byte. 3. Extract the frame size from the last four bytes. 4. Read the extracted size and output it on the correct output. 5. Goto 1.  ### Stream format when using a TTY  When the TTY setting is enabled in [`POST /containers/create`](#operation/ContainerCreate), the stream is not multiplexed. The data exchanged over the hijacked connection is simply the raw data from the process PTY and client\\'s `stdin`.\n     * Attach to a container\n     * @param id ID or name of the container\n     * @param stdout\n     * @param stderr\n     * @param options\n     * @param options.detachKeys Override the key sequence for detaching a container.Format is a single character '[a-Z]' or 'ctrl-&lt;value&gt;' where '&lt;value&gt;' is one of: 'a-z', '@', '^', '[', ',' or '_'.\n     * @param options.logs Replay previous logs from the container.  This is useful for attaching to a container that has started and you want to output everything since the container started.  If 'stream' is also enabled, once all the previous output has been returned, it will seamlessly transition into streaming current output.\n     * @param options.stream Stream attached streams from the time the request was made onwards.\n     * @param options.stdin Attach to 'stdin'\n     * @param options.stdout Attach to 'stdout'\n     * @param options.stderr Attach to 'stderr'\n     */\n    public async containerAttach(\n        id: string,\n        stdout: stream.Writable,\n        stderr: stream.Writable | null,\n        options?: {\n            detachKeys?: string;\n            logs?: boolean;\n            stream?: boolean;\n            stdin?: boolean;\n            stdout?: boolean;\n            stderr?: boolean;\n        },\n    ): Promise<void> {\n        const response = await this.api.upgrade(\n            `/containers/${id}/attach`,\n            options,\n        );\n        switch (response.content) {\n            case DOCKER_RAW_STREAM:\n                response.socket.pipe(stdout);\n                break;\n            case DOCKER_MULTIPLEXED_STREAM:\n                if (stderr === null) {\n                    throw new Error(\n                        'stderr is required to process multiplexed stream',\n                    );\n                }\n                response.socket.pipe(demultiplexStream(stdout, stderr));\n                break;\n            default:\n                throw new Error(\n                    'Unsupported content type: ' + response.content,\n                );\n        }\n        return new Promise((resolve, reject) => {\n            response.socket.once('error', reject);\n            response.socket.once('close', resolve);\n        });\n    }\n\n    /**\n     * Returns which files in a container\\'s filesystem have been added, deleted, or modified. The `Kind` of modification can be one of:  - `0`: Modified (\\\"C\\\") - `1`: Added (\\\"A\\\") - `2`: Deleted (\\\"D\\\")\n     * Get changes on a container’s filesystem\n     * @param id ID or name of the container\n     */\n    public async containerChanges(\n        id: string,\n    ): Promise<Array<types.FilesystemChange>> {\n        return this.api.getJSON<Array<types.FilesystemChange>>(\n            `/containers/${id}/changes`,\n        );\n    }\n\n    /**\n     * Create a container\n     * @param spec Container to create\n     * @param options\n     * @param options.name Assign the specified name to the container. Must match '/?[a-zA-Z0-9][a-zA-Z0-9_.-]+'.\n     * @param options.platform Platform in the format 'os[/arch[/variant]]' used for image lookup.  When specified, the daemon checks if the requested image is present in the local image cache with the given OS and Architecture, and otherwise returns a '404' status.  If the option is not set, the host\\&#39;s native OS and Architecture are used to look up the image in the image cache. However, if no platform is passed and the given image does exist in the local image cache, but its OS or architecture does not match, the container is created with the available image, and a warning is added to the 'Warnings' field in the response, for example;      WARNING: The requested image\\&#39;s platform (linux/arm64/v8) does not              match the detected host platform (linux/amd64) and no              specific platform was requested\n     */\n    public async containerCreate(\n        spec: types.ContainerCreateRequest,\n        options?: {\n            name?: string;\n            platform?: string;\n        },\n    ): Promise<types.ContainerCreateResponse> {\n        spec.Image = this.parseDockerRef(spec.Image);\n\n        const response = await this.api.post(\n            '/containers/create',\n            options,\n            spec,\n        );\n        return response.json() as Promise<types.ContainerCreateResponse>;\n    }\n\n    /**\n     * Remove a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.volumes Remove anonymous volumes associated with the container.\n     * @param options.force If the container is running, kill it before removing it.\n     * @param options.link Remove the specified link associated with the container.\n     */\n    public async containerDelete(\n        id: string,\n        options?: {\n            volumes?: boolean;\n            force?: boolean;\n            link?: boolean;\n        },\n    ): Promise<void> {\n        await this.api.delete(`/containers/${id}`, {\n            v: options?.volumes,\n            force: options?.force,\n            link: options?.link,\n        });\n    }\n\n    /**\n     * Export the contents of a container as a tarball.\n     * Export a container\n     * @param id ID or name of the container\n     * @param w stream to write container's filesystem content as a TAR archive'\n     */\n    public async containerExport(id: string, w: WritableStream): Promise<void> {\n        const response = await this.api.get(\n            `/containers/${id}/export`,\n            'application/x-tar',\n        );\n        await response.body?.pipeTo(w);\n    }\n\n    /**\n     * Return low-level information about a container.\n     * Inspect a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.size Return the size of container as fields 'SizeRw' and 'SizeRootFs'\n     */\n    public async containerInspect(\n        id: string,\n        options?: {\n            size?: boolean;\n        },\n    ): Promise<types.ContainerInspectResponse> {\n        return this.api.getJSON<types.ContainerInspectResponse>(\n            `/containers/${id}/json`,\n            options,\n        );\n    }\n\n    /**\n     * Send a POSIX signal to a container, defaulting to killing to the container.\n     * Kill a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.signal Signal to send to the container as an integer or string (e.g. 'SIGINT').\n     */\n    public async containerKill(\n        id: string,\n        options?: {\n            signal?: string;\n        },\n    ): Promise<void> {\n        await this.api.post(`/containers/${id}/kill`, options);\n    }\n\n    /**\n     * Returns a list of containers. For details on the format, see the [inspect endpoint](#operation/ContainerInspect).  Note that it uses a different, smaller representation of a container than inspecting a single container. For example, the list of linked containers is not propagated .\n     * List containers\n     * @param options\n     * @param options.all Return all containers. By default, only running containers are shown.\n     * @param options.limit Return this number of most recently created containers, including non-running ones.\n     * @param options.size Return the size of container as fields 'SizeRw' and 'SizeRootFs'.\n     * @param options.filters Filters to process on the container list, encoded as JSON (a 'map[string][]string'). For example, '{\\&quot;status\\&quot;: [\\&quot;paused\\&quot;]}' will only return paused containers.  Available filters:  - 'ancestor''('&lt;image-name&gt;[:&lt;tag&gt;]', '&lt;image id&gt;', or '&lt;image@digest&gt;') - 'before''('&lt;container id&gt;' or '&lt;container name&gt;') - 'expose''('&lt;port&gt;[/&lt;proto&gt;]'|'&lt;startport-endport&gt;/[&lt;proto&gt;]') - 'exited'&lt;int&gt;' containers with exit code of '&lt;int&gt;' - 'health''('starting'|'healthy'|'unhealthy'|'none') - 'id'&lt;ID&gt;' a container\\&#39;s ID - 'isolation''('default'|'process'|'hyperv') (Windows daemon only) - 'is-task''('true'|'false') - 'label'key' or 'label'\\&quot;key'value\\&quot;' of a container label - 'name'&lt;name&gt;' a container\\&#39;s name - 'network''('&lt;network id&gt;' or '&lt;network name&gt;') - 'publish''('&lt;port&gt;[/&lt;proto&gt;]'|'&lt;startport-endport&gt;/[&lt;proto&gt;]') - 'since''('&lt;container id&gt;' or '&lt;container name&gt;') - 'status''('created'|'restarting'|'running'|'removing'|'paused'|'exited'|'dead') - 'volume''('&lt;volume name&gt;' or '&lt;mount point destination&gt;')\n     */\n    public async containerList(options?: {\n        all?: boolean;\n        limit?: number;\n        size?: boolean;\n        filters?: Filter;\n    }): Promise<Array<types.ContainerSummary>> {\n        return this.api.getJSON<Array<types.ContainerSummary>>(\n            '/containers/json',\n            options,\n        );\n    }\n\n    /**\n     * Get `stdout` and `stderr` logs from a container.  Note: This endpoint works only for containers with the `json-file` or `journald` logging driver.\n     * Get container logs\n     * @param id ID or name of the container\n     * @param stdout\n     * @param stderr\n     * @param options\n     * @param options.follow Keep connection after returning logs.\n     * @param options.stdout Return logs from 'stdout'\n     * @param options.stderr Return logs from 'stderr'\n     * @param options.since Only return logs since this time, as a UNIX timestamp\n     * @param options.until Only return logs before this time, as a UNIX timestamp\n     * @param options.timestamps Add timestamps to every log line\n     * @param options.tail Only return this number of log lines from the end of the logs. Specify as an integer or 'all' to output all log lines.\n     */\n    public async containerLogs(\n        id: string,\n        stdout: stream.Writable,\n        stderr: stream.Writable,\n        options?: {\n            follow?: boolean;\n            stdout?: boolean;\n            stderr?: boolean;\n            since?: number;\n            until?: number;\n            timestamps?: boolean;\n            tail?: string;\n        },\n    ): Promise<void> {\n        const demux = demultiplexStream(stdout, stderr);\n        const response = await this.api.get(\n            `/containers/${id}/logs`,\n            'application/vnd.docker.raw-stream',\n            options,\n        );\n        await response.body?.pipeTo(Writable.toWeb(demux));\n    }\n\n    /**\n     * Use the freezer cgroup to suspend all processes in a container.  Traditionally, when suspending a process the `SIGSTOP` signal is used, which is observable by the process being suspended. With the freezer cgroup the process is unaware, and unable to capture, that it is being suspended, and subsequently resumed.\n     * Pause a container\n     * @param id ID or name of the container\n     */\n    public async containerPause(id: string): Promise<void> {\n        await this.api.post(`/containers/${id}/pause`);\n    }\n\n    /**\n     * Delete stopped containers\n     * @param options\n     * @param options.filters Filters to process on the prune list, encoded as JSON (a 'map[string][]string').  Available filters: - 'until'&lt;timestamp&gt;' Prune containers created before this timestamp. The '&lt;timestamp&gt;' can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. '10m', '1h30m') computed relative to the daemon machine’s time. - 'label' ('label'&lt;key&gt;', 'label'&lt;key&gt;'&lt;value&gt;', 'label!'&lt;key&gt;', or 'label!'&lt;key&gt;'&lt;value&gt;') Prune containers with (or without, in case 'label!'...' is used) the specified labels.\n     */\n    public async containerPrune(options?: {\n        filters?: string;\n    }): Promise<types.ContainerPruneResponse> {\n        const response = await this.api.post('/containers/prune', options);\n        return response.json() as Promise<types.ContainerPruneResponse>;\n    }\n\n    /**\n     * Rename a container\n     * @param id ID or name of the container\n     * @param name New name for the container\n     */\n    public async containerRename(id: string, name: string): Promise<void> {\n        await this.api.post(`/containers/${id}/rename?name=${name}`);\n    }\n\n    /**\n     * Resize the TTY for a container.\n     * Resize a container TTY\n     * @param id ID or name of the container\n     * @param height Height of the TTY session in characters\n     * @param width Width of the TTY session in characters\n     */\n    public async containerResize(\n        id: string,\n        width: number,\n        height: number,\n    ): Promise<void> {\n        await this.api.post(`/containers/${id}/resize`, {\n            w: width,\n            h: height,\n        });\n    }\n\n    /**\n     * Restart a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.signal Signal to send to the container as an integer or string (e.g. 'SIGINT').\n     * @param options.timeout Number of seconds to wait before killing the container\n     */\n    public async containerRestart(\n        id: string,\n        options?: {\n            signal?: string;\n            timeout?: number;\n        },\n    ): Promise<void> {\n        await this.api.post(`/containers/${id}/restart`, {\n            signal: options?.signal,\n            t: options?.timeout,\n        });\n    }\n\n    /**\n     * Start a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.detachKeys Override the key sequence for detaching a container. Format is a single character '[a-Z]' or 'ctrl-&lt;value&gt;' where '&lt;value&gt;' is one of: 'a-z', '@', '^', '[', ',' or '_'.\n     */\n    public async containerStart(\n        id: string,\n        options?: {\n            detachKeys?: string;\n        },\n    ): Promise<void> {\n        await this.api.post(`/containers/${id}/start`, options);\n    }\n\n    /**\n     * This endpoint returns a live stream of a container’s resource usage statistics.  The `precpu_stats` is the CPU statistic of the *previous* read, and is used to calculate the CPU usage percentage. It is not an exact copy of the `cpu_stats` field.  If either `precpu_stats.online_cpus` or `cpu_stats.online_cpus` is nil then for compatibility with older daemons the length of the corresponding `cpu_usage.percpu_usage` array should be used.  On a cgroup v2 host, the following fields are not set * `blkio_stats`: all fields other than `io_service_bytes_recursive` * `cpu_stats`: `cpu_usage.percpu_usage` * `memory_stats`: `max_usage` and `failcnt` Also, `memory_stats.stats` fields are incompatible with cgroup v1.  To calculate the values shown by the `stats` command of the docker cli tool the following formulas can be used: * used_memory = `memory_stats.usage - memory_stats.stats.cache` * available_memory = `memory_stats.limit` * Memory usage % = `(used_memory / available_memory) * 100.0` * cpu_delta = `cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage` * system_cpu_delta = `cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage` * number_cpus = `length(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus` * CPU usage % = `(cpu_delta / system_cpu_delta) * number_cpus * 100.0`\n     * Get container stats based on resource usage\n     * @param id ID or name of the container\n     * @param options\n     * @param options.stream Stream the output. If false, the stats will be output once and then it will disconnect.\n     * @param options.oneShot Only get a single stat instead of waiting for 2 cycles. Must be used with 'stream'false'.\n     */\n    public async containerStats(\n        id: string,\n        options?: {\n            stream?: boolean;\n            oneShot?: boolean;\n        },\n    ): Promise<types.ContainerStatsResponse> {\n        return this.api.getJSON<types.ContainerStatsResponse>(\n            `/containers/${id}/stats`,\n            {\n                stream: false, // FIXME implement streaming mode\n                oneShot: options?.oneShot,\n            },\n        );\n    }\n\n    /**\n     * Stop a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.signal Signal to send to the container as an integer or string (e.g. 'SIGINT').\n     * @param options.timeout Number of seconds to wait before killing the container\n     */\n    public async containerStop(\n        id: string,\n        options?: {\n            signal?: string;\n            timeout?: number;\n        },\n    ): Promise<void> {\n        await this.api.post(`/containers/${id}/stop`, {\n            signal: options?.signal,\n            t: options?.timeout,\n        });\n    }\n\n    /**\n     * On Unix systems, this is done by running the `ps` command. This endpoint is not supported on Windows.\n     * List processes running inside a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.psArgs The arguments to pass to 'ps'. For example, 'aux'\n     */\n    public async containerTop(\n        id: string,\n        options?: {\n            psArgs?: string;\n        },\n    ): Promise<types.ContainerTopResponse> {\n        return this.api.getJSON<types.ContainerTopResponse>(\n            `/containers/${id}/top`,\n            {\n                ps_args: options?.psArgs,\n            },\n        );\n    }\n\n    /**\n     * Resume a container which has been paused.\n     * Unpause a container\n     * @param id ID or name of the container\n     */\n    public async containerUnpause(id: string): Promise<void> {\n        await this.api.post(`/containers/${id}/unpause`);\n    }\n\n    /**\n     * Change various configuration options of a container without having to recreate it.\n     * Update a container\n     * @param id ID or name of the container\n     * @param update\n     */\n    public async containerUpdate(\n        id: string,\n        update: types.ContainerUpdateRequest,\n    ): Promise<types.ContainerUpdateResponse> {\n        const response = await this.api.post(\n            `/containers/${id}/update`,\n            update,\n        );\n        return response.json() as Promise<types.ContainerUpdateResponse>;\n    }\n\n    /**\n     * Block until a container stops, then returns the exit code.\n     * Wait for a container\n     * @param id ID or name of the container\n     * @param options\n     * @param options.condition Wait until a container state reaches the given condition.  Defaults to 'not-running' if omitted or empty.\n     */\n    public async containerWait(\n        id: string,\n        options?: {\n            condition?: 'not-running' | 'next-exit' | 'removed';\n        },\n    ): Promise<types.ContainerWaitResponse> {\n        const response = await this.api.post(\n            `/containers/${id}/wait`,\n            undefined,\n            options,\n        );\n        return response.json() as Promise<types.ContainerWaitResponse>;\n    }\n\n    /**\n     * Upload a tar archive to be extracted to a path in the filesystem of container id. `path` parameter is asserted to be a directory. If it exists as a file, 400 error will be returned with message \\\"not a directory\\\".\n     * Extract an archive of files or folders to a directory in a container\n     * @param id ID or name of the container\n     * @param path Path to a directory in the container to extract the archive’s contents into.\n     * @param tar The input stream must be a tar archive compressed with one of the following algorithms: 'identity' (no compression), 'gzip', 'bzip2', or 'xz'.\n     * @param options\n     * @param options.noOverwriteDirNonDir If '1', 'true', or 'True' then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa.\n     * @param options.copyUIDGID If '1', 'true', then it will copy UID/GID maps to the dest file or dir\n     */\n    public async putContainerArchive(\n        id: string,\n        path: string,\n        tar: stream.Readable,\n        options?: {\n            noOverwriteDirNonDir?: string;\n            copyUIDGID?: string;\n        },\n    ): Promise<void> {\n        await this.api.put(\n            `/containers/${id}/archive`,\n            {\n                path: path,\n                noOverwriteDirNonDir: options?.noOverwriteDirNonDir,\n                copyUIDGID: options?.copyUIDGID,\n            },\n            tar,\n            'application/x-tar',\n        );\n    }\n\n    // --- Network API\n\n    /**\n     * The network must be either a local-scoped network or a swarm-scoped network with the `attachable` option set. A network cannot be re-attached to a running container\n     * Connect a container to a network\n     * @param id Network ID or name\n     * @param container\n     */\n    public async networkConnect(\n        id: string,\n        container: types.NetworkConnectRequest,\n    ): Promise<void> {\n        await this.api.post(`/networks/${id}/connect`, container);\n    }\n\n    /**\n     * Create a network\n     * @param config Network configuration\n     */\n    public async networkCreate(\n        config: types.NetworkCreateRequest,\n    ): Promise<types.NetworkCreateResponse> {\n        const response = await this.api.post(\n            '/networks/create',\n            undefined,\n            config,\n        );\n        return response.json() as Promise<types.NetworkCreateResponse>;\n    }\n\n    /**\n     * Remove a network\n     * @param id Network ID or name\n     */\n    public async networkDelete(id: string): Promise<void> {\n        await this.api.delete(`/networks/${id}`);\n    }\n\n    /**\n     * Disconnect a container from a network\n     * @param id Network ID or name\n     * @param container\n     */\n    public async networkDisconnect(\n        id: string,\n        container: types.NetworkDisconnectRequest,\n    ): Promise<void> {\n        await this.api.post(`/networks/${id}/disconnect`, container);\n    }\n\n    /**\n     * Inspect a network\n     * @param id Network ID or name\n     * @param options\n     * @param options.verbose Detailed inspect output for troubleshooting\n     * @param options.scope Filter the network by scope (swarm, global, or local)\n     */\n    public async networkInspect(\n        id: string,\n        options?: {\n            verbose?: boolean;\n            scope?: string;\n        },\n    ): Promise<types.NetworkInspect> {\n        return this.api.getJSON(`/networks/${id}`, options);\n    }\n\n    /**\n     * Returns a list of networks. For details on the format, see the [network inspect endpoint](#operation/NetworkInspect).  Note that it uses a different, smaller representation of a network than inspecting a single network. For example, the list of containers attached to the network is not propagated in API versions 1.28 and up.\n     * List networks\n     * @param options\n     * @param options.filters JSON encoded value of the filters (a 'map[string][]string') to process on the networks list.  Available filters:  - 'dangling'&lt;boolean&gt;' When set to 'true' (or '1'), returns all    networks that are not in use by a container. When set to 'false'    (or '0'), only networks that are in use by one or more    containers are returned. - 'driver'&lt;driver-name&gt;' Matches a network\\&#39;s driver. - 'id'&lt;network-id&gt;' Matches all or part of a network ID. - 'label'&lt;key&gt;' or 'label'&lt;key&gt;'&lt;value&gt;' of a network label. - 'name'&lt;network-name&gt;' Matches all or part of a network name. - 'scope'[\\&quot;swarm\\&quot;|\\&quot;global\\&quot;|\\&quot;local\\&quot;]' Filters networks by scope ('swarm', 'global', or 'local'). - 'type'[\\&quot;custom\\&quot;|\\&quot;builtin\\&quot;]' Filters networks by type. The 'custom' keyword returns all user-defined networks.\n     */\n    public async networkList(options?: {\n        filters?: Filter;\n    }): Promise<Array<types.NetworkSummary>> {\n        return this.api.getJSON('/networks', options);\n    }\n\n    /**\n     * Delete unused networks\n     * @param filters Filters to process on the prune list, encoded as JSON (a 'map[string][]string').  Available filters: - 'until'&lt;timestamp&gt;' Prune networks created before this timestamp. The '&lt;timestamp&gt;' can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. '10m', '1h30m') computed relative to the daemon machine’s time. - 'label' ('label'&lt;key&gt;', 'label'&lt;key&gt;'&lt;value&gt;', 'label!'&lt;key&gt;', or 'label!'&lt;key&gt;'&lt;value&gt;') Prune networks with (or without, in case 'label!'...' is used) the specified labels.\n     */\n    public async networkPrune(\n        filters?: Filter,\n    ): Promise<types.NetworkPruneResponse> {\n        const response = await this.api.post('/networks/prune', filters);\n        return response.json() as Promise<types.NetworkPruneResponse>;\n    }\n\n    // --- Volumes API\n\n    /**\n     * Create a volume\n     * @param spec Volume configuration\n     */\n    public async volumeCreate(\n        spec: types.VolumeCreateOptions,\n    ): Promise<types.Volume> {\n        const response = await this.api.post(\n            '/volumes/create',\n            undefined,\n            spec,\n            {\n                Accept: '*/*',\n            },\n        );\n        return response.json() as Promise<types.Volume>;\n    }\n\n    /**\n     * Instruct the driver to remove the volume.\n     * Remove a volume\n     * @param id Volume name or ID\n     * @param options\n     * @param options.force Force the removal of the volume\n     */\n    public async volumeDelete(\n        id: string,\n        options?: {\n            force?: boolean;\n        },\n    ): Promise<void> {\n        await this.api.delete(`/volumes/${id}`, options);\n    }\n\n    /**\n     * Inspect a volume\n     * @param id Volume name or ID\n     */\n    public async volumeInspect(id: string): Promise<types.Volume> {\n        return this.api.getJSON(`/volumes/${id}`);\n    }\n\n    /**\n     * List volumes\n     * @param filters JSON encoded value of the filters (a 'map[string][]string') to process on the volumes list. Available filters:  - 'dangling'&lt;boolean&gt;' When set to 'true' (or '1'), returns all    volumes that are not in use by a container. When set to 'false'    (or '0'), only volumes that are in use by one or more    containers are returned. - 'driver'&lt;volume-driver-name&gt;' Matches volumes based on their driver. - 'label'&lt;key&gt;' or 'label'&lt;key&gt;:&lt;value&gt;' Matches volumes based on    the presence of a 'label' alone or a 'label' and a value. - 'name'&lt;volume-name&gt;' Matches all or part of a volume name.\n     */\n    public async volumeList(\n        filters?: Filter,\n    ): Promise<types.VolumeListResponse> {\n        return this.api.getJSON(`/volumes`, {\n            filters: filters,\n        });\n    }\n\n    /**\n     * Delete unused volumes\n     * @param filters Filters to process on the prune list, encoded as JSON (a 'map[string][]string').  Available filters: - 'label' ('label'&lt;key&gt;', 'label'&lt;key&gt;'&lt;value&gt;', 'label!'&lt;key&gt;', or 'label!'&lt;key&gt;'&lt;value&gt;') Prune volumes with (or without, in case 'label!'...' is used) the specified labels. - 'all' ('all'true') - Consider all (local) volumes for pruning and not just anonymous volumes.\n     */\n    public async volumePrune(\n        filters?: Filter,\n    ): Promise<types.VolumePruneResponse> {\n        const response = await this.api.post('/volumes/prune', {\n            filters: filters,\n        });\n        return response.json() as Promise<types.VolumePruneResponse>;\n    }\n\n    // --- Image API\n\n    /**\n     * Return image digest and platform information by contacting the registry.\n     * Get image information from the registry\n     * @param name Image name or id\n     */\n    public async distributionInspect(\n        name: string,\n    ): Promise<types.DistributionInspect> {\n        return this.api.getJSON(`/distribution/${name}/json`);\n    }\n\n    /**\n     * Delete builder cache\n     * @param reservedSpace Amount of disk space in bytes to keep for cache\n     * @param maxUsedSpace Maximum amount of disk space allowed to keep for cache\n     * @param minFreeSpace Target amount of free disk space after pruning\n     * @param all Remove all types of build cache\n     * @param filters A JSON encoded value of the filters (a &#x60;map[string][]string&#x60;) to process on the list of build cache objects.  Available filters:  - &#x60;until&#x3D;&lt;timestamp&gt;&#x60; remove cache older than &#x60;&lt;timestamp&gt;&#x60;. The &#x60;&lt;timestamp&gt;&#x60; can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. &#x60;10m&#x60;, &#x60;1h30m&#x60;) computed relative to the daemon\\&#39;s local time. - &#x60;id&#x3D;&lt;id&gt;&#x60; - &#x60;parent&#x3D;&lt;id&gt;&#x60; - &#x60;type&#x3D;&lt;string&gt;&#x60; - &#x60;description&#x3D;&lt;string&gt;&#x60; - &#x60;inuse&#x60; - &#x60;shared&#x60; - &#x60;private&#x60;\n     */\n    public async buildPrune(options?: {\n        reservedSpace?: number;\n        maxUsedSpace?: number;\n        minFreeSpace?: number;\n        all?: boolean;\n        filters?: Filter;\n    }): Promise<types.BuildPruneResponse> {\n        const response = await this.api.post('/build/prune', options);\n        return response.json() as Promise<types.BuildPruneResponse>;\n    }\n\n    /**\n     * Build an image from a tar archive with a `Dockerfile` in it.  The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive\\'s root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](https://docs.docker.com/engine/reference/builder/).  The Docker daemon performs a preliminary validation of the `Dockerfile` before starting the build, and returns an error if the syntax is incorrect. After that, each instruction is run one-by-one until the ID of the new image is output.  The build is canceled if the client drops the connection by quitting or being killed.\n     * Build an image\n     *\n     * @param buildContext A tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz.\n     * @param options\n     * @param options.dockerfile Path within the build context to the &#x60;Dockerfile&#x60;. This is ignored if &#x60;remote&#x60; is specified and points to an external &#x60;Dockerfile&#x60;.\n     * @param options.t A name and optional tag to apply to the image in the &#x60;name:tag&#x60; format. If you omit the tag the default &#x60;latest&#x60; value is assumed. You can provide several &#x60;t&#x60; parameters.\n     * @param options.extrahosts Extra hosts to add to /etc/hosts\n     * @param options.remote A Git repository URI or HTTP/HTTPS context URI. If the URI points to a single text file, the file's contents are placed into a file called &#x60;Dockerfile&#x60; and the image is built from that file. If the URI points to a tarball, the file is downloaded by the daemon and the contents therein used as the context for the build. If the URI points to a tarball and the &#x60;dockerfile&#x60; parameter is also specified, there must be a file with the corresponding path inside the tarball.\n     * @param options.q Suppress verbose build output.\n     * @param options.nocache Do not use the cache when building the image.\n     * @param options.cachefrom JSON array of images used for build cache resolution.\n     * @param options.pull Attempt to pull the image even if an older image exists locally.\n     * @param options.rm Remove intermediate containers after a successful build.\n     * @param options.forcerm Always remove intermediate containers, even upon failure.\n     * @param options.memory Set memory limit for build.\n     * @param options.memswap Total memory (memory + swap). Set as &#x60;-1&#x60; to disable swap.\n     * @param options.cpushares CPU shares (relative weight).\n     * @param options.cpusetcpus CPUs in which to allow execution (e.g., &#x60;0-3&#x60;, &#x60;0,1&#x60;).\n     * @param options.cpuperiod The length of a CPU period in microseconds.\n     * @param options.cpuquota Microseconds of CPU time that the container can get in a CPU period.\n     * @param options.buildargs JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker uses the buildargs as the environment context for commands run via the &#x60;Dockerfile&#x60; RUN instruction, or for variable expansion in other &#x60;Dockerfile&#x60; instructions. This is not meant for passing secret values.  For example, the build arg &#x60;FOO&#x3D;bar&#x60; would become &#x60;{\\&quot;FOO\\&quot;:\\&quot;bar\\&quot;}&#x60; in JSON. This would result in the query parameter &#x60;buildargs&#x3D;{\\&quot;FOO\\&quot;:\\&quot;bar\\&quot;}&#x60;. Note that &#x60;{\\&quot;FOO\\&quot;:\\&quot;bar\\&quot;}&#x60; should be URI component encoded.  [Read more about the buildargs instruction.](https://docs.docker.com/engine/reference/builder/#arg)\n     * @param options.shmsize Size of &#x60;/dev/shm&#x60; in bytes. The size must be greater than 0. If omitted the system uses 64MB.\n     * @param options.squash Squash the resulting images layers into a single layer. *(Experimental release only.)*\n     * @param options.labels Arbitrary key/value labels to set on the image, as a JSON map of string pairs.\n     * @param options.networkmode Sets the networking mode for the run commands during build. Supported standard values are: &#x60;bridge&#x60;, &#x60;host&#x60;, &#x60;none&#x60;, and &#x60;container:&lt;name|id&gt;&#x60;. Any other value is taken as a custom network\\&#39;s name or ID to which this container should connect to.\n     * @param options.contentType\n     * @param options.xRegistryConfig This is a base64-encoded JSON object with auth configurations for multiple registries that a build may refer to.  The key is a registry URL, and the value is an auth configuration object, [as described in the authentication section](#section/Authentication). For example:  &#x60;&#x60;&#x60; {   \\&quot;docker.example.com\\&quot;: {     \\&quot;username\\&quot;: \\&quot;janedoe\\&quot;,     \\&quot;password\\&quot;: \\&quot;hunter2\\&quot;   },   \\&quot;https://index.docker.io/v1/\\&quot;: {     \\&quot;username\\&quot;: \\&quot;mobydock\\&quot;,     \\&quot;password\\&quot;: \\&quot;conta1n3rize14\\&quot;   } } &#x60;&#x60;&#x60;  Only the registry domain name (and port if not the default 443) are required. However, for legacy reasons, the Docker Hub registry must be specified with both a &#x60;https://&#x60; prefix and a &#x60;/v1/&#x60; suffix even though Docker will prefer to use the v2 registry API.\n     * @param options.platform Platform in the format os[/arch[/variant]]\n     * @param options.target Target build stage\n     * @param options.outputs BuildKit output configuration in the format of a stringified JSON array of objects. Each object must have two top-level properties: &#x60;Type&#x60; and &#x60;Attrs&#x60;. The &#x60;Type&#x60; property must be set to \\&#39;moby\\&#39;. The &#x60;Attrs&#x60; property is a map of attributes for the BuildKit output configuration. See https://docs.docker.com/build/exporters/oci-docker/ for more information.  Example:  &#x60;&#x60;&#x60; [{\\&quot;Type\\&quot;:\\&quot;moby\\&quot;,\\&quot;Attrs\\&quot;:{\\&quot;type\\&quot;:\\&quot;image\\&quot;,\\&quot;force-compression\\&quot;:\\&quot;true\\&quot;,\\&quot;compression\\&quot;:\\&quot;zstd\\&quot;}}] &#x60;&#x60;&#x60;\n     * @param options.version Version of the builder backend to use.  - &#x60;1&#x60; is the first generation classic (deprecated) builder in the Docker daemon (default) - &#x60;2&#x60; is [BuildKit](https://github.com/moby/buildkit)\n     */\n    public imageBuild(\n        buildContext: ReadableStream,\n        options?: {\n            dockerfile?: string;\n            tag?: string;\n            extrahosts?: string;\n            remote?: string;\n            quiet?: boolean;\n            nocache?: boolean;\n            cachefrom?: string;\n            pull?: string;\n            rm?: boolean;\n            forcerm?: boolean;\n            memory?: number;\n            memswap?: number;\n            cpushares?: number;\n            cpusetcpus?: string;\n            cpuperiod?: number;\n            cpuquota?: number;\n            buildargs?: string;\n            shmsize?: number;\n            squash?: boolean;\n            labels?: string;\n            networkmode?: string;\n            credentials?: Record<string, AuthConfig>;\n            platform?: string;\n            target?: string;\n            outputs?: string;\n            version?: '1' | '2';\n        },\n    ): JSONMessages<JSONMessage, string> {\n        const headers: Record<string, string> = {};\n        headers['Content-Type'] = 'application/x-tar';\n\n        if (options?.credentials) {\n            headers['X-Registry-Config'] = this.authCredentials(\n                options.credentials,\n            );\n        }\n\n        const request = this.api.post(\n            '/build',\n            {\n                dockerfile: options?.dockerfile,\n                t: options?.tag,\n                extrahosts: options?.extrahosts,\n                remote: options?.remote,\n                q: options?.quiet,\n                nocache: options?.nocache,\n                cachefrom: options?.cachefrom,\n                pull: options?.pull,\n                rm: options?.rm,\n                forcerm: options?.forcerm,\n                memory: options?.memory,\n                memswap: options?.memswap,\n                cpushares: options?.cpushares,\n                cpusetcpus: options?.cpusetcpus,\n                cpuperiod: options?.cpuperiod,\n                cpuquota: options?.cpuquota,\n                buildargs: options?.buildargs,\n                shmsize: options?.shmsize,\n                squash: options?.squash,\n                labels: options?.labels,\n                networkmode: options?.networkmode,\n                platform: options?.platform,\n                target: options?.target,\n                outputs: options?.outputs,\n                version: options?.version || '2',\n            },\n            buildContext,\n            headers,\n        );\n\n        return {\n            messages: async function* (): AsyncGenerator<\n                types.JSONMessage,\n                void,\n                undefined\n            > {\n                const response = await request;\n                yield* jsonMessages<types.JSONMessage>(response);\n            },\n            wait: async function (): Promise<string> {\n                let id = '';\n                const response = await request;\n                for await (const message of jsonMessages<types.JSONMessage>(\n                    response,\n                )) {\n                    if (message.errorDetail) {\n                        throw new Error(message.errorDetail?.message);\n                    }\n                    if (message.id === 'moby.image.id') {\n                        id = message?.aux?.ID || '';\n                    }\n                }\n                return id;\n            },\n        };\n    }\n\n    /**\n     * Create a new image from a container\n     * @param container The ID or name of the container to commit\n     * @param repo Repository name for the created image\n     * @param tag Tag name for the create image\n     * @param comment Commit message\n     * @param author Author of the image (e.g., &#x60;John Hannibal Smith &lt;hannibal@a-team.com&gt;&#x60;)\n     * @param pause Whether to pause the container before committing\n     * @param changes &#x60;Dockerfile&#x60; instructions to apply while committing\n     * @param containerConfig The container configuration\n     */\n    public async imageCommit(\n        container: string,\n        options?: {\n            repo?: string;\n            tag?: string;\n            comment?: string;\n            author?: string;\n            pause?: boolean;\n            changes?: string;\n            containerConfig?: types.ContainerConfig;\n        },\n    ): Promise<types.IDResponse> {\n        const response = await this.api.post(`/commit`, {\n            container: container,\n            repo: options?.repo,\n            tag: options?.tag,\n            comment: options?.comment,\n            author: options?.author,\n            pause: options?.pause,\n            changes: options?.changes,\n            containerConfig: options?.containerConfig,\n        });\n        return response.json() as Promise<types.IDResponse>;\n    }\n\n    /**\n     * Pull or import an image.\n     * Create an image\n     * @param options\n     * @param options.fromImage Name of the image to pull. If the name includes a tag or digest, specific behavior applies:  - If only 'fromImage' includes a tag, that tag is used. - If both 'fromImage' and 'tag' are provided, 'tag' takes precedence. - If 'fromImage' includes a digest, the image is pulled by digest, and 'tag' is ignored. - If neither a tag nor digest is specified, all tags are pulled.\n     * @param options.fromSrc Source to import. The value may be a URL from which the image can be retrieved or '-' to read the image from the request body. This parameter may only be used when importing an image.\n     * @param options.repo Repository name given to an image when it is imported. The repo may include a tag. This parameter may only be used when importing an image.\n     * @param options.tag Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled.\n     * @param options.message Set commit message for imported image.\n     * @param options.credentials A base64url-encoded auth configuration.  Refer to the [authentication section](#section/Authentication) for details.\n     * @param options.changes Apply 'Dockerfile' instructions to the image that is created, for example: 'changes'ENV DEBUG'true'. Note that 'ENV DEBUG'true' should be URI component encoded.  Supported 'Dockerfile' instructions: 'CMD'|'ENTRYPOINT'|'ENV'|'EXPOSE'|'ONBUILD'|'USER'|'VOLUME'|'WORKDIR'\n     * @param options.platform Platform in the format os[/arch[/variant]].  When used in combination with the 'fromImage' option, the daemon checks if the given image is present in the local image cache with the given OS and Architecture, and otherwise attempts to pull the image. If the option is not set, the host\\&#39;s native OS and Architecture are used. If the given image does not exist in the local image cache, the daemon attempts to pull the image with the host\\&#39;s native OS and Architecture. If the given image does exists in the local image cache, but its OS or architecture does not match, a warning is produced.  When used with the 'fromSrc' option to import an image from an archive, this option sets the platform information for the imported image. If the option is not set, the host\\&#39;s native OS and Architecture are used for the imported image.\n     * @param options.inputImage Image content if the value '-' has been specified in fromSrc query parameter\n     */\n    public imageCreate(options?: {\n        fromImage?: string;\n        fromSrc?: string;\n        repo?: string;\n        tag?: string;\n        message?: string;\n        credentials?: AuthConfig;\n        changes?: Array<string>;\n        platform?: string;\n        inputImage?: string;\n    }): JSONMessages<JSONMessage, string> {\n        const headers: Record<string, string> = {};\n\n        if (options?.credentials) {\n            headers['X-Registry-Auth'] = this.authCredentials(\n                options.credentials,\n            );\n        }\n\n        let ref = this.parseDockerRef(options?.fromImage);\n\n        const request = this.api.post(\n            '/images/create',\n            {\n                fromImage: ref,\n                fromSrc: options?.fromSrc,\n                repo: options?.repo,\n                tag: options?.tag,\n                message: options?.message,\n                changes: options?.changes,\n                platform: options?.platform,\n                inputImage: options?.inputImage,\n            },\n            undefined,\n            headers,\n        );\n\n        return {\n            messages: async function* (): AsyncGenerator<\n                types.JSONMessage,\n                void,\n                undefined\n            > {\n                const response = await request;\n                yield* jsonMessages<types.JSONMessage>(response);\n            },\n            wait: async function (): Promise<string> {\n                let digest = '';\n                const response = await request;\n                for await (const message of jsonMessages<types.JSONMessage>(\n                    response,\n                )) {\n                    if (message.errorDetail) {\n                        throw new Error(message.errorDetail?.message);\n                    }\n                    if (message.status?.startsWith('Digest: ')) {\n                        digest = message.status.substring(8);\n                    }\n                }\n                return digest;\n            },\n        };\n    }\n\n    private parseDockerRef(ref: string | undefined) {\n        if (ref && !ref.includes('/')) {\n            ref = `docker.io/library/${ref}`;\n        } else if (\n            ref &&\n            ref.startsWith('docker.io/') &&\n            ref.split('/').length === 2\n        ) {\n            ref = ref.replace('docker.io/', 'docker.io/library/');\n        }\n        return ref;\n    }\n\n    /**\n     * Remove an image, along with any untagged parent images that were referenced by that image.  Images can\\'t be removed if they have descendant images, are being used by a running container or are being used by a build.\n     * Remove an image\n     * @param name Image name or ID\n     * @param options\n     * @param options.force Remove the image even if it is being used by stopped containers or has other tags\n     * @param options.noprune Do not delete untagged parent images\n     * @param options.platforms Select platform-specific content to delete. Multiple values are accepted. Each platform is a OCI platform encoded as a JSON string.\n     */\n    public async imageDelete(\n        name: string,\n        options?: {\n            force?: boolean;\n            noprune?: boolean;\n            platforms?: Array<string>;\n        },\n    ): Promise<Array<types.ImageDeleteResponseItem>> {\n        const response = await this.api.delete(`/images/${name}`, options);\n        return response.json() as Promise<Array<types.ImageDeleteResponseItem>>;\n    }\n\n    /**\n     * Get a tarball containing all images and metadata for a repository.  If `name` is a specific name and tag (e.g. `ubuntu:latest`), then only that image (and its parents) are returned. If `name` is an image ID, similarly only that image (and its parents) are returned, but with the exclusion of the `repositories` file in the tarball, as there were no image names referenced.  ### Image tarball format  An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).  Additionally, includes the manifest.json file associated with a backwards compatible docker save format.  If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.  ```json {   \\\"hello-world\\\": {     \\\"latest\\\": \\\"565a9d68a73f6706862bfe8409a7f659776d4d60a8d096eb4a3cbce6999cc2a1\\\"   } } ```\n     * Export an image\n     * @param name Image name or ID\n     * @param w stream to write the tarball to\n     * @param platform JSON encoded OCI platform describing a platform which will be used to select a platform-specific image to be saved if the image is multi-platform. If not provided, the full multi-platform image will be saved.  Example: &#x60;{\\&quot;os\\&quot;: \\&quot;linux\\&quot;, \\&quot;architecture\\&quot;: \\&quot;arm\\&quot;, \\&quot;variant\\&quot;: \\&quot;v5\\&quot;}&#x60;\n     */\n    public async imageGet(\n        name: string,\n        w: WritableStream,\n        platform?: types.Platform,\n    ): Promise<void> {\n        const response = await this.api.get(\n            `/images/${name}/get`,\n            'application/x-tar',\n            {\n                platform: platform,\n            },\n        );\n        await response.body?.pipeTo(w);\n    }\n\n    /**\n     * Get a tarball containing all images and metadata for several image repositories.  For each value of the `names` parameter: if it is a specific name and tag (e.g. `ubuntu:latest`), then only that image (and its parents) are returned; if it is an image ID, similarly only that image (and its parents) are returned and there would be no names referenced in the \\'repositories\\' file for this image ID.  For details on the format, see the [export image endpoint](#operation/ImageGet).\n     * Export several images\n     * @param names Image names to filter by\n     * @param platform JSON encoded OCI platform(s) which will be used to select the platform-specific image(s) to be saved if the image is multi-platform. If not provided, the full multi-platform image will be saved.  Example: &#x60;{\\&quot;os\\&quot;: \\&quot;linux\\&quot;, \\&quot;architecture\\&quot;: \\&quot;arm\\&quot;, \\&quot;variant\\&quot;: \\&quot;v5\\&quot;}&#x60;\n     */\n    public async imageGetAll(\n        names: Array<string>,\n        platform?: types.Platform,\n    ): Promise<ReadableStream> {\n        const response = await this.api.get(\n            `/images/get`,\n            'application/x-tar',\n            {\n                names: names,\n                platform: platform,\n            },\n        );\n        if (!response.body) {\n            throw new Error('No response body');\n        }\n        return response.body;\n    }\n\n    /**\n     * Return parent layers of an image.\n     * Get the history of an image\n     * @param name Image name or ID\n     * @param options\n     * @param options.platform JSON-encoded OCI platform to select the platform-variant. If omitted, it defaults to any locally available platform, prioritizing the daemon\\&#39;s host platform.  If the daemon provides a multi-platform image store, this selects the platform-variant to show the history for. If the image is a single-platform image, or if the multi-platform image does not provide a variant matching the given platform, an error is returned.  Example: '{\\&quot;os\\&quot;: \\&quot;linux\\&quot;, \\&quot;architecture\\&quot;: \\&quot;arm\\&quot;, \\&quot;variant\\&quot;: \\&quot;v5\\&quot;}'\n     */\n    public async imageHistory(\n        name: string,\n        options?: {\n            platform?: string;\n        },\n    ): Promise<Array<types.HistoryResponseItem>> {\n        return this.api.getJSON(`/image/${name}/history`, options);\n    }\n\n    /**\n     * Return low-level information about an image.\n     * Inspect an image\n     * @param name Image name or id\n     * @param options\n     * @param options.manifests Include Manifests in the image summary.\n     */\n    public async imageInspect(\n        name: string,\n        options?: {\n            manifests?: boolean;\n        },\n    ): Promise<types.ImageInspect> {\n        return this.api.getJSON(`/images/${name}/json`, options);\n    }\n\n    /**\n     * Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image.\n     * List Images\n     * @param options\n     * @param options.all Show all images. Only images from a final layer (no children) are shown by default.\n     * @param options.filters A JSON encoded value of the filters (a 'map[string][]string') to process on the images list.  Available filters:  - 'before''('&lt;image-name&gt;[:&lt;tag&gt;]',  '&lt;image id&gt;' or '&lt;image@digest&gt;') - 'dangling'true' - 'label'key' or 'label'\\&quot;key'value\\&quot;' of an image label - 'reference''('&lt;image-name&gt;[:&lt;tag&gt;]') - 'since''('&lt;image-name&gt;[:&lt;tag&gt;]',  '&lt;image id&gt;' or '&lt;image@digest&gt;') - 'until'&lt;timestamp&gt;'\n     * @param options.sharedSize Compute and show shared size as a 'SharedSize' field on each image.\n     * @param options.digests Show digest information as a 'RepoDigests' field on each image.\n     * @param options.manifests Include 'Manifests' in the image summary.\n     */\n    public async imageList(options?: {\n        all?: boolean;\n        filters?: Filter;\n        sharedSize?: boolean;\n        digests?: boolean;\n        manifests?: boolean;\n    }): Promise<Array<types.ImageSummary>> {\n        return this.api.getJSON('/images/json', options);\n    }\n\n    /**\n     * Load a set of images and tags into a repository.  For details on the format, see the [export image endpoint](#operation/ImageGet).\n     * Import images\n     * @param quiet Suppress progress details during load.\n     * @param platform JSON encoded OCI platform(s) which will be used to select the platform-specific image(s) to load if the image is multi-platform. If not provided, the full multi-platform image will be loaded.  Example: &#x60;{\\&quot;os\\&quot;: \\&quot;linux\\&quot;, \\&quot;architecture\\&quot;: \\&quot;arm\\&quot;, \\&quot;variant\\&quot;: \\&quot;v5\\&quot;}&#x60;\n     * @param imagesTarball Tar archive containing images\n     */\n    public async imageLoad(\n        imagesTarball: ReadableStream,\n        options?: {\n            quiet?: boolean;\n            platform?: Platform;\n            callback?: (event: any) => void;\n        },\n    ): Promise<void> {\n        await this.api.post(`/images/load`, options, imagesTarball, {\n            'Content-Type': 'application/x-tar',\n        });\n    }\n\n    /**\n     * Delete unused images\n     * @param filters Filters to process on the prune list, encoded as JSON (a &#x60;map[string][]string&#x60;). Available filters:  - &#x60;dangling&#x3D;&lt;boolean&gt;&#x60; When set to &#x60;true&#x60; (or &#x60;1&#x60;), prune only    unused *and* untagged images. When set to &#x60;false&#x60;    (or &#x60;0&#x60;), all unused images are pruned. - &#x60;until&#x3D;&lt;string&gt;&#x60; Prune images created before this timestamp. The &#x60;&lt;timestamp&gt;&#x60; can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. &#x60;10m&#x60;, &#x60;1h30m&#x60;) computed relative to the daemon machine’s time. - &#x60;label&#x60; (&#x60;label&#x3D;&lt;key&gt;&#x60;, &#x60;label&#x3D;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;, &#x60;label!&#x3D;&lt;key&gt;&#x60;, or &#x60;label!&#x3D;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;) Prune images with (or without, in case &#x60;label!&#x3D;...&#x60; is used) the specified labels.\n     */\n    public async imagePrune(\n        filters?: Filter,\n    ): Promise<types.ImagePruneResponse> {\n        const response = await this.api.post(`/images/prune`, {\n            filters: filters,\n        });\n        return response.json() as Promise<types.ImagePruneResponse>;\n    }\n\n    /**\n     * Push an image to a registry.  If you wish to push an image on to a private registry, that image must already have a tag which references the registry. For example, `registry.example.com/myimage:latest`.  The push is cancelled if the HTTP connection is closed.\n     * Push an image\n     * @param name Name of the image to push. For example, &#x60;registry.example.com/myimage&#x60;. The image must be present in the local image store with the same name.  The name should be provided without tag; if a tag is provided, it is ignored. For example, &#x60;registry.example.com/myimage:latest&#x60; is considered equivalent to &#x60;registry.example.com/myimage&#x60;.  Use the &#x60;tag&#x60; parameter to specify the tag to push.\n     * @param options push options including credentials\n     * @param options.credentials A base64url-encoded auth configuration.  Refer to the [authentication section](#section/Authentication) for details.\n     * @param options.tag Tag of the image to push. For example, &#x60;latest&#x60;. If no tag is provided, all tags of the given image that are present in the local image store are pushed.\n     * @param options.platform JSON-encoded OCI platform to select the platform-variant to push. If not provided, all available variants will attempt to be pushed.  If the daemon provides a multi-platform image store, this selects the platform-variant to push to the registry. If the image is a single-platform image, or if the multi-platform image does not provide a variant matching the given platform, an error is returned.  Example: &#x60;{\\&quot;os\\&quot;: \\&quot;linux\\&quot;, \\&quot;architecture\\&quot;: \\&quot;arm\\&quot;, \\&quot;variant\\&quot;: \\&quot;v5\\&quot;}&#x60;\n     */\n    public imagePush(\n        name: string,\n        options: {\n            credentials?: AuthConfig;\n            tag?: string;\n            platform?: Platform;\n        },\n    ): JSONMessages<JSONMessage, void> {\n        const headers: Record<string, string> = {};\n\n        if (options?.credentials) {\n            headers['X-Registry-Auth'] = this.authCredentials(\n                options.credentials,\n            );\n        }\n\n        const request = this.api.post(\n            `/images/${name}/push`,\n            {\n                tag: options?.tag,\n                platform: options?.platform,\n            },\n            undefined,\n            headers,\n        );\n\n        return {\n            messages: async function* (): AsyncGenerator<\n                types.JSONMessage,\n                void,\n                undefined\n            > {\n                const response = await request;\n                yield* jsonMessages<types.JSONMessage>(response);\n            },\n            wait: async function (): Promise<void> {\n                const response = await request;\n                for await (const message of jsonMessages<types.JSONMessage>(\n                    response,\n                )) {\n                    if (message.errorDetail) {\n                        throw new Error(message.errorDetail?.message);\n                    }\n                    // noop\n                }\n            },\n        };\n    }\n\n    /**\n     * Tag an image so that it becomes part of a repository.\n     * Tag an image\n     * @param name Image name or ID to tag.\n     * @param repo The repository to tag in. For example, &#x60;someuser/someimage&#x60;.\n     * @param tag The name of the new tag.\n     */\n    public async imageTag(\n        name: string,\n        repo: string,\n        tag: string,\n    ): Promise<void> {\n        await this.api.post(`/images/${name}/tag`, {\n            repo: repo,\n            tag: tag,\n        });\n    }\n\n    // -- Exec\n\n    /**\n     * Run a command inside a running container\n     * Create an exec instance\n     * @param id ID or name of container\n     * @param execConfig Exec configuration options\n     * @returns Promise that resolves to exec instance ID response\n     */\n    public async containerExec(\n        id: string,\n        execConfig: types.ExecConfig,\n    ): Promise<types.IDResponse> {\n        const response = await this.api.post(\n            `/containers/${id}/exec`,\n            undefined,\n            execConfig,\n        );\n        return response.json() as Promise<types.IDResponse>;\n    }\n\n    /**\n     * Return low-level information about an exec instance\n     * Inspect an exec instance\n     * @param id Exec instance ID\n     * @returns Promise that resolves to exec instance details\n     */\n    public async execInspect(id: string): Promise<types.ExecInspectResponse> {\n        return this.api.getJSON(`/exec/${id}/json`);\n    }\n\n    /**\n     * Resize the TTY session used by an exec instance\n     * Resize an exec instance\n     * @param id Exec instance ID\n     * @param width Width of the TTY session in characters\n     * @param height Height of the TTY session in characters\n     * @returns Promise that resolves when the resize is complete\n     */\n    public async execResize(\n        id: string,\n        width: number,\n        height: number,\n    ): Promise<void> {\n        await this.api.post(`/exec/${id}/resize`, {\n            w: width,\n            h: height,\n        });\n    }\n\n    /**\n     * Start an exec instance\n     * @param id Exec instance ID\n     * @param stdout Optional stream to write stdout content\n     * @param stderr Optional stream to write stderr content\n     * @param execStartConfig Configuration options for starting the exec instance\n     * @returns Promise that resolves when the exec instance completes\n     */\n    public async execStart(\n        id: string,\n        stdout: stream.Writable | null,\n        stderr: stream.Writable | null,\n        execStartConfig?: types.ExecStartConfig,\n    ): Promise<void> {\n        if (execStartConfig?.Detach) {\n            await this.api.post(`/exec/${id}/start`, execStartConfig);\n        } else {\n            if (isWritable(stdout)) {\n                const response = await this.api.upgrade(\n                    `/exec/${id}/start`,\n                    execStartConfig,\n                );\n                switch (response.content) {\n                    case DOCKER_RAW_STREAM:\n                        response.socket.pipe(stdout);\n                        break;\n                    case DOCKER_MULTIPLEXED_STREAM:\n                        if (isWritable(stderr)) {\n                            response.socket.pipe(\n                                demultiplexStream(stdout, stderr),\n                            );\n                            break;\n                        } else {\n                            throw new Error(\n                                'stderr is required to process multiplexed stream',\n                            );\n                        }\n                    default:\n                        throw new Error(\n                            'Unsupported content type: ' + response.content,\n                        );\n                }\n                return new Promise((resolve, reject) => {\n                    response.socket.once('error', reject);\n                    response.socket.once('close', resolve);\n                });\n            } else {\n                throw new Error('stdout is required to process stream');\n            }\n        }\n    }\n}\n\nfunction isWritable(w: Writable | null): w is Writable {\n    return w !== null;\n}\n\nexport interface JSONMessages<T, R> {\n    messages(): AsyncGenerator<T, void, undefined>;\n    wait(): Promise<R>;\n}\n","import { Writable } from 'stream';\n\n// Logger handles container logs and calls a callback for each line\nexport class Logger extends Writable {\n    private buffer: string = '';\n    private callback: (line: string) => void;\n\n    constructor(callback: (line: string) => void) {\n        super({ objectMode: false });\n        this.callback = callback;\n    }\n\n    override _write(\n        chunk: any,\n        encoding: BufferEncoding,\n        callback: (error?: Error | null) => void,\n    ): void {\n        console.log(chunk.toString());\n        try {\n            this.buffer += chunk.toString();\n\n            let newlineIndex;\n            while ((newlineIndex = this.buffer.indexOf('\\n')) !== -1) {\n                const line = this.buffer.substring(0, newlineIndex);\n                this.buffer = this.buffer.substring(newlineIndex + 1);\n                this.callback(line);\n            }\n\n            callback();\n        } catch (error) {\n            callback(error instanceof Error ? error : new Error(String(error)));\n        }\n    }\n\n    override _final(callback: (error?: Error | null) => void): void {\n        try {\n            if (this.buffer.length > 0) {\n                this.callback(this.buffer);\n                this.buffer = '';\n            }\n            callback();\n        } catch (error) {\n            callback(error instanceof Error ? error : new Error(String(error)));\n        }\n    }\n}\n","import type {\n    Agent,\n    Response as UndiciResponse,\n    RequestInit as UndiciRequestInit,\n} from 'undici';\nimport { fetch } from 'undici';\nimport type {\n    OCIImageIndex,\n    OCIManifest,\n    RegistryAuth,\n    RegistryErrorResponse,\n    TagsList,\n} from './types/index.js';\n\n/**\n * OCI Distribution Specification media types\n */\nexport const MediaTypes = {\n    // Manifest types\n    MANIFEST_V2: 'application/vnd.docker.distribution.manifest.v2+json',\n    MANIFEST_LIST_V2:\n        'application/vnd.docker.distribution.manifest.list.v2+json',\n    OCI_MANIFEST_V1: 'application/vnd.oci.image.manifest.v1+json',\n    OCI_INDEX_V1: 'application/vnd.oci.image.index.v1+json',\n\n    // Config types\n    CONTAINER_IMAGE_V1: 'application/vnd.docker.container.image.v1+json',\n    OCI_CONFIG_V1: 'application/vnd.oci.image.config.v1+json',\n\n    // Layer types\n    IMAGE_LAYER: 'application/vnd.docker.image.rootfs.diff.tar.gzip',\n    IMAGE_LAYER_FOREIGN:\n        'application/vnd.docker.image.rootfs.foreign.diff.tar.gzip',\n    OCI_LAYER: 'application/vnd.oci.image.layer.v1.tar+gzip',\n} as const;\n\n/**\n * Custom error class for registry-specific errors\n */\nexport class RegistryError extends Error {\n    public code: string;\n    public statusCode?: number;\n    public detail?: any;\n\n    constructor(\n        message: string,\n        code: string,\n        statusCode?: number,\n        detail?: any,\n    ) {\n        super(message);\n        this.name = 'RegistryError';\n        this.code = code;\n        this.statusCode = statusCode;\n        this.detail = detail;\n    }\n}\n\n/**\n * OCI Registry Client\n *\n * Implements the OCI Distribution Specification for interacting with container registries.\n * Supports manifest operations, blob operations, and tag management.\n *\n * @example\n * ```typescript\n * const client = new RegistryClient('https://registry-1.docker.io', {\n *   username: 'myuser',\n *   password: 'mypassword'\n * });\n *\n * // Read a manifest\n * const manifest = await client.getManifest('library/nginx', 'latest');\n *\n * // List tags\n * const tags = await client.listTags('library/nginx');\n * ```\n */\nexport class RegistryClient {\n    private baseUrl: string;\n    private auth?: RegistryAuth;\n    private agent?: Agent;\n    private userAgent: string;\n    private bearerToken?: string;\n    private tokenExpiry?: number;\n\n    /**\n     * Create a new RegistryClient\n     *\n     * @param baseUrl - Base URL of the registry (e.g., 'https://registry-1.docker.io')\n     * @param auth - Optional authentication credentials\n     * @param agent - Optional undici Agent for custom connection handling\n     * @param userAgent - Optional custom User-Agent header\n     */\n    constructor(\n        baseUrl: string,\n        auth?: RegistryAuth,\n        agent?: Agent,\n        userAgent: string = 'oci-registry-client/1.0',\n    ) {\n        this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n        this.auth = auth;\n        this.agent = agent;\n        this.userAgent = userAgent;\n    }\n\n    /**\n     * Close the client and cleanup resources\n     */\n    public async close(): Promise<void> {\n        if (this.agent) {\n            await this.agent.destroy();\n        }\n    }\n\n    /**\n     * Get a manifest from the registry\n     *\n     * @param repository - Repository name (e.g., 'library/nginx')\n     * @param reference - Tag or digest (e.g., 'latest' or 'sha256:...')\n     * @returns The manifest object (either Manifest or Index depending on media type)\n     *\n     * @example\n     * ```typescript\n     * const manifest = await client.getManifest('library/nginx', 'latest');\n     * console.log(manifest.config.digest);\n     * ```\n     */\n    public async getManifest(\n        repository: string,\n        reference: string,\n    ): Promise<OCIManifest | OCIImageIndex> {\n        const url = `${this.baseUrl}/v2/${repository}/manifests/${reference}`;\n        const headers = this.buildHeaders({\n            Accept: [\n                MediaTypes.OCI_MANIFEST_V1,\n                MediaTypes.OCI_INDEX_V1,\n                MediaTypes.MANIFEST_V2,\n                MediaTypes.MANIFEST_LIST_V2,\n            ].join(', '),\n        });\n\n        const response = await this.fetch(url, { headers });\n        await this.handleResponse(response);\n\n        return response.json() as Promise<OCIManifest | OCIImageIndex>;\n    }\n\n    /**\n     * Check if a manifest exists and get its digest\n     *\n     * @param repository - Repository name\n     * @param reference - Tag or digest\n     * @returns The manifest digest from the Docker-Content-Digest header\n     *\n     * @example\n     * ```typescript\n     * const digest = await client.headManifest('library/nginx', 'latest');\n     * console.log(digest); // sha256:...\n     * ```\n     */\n    public async resolve(\n        repository: string,\n        reference: string,\n    ): Promise<string> {\n        const url = `${this.baseUrl}/v2/${repository}/manifests/${reference}`;\n        const headers = this.buildHeaders({\n            Accept: [\n                MediaTypes.OCI_MANIFEST_V1,\n                MediaTypes.OCI_INDEX_V1,\n                MediaTypes.MANIFEST_V2,\n                MediaTypes.MANIFEST_LIST_V2,\n            ].join(', '),\n        });\n\n        const response = await this.fetch(url, {\n            method: 'HEAD',\n            headers,\n        });\n        await this.handleResponse(response);\n\n        const digest = response.headers.get('Docker-Content-Digest');\n        if (!digest) {\n            throw new Error(\n                'Docker-Content-Digest header not found in response',\n            );\n        }\n\n        return digest;\n    }\n\n    /**\n     * Push a manifest to the registry\n     *\n     * @param repository - Repository name\n     * @param reference - Tag or digest\n     * @param manifest - The manifest object to push\n     * @returns The digest of the uploaded manifest\n     *\n     * @example\n     * ```typescript\n     * const manifest = {\n     *   schemaVersion: 2,\n     *   mediaType: MediaTypes.OCI_MANIFEST_V1,\n     *   config: {...},\n     *   layers: [...]\n     * };\n     * const digest = await client.putManifest('myrepo/myimage', 'v1.0', manifest);\n     * ```\n     */\n    public async putManifest(\n        repository: string,\n        reference: string,\n        manifest: OCIManifest | OCIImageIndex,\n    ): Promise<string> {\n        const url = `${this.baseUrl}/v2/${repository}/manifests/${reference}`;\n        const body = JSON.stringify(manifest);\n        const headers = this.buildHeaders({\n            'Content-Type': manifest.mediaType || MediaTypes.OCI_MANIFEST_V1,\n            'Content-Length': String(Buffer.byteLength(body)),\n        });\n\n        const response = await this.fetch(url, {\n            method: 'PUT',\n            headers,\n            body,\n        });\n        await this.handleResponse(response);\n\n        const digest = response.headers.get('Docker-Content-Digest');\n        if (!digest) {\n            throw new Error(\n                'Docker-Content-Digest header not found in response',\n            );\n        }\n\n        return digest;\n    }\n\n    /**\n     * Delete a manifest from the registry\n     *\n     * @param repository - Repository name\n     * @param digest - Manifest digest (must be a digest, not a tag)\n     *\n     * @example\n     * ```typescript\n     * await client.deleteManifest('myrepo/myimage', 'sha256:abc123...');\n     * ```\n     */\n    public async deleteManifest(\n        repository: string,\n        digest: string,\n    ): Promise<void> {\n        if (!digest.startsWith('sha256:') && !digest.startsWith('sha512:')) {\n            throw new Error('deleteManifest requires a digest, not a tag');\n        }\n\n        const url = `${this.baseUrl}/v2/${repository}/manifests/${digest}`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, {\n            method: 'DELETE',\n            headers,\n        });\n        await this.handleResponse(response);\n    }\n\n    /**\n     * Get a blob from the registry\n     *\n     * @param repository - Repository name\n     * @param digest - Blob digest\n     * @returns ReadableStream of the blob content\n     *\n     * @example\n     * ```typescript\n     * const stream = await client.getBlob('library/nginx', 'sha256:abc123...');\n     * // Pipe to file or process the stream\n     * ```\n     */\n    public async getBlob(\n        repository: string,\n        digest: string,\n    ): Promise<ReadableStream> {\n        const url = `${this.baseUrl}/v2/${repository}/blobs/${digest}`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, { headers });\n        await this.handleResponse(response);\n\n        if (!response.body) {\n            throw new Error('No response body received');\n        }\n\n        return response.body;\n    }\n\n    /**\n     * Check if a blob exists\n     *\n     * @param repository - Repository name\n     * @param digest - Blob digest\n     * @returns Boolean indicating if the blob exists\n     *\n     * @example\n     * ```typescript\n     * const exists = await client.headBlob('library/nginx', 'sha256:abc123...');\n     * if (!exists) {\n     *   // Upload the blob\n     * }\n     * ```\n     */\n    public async headBlob(\n        repository: string,\n        digest: string,\n    ): Promise<boolean> {\n        const url = `${this.baseUrl}/v2/${repository}/blobs/${digest}`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, {\n            method: 'HEAD',\n            headers,\n        });\n\n        return response.status === 200;\n    }\n\n    /**\n     * Delete a blob from the registry\n     *\n     * @param repository - Repository name\n     * @param digest - Blob digest\n     *\n     * @example\n     * ```typescript\n     * await client.deleteBlob('myrepo/myimage', 'sha256:abc123...');\n     * ```\n     */\n    public async deleteBlob(repository: string, digest: string): Promise<void> {\n        const url = `${this.baseUrl}/v2/${repository}/blobs/${digest}`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, {\n            method: 'DELETE',\n            headers,\n        });\n        await this.handleResponse(response);\n    }\n\n    /**\n     * Initiate a blob upload\n     *\n     * @param repository - Repository name\n     * @returns Upload location URL\n     *\n     * @example\n     * ```typescript\n     * const uploadUrl = await client.initiateUpload('myrepo/myimage');\n     * // Use uploadUrl for chunked upload or monolithic upload\n     * ```\n     */\n    public async initiateUpload(repository: string): Promise<string> {\n        const url = `${this.baseUrl}/v2/${repository}/blobs/uploads/`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, {\n            method: 'POST',\n            headers,\n        });\n        await this.handleResponse(response);\n\n        const location = response.headers.get('Location');\n        if (!location) {\n            throw new Error(\n                'Location header not found in upload initiation response',\n            );\n        }\n\n        // Handle relative URLs\n        if (location.startsWith('http://') || location.startsWith('https://')) {\n            return location;\n        }\n        return `${this.baseUrl}${location}`;\n    }\n\n    /**\n     * Upload a blob in a single request (monolithic upload)\n     *\n     * @param repository - Repository name\n     * @param blob - Blob content as ReadableStream or Buffer\n     * @param digest - Expected digest of the blob\n     * @returns The digest of the uploaded blob\n     *\n     * @example\n     * ```typescript\n     * const blobData = Buffer.from('layer content...');\n     * const digest = await client.uploadBlob('myrepo/myimage', blobData, 'sha256:abc123...');\n     * ```\n     */\n    public async uploadBlob(\n        repository: string,\n        blob: ReadableStream | Buffer,\n        digest: string,\n    ): Promise<string> {\n        const uploadUrl = await this.initiateUpload(repository);\n\n        // Add digest parameter to complete the upload\n        const url = new URL(uploadUrl);\n        url.searchParams.set('digest', digest);\n\n        const headers = this.buildHeaders({\n            'Content-Type': 'application/octet-stream',\n        });\n\n        const body = blob instanceof Buffer ? blob : blob;\n\n        const response = await this.fetch(url.toString(), {\n            method: 'PUT',\n            headers,\n            body: body as any,\n        });\n        await this.handleResponse(response);\n\n        const resultDigest = response.headers.get('Docker-Content-Digest');\n        if (!resultDigest) {\n            throw new Error(\n                'Docker-Content-Digest header not found in response',\n            );\n        }\n\n        return resultDigest;\n    }\n\n    /**\n     * List tags for a repository\n     *\n     * @param repository - Repository name\n     * @param n - Maximum number of tags to return (optional)\n     * @param last - Last tag from previous request for pagination (optional)\n     * @returns TagsList containing repository name and array of tags\n     *\n     * @example\n     * ```typescript\n     * const tags = await client.listTags('library/nginx');\n     * console.log(tags.tags); // ['latest', '1.21', '1.20', ...]\n     *\n     * // With pagination\n     * const firstPage = await client.listTags('library/nginx', 10);\n     * const secondPage = await client.listTags('library/nginx', 10, firstPage.tags[9]);\n     * ```\n     */\n    public async listTags(\n        repository: string,\n        n?: number,\n        last?: string,\n    ): Promise<TagsList> {\n        const url = new URL(`${this.baseUrl}/v2/${repository}/tags/list`);\n        if (n !== undefined) {\n            url.searchParams.set('n', String(n));\n        }\n        if (last !== undefined) {\n            url.searchParams.set('last', last);\n        }\n\n        const headers = this.buildHeaders();\n        const response = await this.fetch(url.toString(), { headers });\n        await this.handleResponse(response);\n\n        return response.json() as Promise<TagsList>;\n    }\n\n    /**\n     * Check if the registry supports the OCI Distribution API\n     *\n     * @returns Boolean indicating if the v2 API is supported\n     *\n     * @example\n     * ```typescript\n     * const isSupported = await client.checkVersion();\n     * if (!isSupported) {\n     *   throw new Error('Registry does not support OCI Distribution API v2');\n     * }\n     * ```\n     */\n    public async checkVersion(): Promise<boolean> {\n        const url = `${this.baseUrl}/v2/`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, { headers });\n        return response.status === 200;\n    }\n\n    /**\n     * Ping the registry to check connectivity and authentication\n     *\n     * Sends a GET request to the /v2/ endpoint and verifies the response is 200 OK.\n     * This is useful for checking if the registry is reachable and if credentials are valid.\n     *\n     * @returns Promise that resolves if the registry responds with 200 OK\n     * @throws Error if the registry is not reachable or returns a non-200 status\n     *\n     * @example\n     * ```typescript\n     * try {\n     *   await client.ping();\n     *   console.log('Registry is reachable');\n     * } catch (error) {\n     *   console.error('Registry is not reachable:', error);\n     * }\n     * ```\n     */\n    public async ping(): Promise<void> {\n        const url = `${this.baseUrl}/v2/`;\n        const headers = this.buildHeaders();\n\n        const response = await this.fetch(url, { headers });\n\n        if (response.status !== 200) {\n            throw new Error(\n                `Registry ping failed: ${response.status} ${response.statusText}`,\n            );\n        }\n    }\n\n    /**\n     * Build request headers with authentication\n     */\n    private buildHeaders(\n        additional?: Record<string, string>,\n    ): Record<string, string> {\n        const headers: Record<string, string> = {\n            'User-Agent': this.userAgent,\n            ...additional,\n        };\n\n        // Add authentication headers\n        if (\n            this.bearerToken &&\n            this.tokenExpiry &&\n            Date.now() < this.tokenExpiry\n        ) {\n            headers.Authorization = `Bearer ${this.bearerToken}`;\n        } else if (this.auth?.token) {\n            headers.Authorization = `Bearer ${this.auth.token}`;\n        } else if (this.auth?.identityToken) {\n            headers.Authorization = `Bearer ${this.auth.identityToken}`;\n        } else if (this.auth?.username && this.auth?.password) {\n            const credentials = Buffer.from(\n                `${this.auth.username}:${this.auth.password}`,\n            ).toString('base64');\n            headers.Authorization = `Basic ${credentials}`;\n        }\n\n        return headers;\n    }\n\n    /**\n     * Wrapper around fetch to use the configured agent\n     */\n    private async fetch(\n        url: string,\n        options?: UndiciRequestInit,\n    ): Promise<UndiciResponse> {\n        const fetchOptions: UndiciRequestInit = {\n            ...options,\n            dispatcher: this.agent,\n        };\n\n        try {\n            return await fetch(url, fetchOptions);\n        } catch (error) {\n            // Handle WWW-Authenticate challenge for token-based auth\n            if (error instanceof Error && error.message.includes('401')) {\n                // Try to handle auth challenge and retry\n                await this.handleAuthChallenge(url);\n                return fetch(url, {\n                    ...fetchOptions,\n                    headers: this.buildHeaders(\n                        options?.headers as Record<string, string>,\n                    ),\n                });\n            }\n            throw error;\n        }\n    }\n\n    /**\n     * Handle authentication challenges (WWW-Authenticate)\n     */\n    private async handleAuthChallenge(url: string): Promise<void> {\n        // First, make a request to get the auth challenge\n        const response = await fetch(url, {\n            dispatcher: this.agent,\n            headers: {\n                'User-Agent': this.userAgent,\n            },\n        });\n\n        if (response.status === 401) {\n            const wwwAuth = response.headers.get('WWW-Authenticate');\n            if (wwwAuth && wwwAuth.startsWith('Bearer ')) {\n                // Parse the challenge\n                const challenge = this.parseAuthChallenge(wwwAuth);\n                if (challenge.realm) {\n                    // Request a token\n                    await this.fetchBearerToken(\n                        challenge.realm,\n                        challenge.service,\n                        challenge.scope,\n                    );\n                }\n            }\n        }\n    }\n\n    /**\n     * Parse WWW-Authenticate challenge header\n     */\n    private parseAuthChallenge(header: string): {\n        realm?: string;\n        service?: string;\n        scope?: string;\n    } {\n        const challenge: { realm?: string; service?: string; scope?: string } =\n            {};\n\n        // Remove \"Bearer \" prefix\n        const params = header.substring(7);\n\n        // Parse key=\"value\" pairs\n        const regex = /(\\w+)=\"([^\"]+)\"/g;\n        let match;\n        while ((match = regex.exec(params)) !== null) {\n            const key = match[1];\n            const value = match[2];\n            if (key === 'realm' || key === 'service' || key === 'scope') {\n                challenge[key] = value;\n            }\n        }\n\n        return challenge;\n    }\n\n    /**\n     * Fetch a bearer token from the auth service\n     */\n    private async fetchBearerToken(\n        realm: string,\n        service?: string,\n        scope?: string,\n    ): Promise<void> {\n        const url = new URL(realm);\n        if (service) {\n            url.searchParams.set('service', service);\n        }\n        if (scope) {\n            url.searchParams.set('scope', scope);\n        }\n\n        const headers: Record<string, string> = {\n            'User-Agent': this.userAgent,\n        };\n\n        // Add basic auth if credentials are provided\n        if (this.auth?.username && this.auth?.password) {\n            const credentials = Buffer.from(\n                `${this.auth.username}:${this.auth.password}`,\n            ).toString('base64');\n            headers.Authorization = `Basic ${credentials}`;\n        }\n\n        const response = await fetch(url.toString(), {\n            headers,\n            dispatcher: this.agent,\n        });\n\n        if (!response.ok) {\n            throw new Error(`Failed to fetch bearer token: ${response.status}`);\n        }\n\n        const tokenResponse = (await response.json()) as {\n            token?: string;\n            access_token?: string;\n            expires_in?: number;\n        };\n\n        this.bearerToken = tokenResponse.token || tokenResponse.access_token;\n        if (tokenResponse.expires_in) {\n            this.tokenExpiry = Date.now() + tokenResponse.expires_in * 1000;\n        }\n    }\n\n    /**\n     * Handle response errors\n     */\n    private async handleResponse(response: UndiciResponse): Promise<void> {\n        if (!response.ok) {\n            let errorMessage = `Registry request failed: ${response.status} ${response.statusText}`;\n            let errorCode = 'UNKNOWN';\n            let detail: any = undefined;\n\n            try {\n                const contentType = response.headers.get('Content-Type');\n                if (contentType?.includes('application/json')) {\n                    const errorResponse =\n                        (await response.json()) as RegistryErrorResponse;\n                    if (\n                        errorResponse.errors &&\n                        errorResponse.errors.length > 0\n                    ) {\n                        const firstError = errorResponse.errors[0];\n                        if (firstError) {\n                            errorMessage = firstError.message;\n                            errorCode = firstError.code;\n                            detail = firstError.detail;\n                        }\n                    }\n                }\n            } catch {\n                // Failed to parse error response, use default message\n            }\n\n            throw new RegistryError(\n                errorMessage,\n                errorCode,\n                response.status,\n                detail,\n            );\n        }\n    }\n}\n"],"mappings":"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"}