diff --git a/scripts/validate-structure.js b/scripts/validate-structure.js index 6c0b634..fa81059 100755 --- a/scripts/validate-structure.js +++ b/scripts/validate-structure.js @@ -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"; @@ -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 }); @@ -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);