Skip to content
49 changes: 48 additions & 1 deletion scripts/validate-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* find ./gaps -maxdepth 1 -type d -name 'GAP-*' | xargs -I{} node scripts/validate-structure.js {}
*/

import { existsSync, readFileSync, statSync } from "node:fs";
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
import { basename, join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { parseArgs } from "node:util";
Expand Down Expand Up @@ -114,6 +114,50 @@ function validateMetadata(dirPath, gapName) {
}
}

function validateAllowedFiles(dirPath, gapName) {
for (const entry of readdirSync(dirPath)) {
if (entry.startsWith(".")) {
error(gapName, `Dotfiles are not allowed: "${entry}".`);
continue;
}

const fullPath = join(dirPath, entry);

if (statSync(fullPath).isDirectory()) {
if (entry === "versions") {
validateVersionsDir(fullPath, gapName);
} else {
error(gapName, `Unexpected directory "${entry}".`);
}
continue;
}

if (entry === "metadata.yml" || entry === "metadata.json" || entry.endsWith(".md")) {
continue;
}

error(gapName, `Unexpected file "${entry}".`);
}
}

function validateVersionsDir(dirPath, gapName) {
for (const entry of readdirSync(dirPath)) {
if (entry.startsWith(".")) {
error(gapName, `Dotfiles are not allowed in versions/: "${entry}".`);
continue;
}

if (statSync(join(dirPath, entry)).isDirectory()) {
error(gapName, `Unexpected directory in versions/: "${entry}".`);
continue;
}

if (!/^\d{4}-\d{2}\.(md|yml)$/.test(entry)) {
error(gapName, `Unexpected file in versions/: "${entry}". Only YYYY-MM.md and YYYY-MM.yml are allowed.`);
}
}
}

function main() {
const { positionals } = parseArgs({ allowPositionals: true, strict: true });

Expand All @@ -137,6 +181,9 @@ function main() {
// Validate directory naming
const gapName = validateDirectoryNaming(dirPath);

// Validate only allowed files are present
validateAllowedFiles(dirPath, gapName);

// Validate README.md exists
validateReadmeExists(dirPath, gapName);

Expand Down