// // Commands that are available whether or not the sidebar is showing: the // Extensions menu entries and anything that acts on the workspace rather than // on a sidebar selection. // const { ContainerCLI } = require("./Interfaces/ContainerCLI"); const { ComposeCLI } = require("./Interfaces/ComposeCLI"); const { Terminal } = require("./Interfaces/Terminal"); const { Hostnames } = require("./Hostnames"); const systemConfig = require("./Utilities/SystemConfig"); const notify = require("./Utilities/Notify"); const prompt = require("./Utilities/Prompt"); class Commands { // `context` exposes the pieces owned by main.js, which are replaced when // the extension reloads. constructor(context) { this.context = context; this.disposables = new CompositeDisposable(); this.register(); } dispose() { this.disposables.dispose(); } add(command, handler) { this.disposables.add(nova.commands.register(command, handler)); } reloadSidebar() { let sidebar = this.context.sidebar(); if (sidebar) { sidebar.reload(); } } register() { this.add("apple_container.reload", () => this.reloadSidebar()); this.add("apple_container.preferences", () => nova.openConfig()); // System ------------------------------------------------------------ this.add("apple_container.system.start", async () => { try { await ContainerCLI.systemStart(); } catch (error) { notify.configFailure("Unable to start container services", error, "apple-container-system"); } this.reloadSidebar(); }); this.add("apple_container.system.stop", async () => { try { await ContainerCLI.systemStop(); } catch (error) { notify.failure("Unable to stop container services", error, "apple-container-system"); } this.reloadSidebar(); }); this.add("apple_container.system.restart", async () => { try { await ContainerCLI.systemStop(); await ContainerCLI.systemStart(); } catch (error) { notify.failure("Unable to restart container services", error, "apple-container-system"); } this.reloadSidebar(); }); this.add("apple_container.system.status", async () => { try { let result = await ContainerCLI.run(["system", "status"]); nova.workspace.openNewTextDocument({ content: result.stdout }); } catch (error) { notify.failure("Unable to read system status", error, "apple-container-system"); } }); this.add("apple_container.system.logs", () => Terminal.run(Terminal.command([ContainerCLI.path(), "system", "logs", "--follow"])) ); // Builder ----------------------------------------------------------- this.add("apple_container.builder.start", () => this.runBuilder(() => ContainerCLI.builderStart(), "Unable to start the builder") ); this.add("apple_container.builder.stop", () => this.runBuilder(() => ContainerCLI.builderStop(), "Unable to stop the builder") ); this.add("apple_container.builder.delete", async () => { if (!(await prompt.confirm("Delete the builder container?", "Delete"))) { return; } return this.runBuilder(() => ContainerCLI.builderDelete(), "Unable to delete the builder"); }); // Hostnames and DNS --------------------------------------------------- this.add("apple_container.dns.register", async () => { let domain = await prompt.input("Domain to resolve on this Mac", { placeholder: "test", value: systemConfig.defaultDomain() || "" }); if (!domain) { return; } await Hostnames.register(domain); }); this.add("apple_container.dns.openConfig", () => { let path = systemConfig.path(); if (path && nova.fs.access(path, nova.fs.R_OK)) { nova.workspace.openFile(path); } else { notify.info( "No system configuration yet", "Apple Container writes config.toml the first time a setting is changed.", "apple-container-config" ); } }); // Compose ----------------------------------------------------------- this.add("apple_container.compose.up", () => this.runCompose((file) => ComposeCLI.upArgs(file), "Compose up failed") ); this.add("apple_container.compose.down", () => this.runCompose((file) => ComposeCLI.downArgs(file), "Compose down failed") ); this.add("apple_container.compose.build", () => this.runCompose((file) => ComposeCLI.buildArgs(file), "Compose build failed") ); // Images ------------------------------------------------------------ this.add("apple_container.image.pullPrompt", async () => { let reference = await prompt.input("Image to pull", { placeholder: "docker.io/library/nginx:latest" }); if (!reference) { return; } // Pulls are slow and chatty, so they run where the progress shows. await Terminal.run(Terminal.command([ContainerCLI.path(), "image", "pull", reference])); }); this.add("apple_container.image.runPrompt", async () => { let reference = await prompt.input("Image to run", { placeholder: "docker.io/library/nginx:latest" }); if (!reference) { return; } let { runImage } = require("./Sidebar/TreeViews/Images"); await runImage(reference); }); this.add("apple_container.image.buildEditor", () => this.buildFromEditor()); // Language server ---------------------------------------------------- this.add("apple_container.lsp.restart", () => this.context.restartLanguageServer()); } async runBuilder(action, message) { try { await action(); } catch (error) { notify.failure(message, error, "apple-container-builder"); } this.reloadSidebar(); } async runCompose(build, message) { let file = ComposeCLI.defaultFile(); if (!file) { notify.configFailure( "No compose file found", "Add a compose file to the workspace, or set one in Project Settings.", "apple-container-compose-missing" ); return; } let directory = nova.path.dirname(file); let args = build(file); if (nova.config.get("apple_container.compose.terminal", "boolean") !== false) { await Terminal.run(Terminal.command([ComposeCLI.path()].concat(args)), directory); return; } try { await ComposeCLI.run(args, { cwd: directory }); } catch (error) { notify.failure(message, error, "apple-container-compose"); } this.reloadSidebar(); } // Builds an image from the Dockerfile in the frontmost editor. async buildFromEditor() { let editor = nova.workspace.activeTextEditor; let path = editor && editor.document ? editor.document.path : null; if (!path) { notify.info( "No file to build", "Open a Dockerfile or Containerfile first.", "apple-container-build" ); return; } let directory = nova.path.dirname(path); let suggestion = `${nova.path.basename(directory).toLowerCase().replace(/[^a-z0-9._-]/g, "-")}:latest`; let tag = await prompt.input("Tag for the built image", { placeholder: suggestion, value: suggestion }); if (!tag) { return; } await Terminal.run( Terminal.command([ContainerCLI.path(), "build", "--tag", tag, "--file", path, directory]) ); } } module.exports = { Commands };