import { Colors, Path, FS, Compress, Base64 } from "../deps.ts"; import { getMeta, IMeta, log, getConfig } from "../global.ts"; import { ServerError } from "../helper/server_error.ts"; async function runScript(script: string) { console.log(Colors.bold(Colors.blue("Running script:")), script); const runPerm = await Deno.permissions.query({ name: "run", }); if (runPerm.state !== "granted") { console.log( Colors.red("Missing --allow-run permission. Cannot run hooks!") ); throw new Error("Missing --allow-run permission. Cannot run hooks!"); } const process = Deno.run({ cmd: ["deno", "run", "-A", "--unstable", script], }); const status = await process.status(); console.log(Colors.bold(Colors.blue("Finished script:")), script); if (!status.success) { throw new Error( "A hook did not complete sucessfully. This is not a issue of denreg!" ); } } async function runHooks(hooks: undefined | string | string[]) { if (!hooks) return; if (typeof hooks === "string") { hooks = [hooks]; } for (const hook of hooks) { await runScript(hook); } } export default async function publish(options: { dry: boolean }) { const meta: IMeta = await getMeta(); if (!meta.name) throw new Error("name is not set in meta.json"); if (!meta.version) throw new Error("version is not set in meta.json"); if (!meta.files || !Array.isArray(meta.files) || meta.files.length <= 0) throw new Error("files is not set or empty in meta.json"); if (meta.hooks) { log("Running prepublish hooks"); await runHooks(meta.hooks.prepublish); } const tmpDir = await Deno.makeTempDir(); const packedFile = (await Deno.makeTempFile()) + ".tar"; try { const walker = FS.walk(".", { includeDirs: false, includeFiles: true, match: meta.files.map((file) => Path.globToRegExp(file)), }); log("Copying files to package to", tmpDir); const copy = async (path: string) => { const dest = Path.join(tmpDir, path); await FS.ensureDir(Path.dirname(dest)); await FS.copy(path, dest); }; await copy("meta.json"); for await (const file of walker) { await copy(file.path); log("Adding file:", file.path); } log("Compressing files into", packedFile); await Compress.Tar.compress(tmpDir, packedFile, { excludeSrc: true, }); const url = new URL(getConfig("registry")); url.pathname = "/api/package/" + meta.name; if (!options.dry) { log("Uploading new package version"); await fetch(url, { method: "POST", body: await Deno.readFile(packedFile), headers: { Authorization: "Basic " + Base64.encode( getConfig("username") + ":" + getConfig("password") ), }, }) .then((res) => res.status === 200 ? res.json() : Promise.reject(new ServerError(res.statusText)) ) .then((res) => { if (!res.success) { throw new ServerError(res.message); } else { console.log(Colors.green("Upload successfull")); } }) .catch((err) => { //import { ServerError } from "../helper/server_error.ts"; if (err instanceof ServerError) console.log(Colors.red("Server Error: " + err.message)); else console.log(Colors.red("Error: " + err.message)); }); } else { console.log(Colors.yellow("Dry run. Skipping upload")); } if (meta.hooks) { log("Running postpublish hooks"); await runHooks(meta.hooks.postpublish); } } finally { await Deno.remove(tmpDir, { recursive: true }); await Deno.remove(packedFile); } }