mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 06:35:24 +00:00
chore: move plugins to their own repos and drop the plugins folder
This commit is contained in:
1 parent
29a946d02e
commit
e02b5fe6e4
3167 files changed
+286
-440749
No files matched your search
@@ -2,7 +2,6 @@
|
||||
* Reads docker/bundled-plugins.json: which plugins ship in the image and
|
||||
* where each comes from.
|
||||
*
|
||||
* { "id": "x", "source": "workspace" } built from plugins/x
|
||||
* { "id": "x", "source": "tmxplug", "url": "...", "sha256": "..." }
|
||||
* { "id": "x", "source": "tmxplug", "path": "...", "sha256": "..." }
|
||||
*
|
||||
@@ -17,7 +16,7 @@ const path = require("node:path");
|
||||
const ID = /^[a-z0-9][a-z0-9-]*$/;
|
||||
const SHA256 = /^[0-9a-f]{64}$/;
|
||||
|
||||
function parseBundledPlugins(raw, workspaceIds) {
|
||||
function parseBundledPlugins(raw) {
|
||||
const problems = [];
|
||||
const list = raw && Array.isArray(raw.plugins) ? raw.plugins : null;
|
||||
if (!list) {
|
||||
@@ -41,15 +40,7 @@ function parseBundledPlugins(raw, workspaceIds) {
|
||||
}
|
||||
seen.add(entry.id);
|
||||
|
||||
if (entry.source === "workspace") {
|
||||
if (!workspaceIds.includes(entry.id)) {
|
||||
problems.push(
|
||||
`${entry.id} is a workspace plugin but plugins/${entry.id} does not exist`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
plugins.push({ id: entry.id, source: "workspace" });
|
||||
} else if (entry.source === "tmxplug") {
|
||||
if (entry.source === "tmxplug") {
|
||||
const hasUrl =
|
||||
typeof entry.url === "string" && entry.url.startsWith("https://");
|
||||
const hasPath = typeof entry.path === "string" && entry.path.length > 0;
|
||||
@@ -63,12 +54,6 @@ function parseBundledPlugins(raw, workspaceIds) {
|
||||
problems.push(`${entry.id} needs a lowercase hex sha256`);
|
||||
continue;
|
||||
}
|
||||
if (workspaceIds.includes(entry.id)) {
|
||||
problems.push(
|
||||
`${entry.id} comes from a .tmxplug, so delete plugins/${entry.id}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
plugins.push({
|
||||
id: entry.id,
|
||||
source: "tmxplug",
|
||||
@@ -81,33 +66,13 @@ function parseBundledPlugins(raw, workspaceIds) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const id of workspaceIds) {
|
||||
if (!seen.has(id)) {
|
||||
problems.push(
|
||||
`plugins/${id} is not listed in docker/bundled-plugins.json`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { plugins, problems };
|
||||
}
|
||||
|
||||
function loadBundledPlugins(root) {
|
||||
const configPath = path.join(root, "docker", "bundled-plugins.json");
|
||||
const pluginsDir = path.join(root, "plugins");
|
||||
const workspaceIds = fs.existsSync(pluginsDir)
|
||||
? fs
|
||||
.readdirSync(pluginsDir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.filter((entry) =>
|
||||
fs.existsSync(path.join(pluginsDir, entry.name, "manifest.json")),
|
||||
)
|
||||
.map((entry) => entry.name)
|
||||
.sort()
|
||||
: [];
|
||||
|
||||
const raw = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
||||
const { plugins, problems } = parseBundledPlugins(raw, workspaceIds);
|
||||
const { plugins, problems } = parseBundledPlugins(raw);
|
||||
if (problems.length > 0) {
|
||||
throw new Error(`docker/bundled-plugins.json:\n ${problems.join("\n ")}`);
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/**
|
||||
* Every SQL statement a 2.8 install's Postgres or MySQL database runs on its
|
||||
* way to 2.9.0, in the order it runs them: core's drizzle migrations added
|
||||
* since release-2.8.0-tag, then each bundled plugin's own migrations in the
|
||||
* order the loader activates them. The data copies that run after that
|
||||
* (src/backend/upgrade/) are TypeScript, not SQL, and are covered by the
|
||||
* upgrade test and scripts/upgrade-check.sh.
|
||||
*
|
||||
* Snapshot-tested by scripts/upgrade-sql.test.ts, so any change to the
|
||||
* upgrade path shows up as a diff in review.
|
||||
*
|
||||
* Usage: node scripts/lib/upgrade-sql.mjs postgres|mysql
|
||||
*/
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const ROOT = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"../..",
|
||||
);
|
||||
|
||||
/** The last core migration release-2.8.0-tag shipped, per dialect. */
|
||||
export const LAST_28_MIGRATION = {
|
||||
postgres: "0024_flimsy_forge",
|
||||
mysql: "0023_even_beast",
|
||||
};
|
||||
|
||||
/** Plugin ids in the order the loader activates them: dependencies first. */
|
||||
export function pluginActivationOrder(root = ROOT) {
|
||||
const dir = path.join(root, "plugins");
|
||||
const manifests = new Map(
|
||||
fs
|
||||
.readdirSync(dir, { withFileTypes: true })
|
||||
.filter(
|
||||
(entry) =>
|
||||
entry.isDirectory() &&
|
||||
fs.existsSync(path.join(dir, entry.name, "manifest.json")),
|
||||
)
|
||||
.map((entry) => [
|
||||
entry.name,
|
||||
JSON.parse(
|
||||
fs.readFileSync(path.join(dir, entry.name, "manifest.json"), "utf8"),
|
||||
),
|
||||
])
|
||||
.sort(([a], [b]) => a.localeCompare(b)),
|
||||
);
|
||||
|
||||
const order = [];
|
||||
const done = new Set();
|
||||
const visit = (id) => {
|
||||
if (done.has(id) || !manifests.has(id)) return;
|
||||
done.add(id);
|
||||
const manifest = manifests.get(id);
|
||||
for (const dependency of Object.keys(manifest.dependencies ?? {})) {
|
||||
visit(dependency);
|
||||
}
|
||||
for (const dependency of Object.keys(manifest.optionalDependencies ?? {})) {
|
||||
visit(dependency);
|
||||
}
|
||||
order.push(id);
|
||||
};
|
||||
for (const id of manifests.keys()) visit(id);
|
||||
return order;
|
||||
}
|
||||
|
||||
function section(title, sql) {
|
||||
return `-- ==== ${title} ====\n${sql.trim()}\n`;
|
||||
}
|
||||
|
||||
export function buildUpgradeSql(dialect, root = ROOT) {
|
||||
if (!(dialect in LAST_28_MIGRATION)) {
|
||||
throw new Error(`unsupported dialect "${dialect}"`);
|
||||
}
|
||||
const parts = [
|
||||
`-- Termix 2.8.0 to 2.9.0 on ${dialect}, generated by scripts/lib/upgrade-sql.mjs\n`,
|
||||
];
|
||||
|
||||
const coreDir = path.join(root, "drizzle", dialect);
|
||||
const journal = JSON.parse(
|
||||
fs.readFileSync(path.join(coreDir, "meta", "_journal.json"), "utf8"),
|
||||
);
|
||||
const tags = journal.entries.map((entry) => entry.tag);
|
||||
const last = tags.indexOf(LAST_28_MIGRATION[dialect]);
|
||||
if (last === -1) {
|
||||
throw new Error(
|
||||
`${LAST_28_MIGRATION[dialect]} is not in the ${dialect} journal`,
|
||||
);
|
||||
}
|
||||
for (const tag of tags.slice(last + 1)) {
|
||||
parts.push(
|
||||
section(
|
||||
`core ${tag}`,
|
||||
fs.readFileSync(path.join(coreDir, `${tag}.sql`), "utf8"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (const id of pluginActivationOrder(root)) {
|
||||
const dir = path.join(root, "plugins", id, "migrations", dialect);
|
||||
if (!fs.existsSync(dir)) continue;
|
||||
for (const file of fs
|
||||
.readdirSync(dir)
|
||||
.filter((name) => name.endsWith(".sql"))
|
||||
.sort()) {
|
||||
parts.push(
|
||||
section(
|
||||
`plugin ${id} ${file}`,
|
||||
fs.readFileSync(path.join(dir, file), "utf8"),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join("\n").replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
if (
|
||||
process.argv[1] &&
|
||||
fileURLToPath(import.meta.url) === path.resolve(process.argv[1])
|
||||
) {
|
||||
process.stdout.write(buildUpgradeSql(process.argv[2] ?? "postgres"));
|
||||
}
|
||||
Reference in new issue
Block a user