diff --git a/package.json b/package.json index 18e2a8b0a2..2b5d1b81b9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,9 @@ { "type": "module", "scripts": { - "test": "npx ava tests/*.test.js" + "test": "npx ava tests/*.test.js", + "check:reserved-order": "node util/check-reserved-order.cjs", + "add:reserved": "node util/add-reserved-subdomain.cjs" }, "devDependencies": { "ava": "^8.0.1", diff --git a/util/add-reserved-subdomain.cjs b/util/add-reserved-subdomain.cjs new file mode 100644 index 0000000000..500759cd3b --- /dev/null +++ b/util/add-reserved-subdomain.cjs @@ -0,0 +1,57 @@ +const { readFileSync, writeFileSync } = require("node:fs"); +const { join } = require("node:path"); +const readline = require("node:readline"); + +const filePath = join(__dirname, "reserved.json"); +const prompt = "What subdomain would you want to add to the reserved.json list: "; + +const interface = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +interface.question(prompt, (input) => { + const subdomain = input.trim(); + + if (!subdomain) { + console.error("Subdomain cannot be empty."); + interface.close(); + process.exitCode = 1; + return; + } + + if (subdomain !== subdomain.toLowerCase() || /\s/.test(subdomain)) { + console.error("Subdomain must be lowercase and cannot contain whitespace."); + interface.close(); + process.exitCode = 1; + return; + } + + const fileContents = readFileSync(filePath, "utf8"); + const reserved = JSON.parse(fileContents); + + if (reserved.includes(subdomain)) { + console.error(`"${subdomain}" is already in reserved.json.`); + interface.close(); + process.exitCode = 1; + return; + } + + const insertionIndex = reserved.findIndex( + (entry) => entry > subdomain, + ); + const index = insertionIndex === -1 ? reserved.length : insertionIndex; + reserved.splice(index, 0, subdomain); + + const newline = fileContents.includes("\r\n") ? "\r\n" : "\n"; + const output = `${JSON.stringify(reserved, null, 4)}${newline}`; + writeFileSync(filePath, output); + + const lineNumber = index + 2; + const precedingEntry = index > 0 ? reserved[index - 1] : "["; + const followingEntry = index < reserved.length - 1 ? reserved[index + 1] : "]"; + console.log( + `Added "${subdomain}" on line ${lineNumber}, after "${precedingEntry}" and before "${followingEntry}".`, + ); + interface.close(); +}); \ No newline at end of file diff --git a/util/check-reserved-order.cjs b/util/check-reserved-order.cjs new file mode 100644 index 0000000000..5456ee6c05 --- /dev/null +++ b/util/check-reserved-order.cjs @@ -0,0 +1,31 @@ +const { readFileSync } = require("node:fs"); +const { join } = require("node:path"); + +const filePath = join(__dirname, "reserved.json"); +const fileContents = readFileSync(filePath, "utf8"); +const reserved = JSON.parse(fileContents); + +for (let index = 1; index < reserved.length; index += 1) { + if (reserved[index - 1] > reserved[index]) { + let precedingIndex = index - 1; + + while ( + precedingIndex >= 0 && + reserved[precedingIndex] > reserved[index] + ) { + precedingIndex -= 1; + } + + const precedingLine = precedingIndex + 2; + + console.error( + `reserved.json is not in alphabetical order: line ${index + 2} ("${reserved[index]}") should go after line ${precedingLine} ("${precedingIndex >= 0 ? reserved[precedingIndex] : "["}") and before line ${index + 1} ("${reserved[index - 1]}").`, + ); + process.exitCode = 1; + break; + } +} + +if (process.exitCode !== 1) { + console.log("reserved.json is in alphabetical order."); +} \ No newline at end of file