🏡 index : quine-global/quine-anaconda-webui.git

#!/usr/bin/env node
import esbuild from "esbuild";
import copy from "esbuild-plugin-copy";
import { sassPlugin } from "esbuild-sass-plugin";
import fs from "fs";
import path from "path";

import { cockpitPoEsbuildPlugin } from "./pkg/lib/cockpit-po-plugin.js";
import { cockpitRsyncEsbuildPlugin } from "./pkg/lib/cockpit-rsync-plugin.js";
import { cleanPlugin } from "./pkg/lib/esbuild-cleanup-plugin.js";
import { cockpitCompressPlugin } from "./pkg/lib/esbuild-compress-plugin.js";

const production = process.env.NODE_ENV === "production";
const watchMode = process.env.ESBUILD_WATCH === "true" || false;
/* List of directories to use when resolving import statements */
const nodePaths = ["pkg/lib"];
const outdir = "dist";

// Obtain package name from package.json
const packageJson = JSON.parse(fs.readFileSync("package.json"));

const getTime = () => new Date().toTimeString()
        .split(" ")[0];

// similar to fs.watch(), but recursively watches all subdirectories
function watchDirs (dir, onChange) {
    const callback = (ev, dir, fname) => {
        // only listen for "change" events, as renames are noisy
        // ignore hidden files and the "4913" temporary file created by vim
        const isHidden = /^\./.test(fname);
        if (ev !== "change" || isHidden || fname === "4913") {
            return;
        }
        onChange(path.join(dir, fname));
    };

    fs.watch(dir, {}, (ev, path) => callback(ev, dir, path));

    // watch all subdirectories in dir
    const d = fs.opendirSync(dir);
    let dirent;
    while ((dirent = d.readSync()) !== null) {
        if (dirent.isDirectory()) {
            watchDirs(path.join(dir, dirent.name), onChange);
        }
    }
    d.closeSync();
}

const context = await esbuild.context({
    bundle: true,
    entryPoints: ["./src/index.js", "./src/anacondaLogin.js"],
    external: ["*.woff", "*.woff2", "*.jpg", "*.svg", "../../assets*"],
    legalComments: "external", // Move all legal comments to a .LEGAL.txt file
    loader: {
        ".js": "jsx",
        ".py": "text",
        ".txt": "text",
    },
    minify: production,
    nodePaths,
    outdir,
    plugins: [
        cleanPlugin(),
        // Esbuild will only copy assets that are explicitly imported and used
        // in the code. This is a problem for index.html and manifest.json which are not imported
        copy({
            assets: [
                { from: ["./images/qr-code-feedback.svg"], to: ["./qr-code-feedback.svg"] },
                { from: ["./src/manifest.json"], to: ["./manifest.json"] },
                { from: ["./src/index.html"], to: ["./index.html"] },
                { from: ["./src/login.html"], to: ["./login.html"] },
                { from: ["./VERSION.txt"], to: ["./VERSION.txt"] },
            ]
        }),
        sassPlugin({
            loadPaths: [...nodePaths, "node_modules"],
            quietDeps: true,
        }),
        cockpitPoEsbuildPlugin(),
        // Login assets are served via /cockpit/static/ which does not
        // support .gz transparent serving, causing MIME type mismatch.
        cockpitCompressPlugin({ exclude: /anacondaLogin\.(js|css)$/ }),
        cockpitRsyncEsbuildPlugin({ dest: packageJson.name }),

        {
            name: "notify-end",
            setup (build) {
                build.onEnd(() => {
                    // eslint-disable-next-line no-console
                    console.log(`${getTime()}: Build finished`);
                });
            }
        },
    ],
    sourcemap: "linked",
    target: ["es2020"],
});

try {
    await context.rebuild();
} catch (e) {
    if (!watchMode) {
        process.exit(1);
    }
    // ignore errors in watch mode
}

if (watchMode) {
    const onChange = async path => {
        // eslint-disable-next-line no-console
        console.log("change detected:", path);
        await context.cancel();
        try {
            await context.rebuild();
        } catch (e) {} // ignore in watch mode
    };

    watchDirs("src", onChange);
    // wait forever until Control-C
    await new Promise(() => {});
}

context.dispose();