/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { readdir } from "node:fs/promises";
import Dockerode from "dockerode";
import { Composition } from "./composition.js";
import { Container } from "./container.js";
import { DockerError } from "./errors.js";
class Docker {
  #intf = new Dockerode();
  get intf() {
    return this.#intf;
  }
  /**
   * Build a composition of multiple containers.
   */
  compose(name, config) {
    return new Composition(this, name, config);
  }
  /**
   * Ensure a container doesn't exist regardless of current state.
   */
  async erase(name) {
    const info = await this.containerStatus(name);
    if (info) {
      const ct = Container(this, this.#intf.getContainer(info.id));
      try {
        await ct.remove(true);
      } catch (e) {
        DockerError.accept(e, 404, 409);
      }
      return ct;
    }
  }
  /**
   * Obtain a running {@link Container}.  Connects to existing container or creates a new container.
   */
  async open(options) {
    const info = await this.containerStatus(options.name);
    if (info) {
      const ct2 = Container(this, this.#intf.getContainer(info.id));
      if (!info.isRunning) {
        await ct2.start();
      }
      return ct2;
    }
    const ct = await this.create(options);
    await ct.start();
    return ct;
  }
  async containerStatus(name) {
    try {
      const inspect = await DockerError.adapt(this.#intf.getContainer(name).inspect());
      return {
        name,
        id: inspect.Id,
        isRunning: inspect.State.Status === "running"
      };
    } catch (e) {
      DockerError.accept(e, 404);
    }
  }
  async create(config) {
    return Container(this, config);
  }
  async start(config) {
    const ct = await this.create(config);
    await DockerError.adapt(ct.start());
    return ct;
  }
  async pull(nameAndTag, platform) {
    const imageConfig = {
      fromImage: nameAndTag
    };
    if (platform !== void 0) {
      imageConfig.platform = platform;
    }
    const progress = await DockerError.adapt(this.#intf.createImage(imageConfig));
    await new Promise((resolve, reject) => {
      this.#intf.modem.followProgress(progress, (error) => {
        if (error) {
          reject(DockerError.translate(error));
        }
        resolve();
      });
    });
  }
  async buildImage(name, path) {
    const files = await readdir(path);
    const stream = await DockerError.adapt(
      this.#intf.buildImage(
        {
          context: path,
          src: files
        },
        {
          t: name
        }
      )
    );
    await new Promise((resolve, reject) => {
      this.#intf.modem.followProgress(stream, (error, result) => {
        if (error) {
          reject(DockerError.translate(error));
        }
        const finalMessage = result[result.length - 1];
        const errorMessage = finalMessage?.error ?? finalMessage?.errorDetail?.message;
        if (errorMessage) {
          reject(new Error(errorMessage));
        }
        resolve();
      });
    });
  }
}
export {
  Docker
};
//# sourceMappingURL=docker.js.map
