2023-02-11 23:09:54 +08:00
|
|
|
import commonjs from "@rollup/plugin-commonjs";
|
|
|
|
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
2023-02-13 00:48:48 +08:00
|
|
|
import { createHash } from "crypto";
|
2026-01-01 19:45:43 +01:00
|
|
|
import { readFile, readdir, writeFile, stat } from "fs/promises";
|
2023-02-13 00:18:39 +08:00
|
|
|
import { argv } from "process";
|
2023-02-13 22:22:21 +08:00
|
|
|
import { rollup, watch } from "rollup";
|
2025-12-27 15:57:32 +01:00
|
|
|
|
2023-03-08 15:43:18 +08:00
|
|
|
import swc from "@swc/core";
|
|
|
|
|
import esbuild from "rollup-plugin-esbuild";
|
2023-01-24 15:56:43 +00:00
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
|
// MAIN EXECUTION
|
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
2025-12-27 15:57:32 +01:00
|
|
|
const args = argv.slice(2);
|
|
|
|
|
console.clear();
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
// Parse arguments
|
2025-12-27 15:57:32 +01:00
|
|
|
const inputPlugins = args.filter((x) => !x.startsWith("-"));
|
|
|
|
|
const flags = args.map((x) => x.toLowerCase()).filter((x) => x.startsWith("-"));
|
|
|
|
|
|
|
|
|
|
const isWatch = flags.includes("--watch") || flags.includes("-w");
|
2026-01-01 19:45:43 +01:00
|
|
|
const isVerbose = flags.includes("--verbose") || flags.includes("-v");
|
2025-12-27 15:57:32 +01:00
|
|
|
const toBuild = inputPlugins.length ? inputPlugins : await readdir("./plugins");
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
console.log(`Found ${toBuild.length} plugin(s) to build`);
|
|
|
|
|
|
|
|
|
|
if (isWatch) {
|
|
|
|
|
console.log("Running in watch mode\n");
|
|
|
|
|
}
|
2025-12-27 15:57:32 +01:00
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
// Build statistics
|
|
|
|
|
let built = 0;
|
2025-12-27 15:57:32 +01:00
|
|
|
let failed = 0;
|
2026-01-01 19:45:43 +01:00
|
|
|
const startTime = Date.now();
|
2025-12-27 15:57:32 +01:00
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
// Build all plugins
|
2025-12-27 16:14:54 +01:00
|
|
|
for (const plugin of toBuild) {
|
2026-01-01 19:45:43 +01:00
|
|
|
if (plugin.endsWith(".ts")) continue;
|
|
|
|
|
|
|
|
|
|
const pluginStartTime = Date.now();
|
|
|
|
|
|
2025-12-27 15:57:32 +01:00
|
|
|
try {
|
2026-01-01 19:45:43 +01:00
|
|
|
console.log(`Building ${plugin}...`);
|
|
|
|
|
|
|
|
|
|
const result = await buildPlugin(plugin);
|
|
|
|
|
const buildTime = Date.now() - pluginStartTime;
|
|
|
|
|
|
|
|
|
|
console.log(`✓ ${plugin} (${buildTime}ms)`);
|
|
|
|
|
built++;
|
2025-10-04 11:16:42 +02:00
|
|
|
} catch (e) {
|
2026-01-01 19:45:43 +01:00
|
|
|
console.log(`✗ ${plugin}`);
|
|
|
|
|
if (isVerbose) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
} else {
|
|
|
|
|
console.error(e.message);
|
|
|
|
|
}
|
2025-12-27 15:57:32 +01:00
|
|
|
failed++;
|
2025-10-04 11:16:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
// Summary
|
|
|
|
|
const totalTime = Date.now() - startTime;
|
|
|
|
|
console.log(`\nBuild completed in ${totalTime}ms`);
|
|
|
|
|
console.log(`Success: ${built}, Failed: ${failed}\n`);
|
2025-12-27 15:57:32 +01:00
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
if (isWatch) {
|
|
|
|
|
console.log("Watching for changes... (Press Ctrl+C to exit)\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
|
// BUILD FUNCTION
|
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
2025-12-27 15:57:32 +01:00
|
|
|
|
|
|
|
|
async function buildPlugin(plugin) {
|
2026-01-01 19:45:43 +01:00
|
|
|
if (plugin.endsWith(".ts")) return {};
|
2025-12-27 15:57:32 +01:00
|
|
|
|
|
|
|
|
const manifest = Object.assign(
|
|
|
|
|
JSON.parse(await readFile("./base_manifest.json")),
|
|
|
|
|
JSON.parse(await readFile(`./plugins/${plugin}/manifest.json`)),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const entry = "index.js";
|
|
|
|
|
const outPath = `./dist/${plugin}/${entry}`;
|
|
|
|
|
|
|
|
|
|
/** @type {import("rollup").RollupOptions} */
|
|
|
|
|
const options = {
|
|
|
|
|
input: `./plugins/${plugin}/${manifest.main}`,
|
|
|
|
|
output: {
|
|
|
|
|
file: outPath,
|
|
|
|
|
globals(id) {
|
|
|
|
|
if (id.startsWith("@vendetta"))
|
|
|
|
|
return id.substring(1).replace(/\//g, ".");
|
|
|
|
|
|
|
|
|
|
const map = {
|
|
|
|
|
react: "window.React",
|
|
|
|
|
"react-native": "vendetta.metro.common.ReactNative",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return map[id] || null;
|
|
|
|
|
},
|
|
|
|
|
format: "iife",
|
|
|
|
|
compact: true,
|
|
|
|
|
exports: "named",
|
|
|
|
|
inlineDynamicImports: true,
|
|
|
|
|
},
|
|
|
|
|
onwarn: (warning) => {
|
2026-01-01 19:45:43 +01:00
|
|
|
if (
|
|
|
|
|
![
|
|
|
|
|
"UNRESOLVED_IMPORT",
|
|
|
|
|
"MISSING_NAME_OPTION_FOR_IIFE_EXPORT",
|
|
|
|
|
"CIRCULAR_DEPENDENCY",
|
|
|
|
|
].includes(warning.code) &&
|
|
|
|
|
isVerbose
|
|
|
|
|
) {
|
|
|
|
|
console.warn(`${plugin}: ${warning.message}`);
|
|
|
|
|
}
|
2025-12-27 15:57:32 +01:00
|
|
|
},
|
|
|
|
|
plugins: [
|
|
|
|
|
nodeResolve({
|
|
|
|
|
resolveOnly: (id) => !["react", "react-native"].includes(id),
|
|
|
|
|
}),
|
|
|
|
|
commonjs(),
|
|
|
|
|
{
|
|
|
|
|
name: "swc",
|
|
|
|
|
transform(code, id) {
|
|
|
|
|
return swc.transform(code, {
|
|
|
|
|
filename: id,
|
|
|
|
|
jsc: {
|
|
|
|
|
parser: {
|
|
|
|
|
syntax: "typescript",
|
|
|
|
|
tsx: true,
|
|
|
|
|
},
|
|
|
|
|
externalHelpers: true,
|
|
|
|
|
},
|
|
|
|
|
env: {
|
|
|
|
|
targets: "defaults",
|
|
|
|
|
include: ["transform-classes", "transform-arrow-functions"],
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
esbuild({ minify: true }),
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
const applyHash = async () => {
|
|
|
|
|
const content = await readFile(outPath);
|
|
|
|
|
return Object.assign(manifest, {
|
|
|
|
|
hash: createHash("sha256").update(content).digest("hex"),
|
2025-12-27 15:57:32 +01:00
|
|
|
main: entry,
|
|
|
|
|
});
|
2026-01-01 19:45:43 +01:00
|
|
|
};
|
2025-12-27 15:57:32 +01:00
|
|
|
|
|
|
|
|
if (!isWatch) {
|
|
|
|
|
const bundle = await rollup(options);
|
|
|
|
|
await bundle.write(options.output);
|
|
|
|
|
await bundle.close();
|
|
|
|
|
|
|
|
|
|
await applyHash();
|
|
|
|
|
await writeFile(`./dist/${plugin}/manifest.json`, JSON.stringify(manifest));
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
const stats = await stat(outPath);
|
|
|
|
|
return { size: stats.size };
|
2025-10-04 11:16:42 +02:00
|
|
|
}
|
2025-12-27 15:57:32 +01:00
|
|
|
|
|
|
|
|
const watcher = watch(options);
|
|
|
|
|
|
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
|
watcher.on("event", async (event) => {
|
|
|
|
|
switch (event.code) {
|
2026-01-01 19:45:43 +01:00
|
|
|
case "BUNDLE_START":
|
|
|
|
|
break;
|
|
|
|
|
|
2025-12-27 15:57:32 +01:00
|
|
|
case "BUNDLE_END": {
|
|
|
|
|
event.result.close();
|
|
|
|
|
|
|
|
|
|
await applyHash();
|
|
|
|
|
await writeFile(
|
|
|
|
|
`./dist/${plugin}/manifest.json`,
|
|
|
|
|
JSON.stringify(manifest),
|
|
|
|
|
);
|
|
|
|
|
|
2026-01-01 19:45:43 +01:00
|
|
|
console.log(`⚡ ${plugin} rebuilt (${event.duration}ms)`);
|
|
|
|
|
resolve({ size: 0 });
|
2025-12-27 15:57:32 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "ERROR":
|
|
|
|
|
case "FATAL":
|
2026-01-01 19:45:43 +01:00
|
|
|
console.error(`✗ ${plugin}`);
|
|
|
|
|
if (isVerbose) {
|
|
|
|
|
console.error(event.error);
|
|
|
|
|
} else {
|
|
|
|
|
console.error(event.error.message);
|
|
|
|
|
}
|
2025-12-27 15:57:32 +01:00
|
|
|
reject(event.error);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-02-11 23:09:54 +08:00
|
|
|
}
|