UNPKG

@enspirit/emb

Version:

A replacement for our Makefile-for-monorepos

56 lines (55 loc) 1.88 kB
import { execa } from 'execa'; export const DefaultGetContainerOptions = { mustBeRunning: true, mustBeUnique: true, }; export class DockerComposeClient { monorepo; containers; constructor(monorepo) { this.monorepo = monorepo; } async init() { await this.loadContainers(); } async getContainer(serviceName, options = DefaultGetContainerOptions) { const getOptions = { ...DefaultGetContainerOptions, ...options }; await this.loadContainers(); const service = this.containers?.get(serviceName); if (!service) { throw new Error(`No compose service found with name ${serviceName}`); } const containers = getOptions.mustBeRunning ? service.containers.filter((c) => c.State === 'running') : service.containers; if (containers.length === 0) { throw new Error(`No container found for service ${serviceName}`); } if (containers.length > 1 && getOptions.mustBeUnique) { throw new Error(`Multiple containers found`); } return containers[0].ID; } async loadContainers(force = false) { if (this.containers && !force) { return; } const { stdout } = await execa({ cwd: this.monorepo.rootDir, }) `docker compose ps -a --format json`; this.containers = stdout .split('\n') .map((l) => JSON.parse(l)) .reduce((services, entry) => { if (!services.has(entry.Service)) { services.set(entry.Service, { name: entry.Service, containers: [], }); } const svc = services.get(entry.Service); svc?.containers.push(entry); return services; }, new Map()); } }