SYNC: Merge pull request #7 from dbgate/feature/applog

This commit is contained in:
Jan Prochazka
2025-08-05 17:13:33 +02:00
committed by Diflow
parent ac0aebd751
commit a96f1d0b49
83 changed files with 1014 additions and 242 deletions

View File

@@ -0,0 +1,129 @@
#!/usr/bin/env node
// assign-dbgm-codes.mjs
import fs from 'fs/promises';
import path from 'path';
const PLACEHOLDER = 'DBGM-00000';
const CODE_RE = /DBGM-(\d{5})/g;
const JS_TS_RE = /\.(mjs|cjs|js|ts|jsx|tsx)$/i;
const IGNORE_DIRS = new Set([
'node_modules',
'.git',
'.hg',
'.svn',
'dist',
'build',
'out',
'.next',
'.turbo',
'.cache',
]);
const IGNORE_FILES = ['assign-dbgm-codes.mjs', 'package.json', 'README.md'];
// --- CLI ---
const args = process.argv.slice(2);
const dryRun = args.includes('--dry');
const rootArg = args.find(a => a !== '--dry') || process.cwd();
const root = path.resolve(rootArg);
// --- helpers ---
async function* walk(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const e of entries) {
if (e.isDirectory()) {
if (IGNORE_DIRS.has(e.name)) continue;
yield* walk(path.join(dir, e.name));
} else if (e.isFile()) {
if (JS_TS_RE.test(e.name) && !IGNORE_FILES.includes(e.name)) yield path.join(dir, e.name);
}
}
}
function formatCode(n) {
return `DBGM-${String(n).padStart(5, '0')}`;
}
// Find the smallest positive integer not in `taken`
function makeNextCodeFn(taken) {
let n = 1;
// advance n to first free
while (taken.has(n)) n++;
return () => {
const code = n;
taken.add(code);
// move n to next free for next call
do {
n++;
} while (taken.has(n));
return formatCode(code);
};
}
// --- main ---
(async () => {
console.log(`Scanning: ${root} ${dryRun ? '(dry run)' : ''}`);
// 1) Collect all taken codes across the repo
const taken = new Set(); // numeric parts only
const files = [];
for await (const file of walk(root)) files.push(file);
await Promise.all(
files.map(async file => {
try {
const text = await fs.readFile(file, 'utf8');
for (const m of text.matchAll(CODE_RE)) {
const num = Number(m[1]);
if (Number.isInteger(num) && num > 0) taken.add(num);
}
} catch (err) {
console.warn(`! Failed to read ${file}: ${err.message}`);
}
})
);
console.log(`Found ${taken.size} occupied code(s).`);
// 2) Replace placeholders with next available unique code
const nextCode = makeNextCodeFn(taken);
let filesChanged = 0;
let placeholdersReplaced = 0;
for (const file of files) {
let text;
try {
text = await fs.readFile(file, 'utf8');
} catch (err) {
console.warn(`! Failed to read ${file}: ${err.message}`);
continue;
}
if (!text.includes(PLACEHOLDER)) continue;
let countInFile = 0;
const updated = text.replaceAll(PLACEHOLDER, () => {
countInFile++;
return nextCode();
});
if (countInFile > 0) {
placeholdersReplaced += countInFile;
filesChanged++;
console.log(`${dryRun ? '[dry]' : '[write]'} ${file}${countInFile} replacement(s)`);
if (!dryRun) {
try {
await fs.writeFile(file, updated, 'utf8');
} catch (err) {
console.warn(`! Failed to write ${file}: ${err.message}`);
}
}
}
}
console.log(`Done. Files changed: ${filesChanged}, placeholders replaced: ${placeholdersReplaced}.`);
})().catch(err => {
console.error(err);
process.exit(1);
});