import { mkdirSync, renameSync, rmSync } from "node:fs"; import { join } from "node:path"; import AdmZip from "adm-zip"; import chalk from "chalk"; import { Command } from "commander"; import { config } from "dotenv"; import fuzzy from "fuzzy"; import inquirer from "inquirer"; import autocomplete from "inquirer-autocomplete-standalone"; import { execShellCommand } from "./lib/execShellCommand.js"; import { importJson } from "./lib/importJson.js"; import { Server } from "./lib/Server.js"; config({ path: `${process.cwd()}/.env`, quiet: true }); function createZip(sourceDir: string, outputFile: string) { let zip = new AdmZip(); zip.addLocalFolder(sourceDir, sourceDir); zip.writeZip(outputFile); } /** * @param {string} pkgName * @param {{ bundle?: string | null }} options */ async function prepareBundle(pkgName: string, options: { bundle: string }) { try { let name: string; let version: string; if (pkgName) { let lastAtSign = pkgName.lastIndexOf("@"); if (lastAtSign > 0) { name = pkgName.substring(0, lastAtSign); version = pkgName.substring(lastAtSign + 1); } else { name = pkgName; version = await execShellCommand(`pnpm view ${pkgName} version`); version = version.trim(); } } else { let packageConfig = await importJson("./package.json", true); name = packageConfig.name; version = packageConfig.version; } let safePackageName = name.replace("@", "").replace("/", "-"); let rootOutputFolder = name.split("/")[0]; let tarball = `${safePackageName}-${version}.tgz`; let zipFileName = `${safePackageName}-${version}.zip`; let hostname = "dev.obet.no"; let server = new Server(hostname); let bundle = await server.getBundle(options.bundle ?? name); if (!bundle) { console.log("Bundle not found. Select a name to create it."); let namespaces = await server.getNamespaces(); let bundleName = options.bundle; if (!bundleName) { ({ bundleName } = await inquirer.prompt({ type: "input", name: "bundleName", message: "What is the name of the bundle?", default: name, })); } let namespace = await autocomplete({ message: "Select namespace", source: (input: string | undefined) => { return Promise.resolve( fuzzy .filter(input || "", namespaces, { extract: (el) => (el.GroupName ? `${el.Name} (${el.GroupName})` : el.Name), }) .map((el) => ({ name: el.original.GroupName ? `${el.original.Name} (${el.original.GroupName})` : el.original.Name, value: el.original.ID, })), ); }, }); if (bundleName) { await server.createBundle(bundleName, namespace); bundle = await server.getBundle(bundleName); } else { process.exit(0); } } let { ID: id, Project_ID } = bundle; if (id) { server.logServerMessage(`Found bundle with Version/Project ID: ${id}/${Project_ID}`); } else { console.log(chalk.yellow("No bundle found...")); } console.log("Removing previous..."); rmSync(rootOutputFolder, { recursive: true, force: true }); console.log("Packing..."); await execShellCommand(pkgName ? `npm pack ${pkgName}` : "npm pack"); console.log("Making output directory..."); mkdirSync(name, { recursive: true }); console.log(`Extracting '${tarball}'...`); await execShellCommand(`tar -xvzf ${tarball} -C ${name}`); console.log(`Moving from 'package' to '${version}'...`); renameSync(join(name, "package"), join(name, version)); console.log("Zipping..."); createZip(rootOutputFolder, zipFileName); console.log("Cleaning..."); rmSync(rootOutputFolder, { recursive: true, force: true }); rmSync(tarball); if (id) { await server.uploadBundle(Project_ID, id, zipFileName); rmSync(zipFileName); console.log("Done!"); } else { console.log("Launching explorer..."); try { await execShellCommand("explorer.exe ."); } catch { // Ignore errors } } } catch (error: any) { console.log(chalk.red(error.message)); console.log(error.inner); } } const cliPkg = await importJson("../package.json"); const program = new Command(); program .version(cliPkg.version) .argument("[package]", "Optional package name. If provided packs the npm package with name [package]") .option("-b, --bundle ", "Override bundle name from package.json") .action(prepareBundle); await program.parseAsync();