WizardConnect/linters/copyright_check.mjs
2026-03-06 11:38:09 +01:00

59 lines
2 KiB
JavaScript

#!/usr/bin/env node
// Copyright (C) 2026 Whiterun LLC,
// This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later.
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html
import { readFileSync, readdirSync, statSync } from "node:fs";
import { join, dirname, relative } from "node:path";
import { fileURLToPath } from "node:url";
const OUR_DIR = dirname(fileURLToPath(import.meta.url));
const ROOT = join(OUR_DIR, "..");
const REQUIRED_LINES = [
"This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later.",
"A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html",
];
// Matches: "Copyright (C) 2026 Whiterun LLC" or "Copyright (C) 2024-2026 Whiterun LLC"
const COPYRIGHT_PATTERN = /Copyright \(C\) (\d{4}-)?\d{4} Whiterun LLC/;
const EXTENSIONS = [".ts", ".mjs"];
const DIRECTORIES = ["packages", "linters"];
function walk(dir) {
const results = [];
for (const entry of readdirSync(dir)) {
const full = join(dir, entry);
const stat = statSync(full);
if (stat.isDirectory()) {
if (entry === "node_modules" || entry === "dist") continue;
results.push(...walk(full));
} else if (EXTENSIONS.some((ext) => entry.endsWith(ext))) {
results.push(full);
}
}
return results;
}
let missing = 0;
for (const directory of DIRECTORIES) {
const dirPath = join(ROOT, directory);
for (const filePath of walk(dirPath)) {
const content = readFileSync(filePath, "utf-8");
const hasRequired = REQUIRED_LINES.every((line) => content.includes(line));
const hasCopyright = COPYRIGHT_PATTERN.test(content);
if (!hasRequired || !hasCopyright) {
console.log(`${relative(ROOT, filePath)}: Missing`);
missing++;
}
}
}
if (missing) {
console.log(`${missing} file(s) are missing copyright headers`);
process.exit(1);
} else {
console.log("OK");
}