chore(repo): format codebase and refine docs
This commit is contained in:
1 parent
638b3169eb
commit
de296d39d8
100 files changed
+23934
-21005
No files matched your search
@@ -1,19 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const DEFAULT_ASSETS = [
|
||||
{
|
||||
path: 'licensed/GeoLite2-City.mmdb',
|
||||
url: 'https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-City.mmdb',
|
||||
path: "licensed/GeoLite2-City.mmdb",
|
||||
url: "https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-City.mmdb",
|
||||
},
|
||||
];
|
||||
|
||||
async function downloadAsset(asset, destination) {
|
||||
const response = await fetch(asset.url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to download ${asset.url}: ${response.status} ${response.statusText}`);
|
||||
throw new Error(
|
||||
`Failed to download ${asset.url}: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
@@ -22,7 +24,7 @@ async function downloadAsset(asset, destination) {
|
||||
}
|
||||
|
||||
async function ensureLicensedAssets({
|
||||
rootDir = __dirname ? path.resolve(__dirname, '..') : process.cwd(),
|
||||
rootDir = __dirname ? path.resolve(__dirname, "..") : process.cwd(),
|
||||
assets = DEFAULT_ASSETS,
|
||||
downloadAsset: downloadImpl = downloadAsset,
|
||||
} = {}) {
|
||||
@@ -39,7 +41,7 @@ async function ensureLicensedAssets({
|
||||
if (require.main === module) {
|
||||
ensureLicensedAssets()
|
||||
.then(() => {
|
||||
process.stdout.write('Licensed assets are ready.\n');
|
||||
process.stdout.write("Licensed assets are ready.\n");
|
||||
})
|
||||
.catch((error) => {
|
||||
process.stderr.write(`${error.stack || error}\n`);
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { spawnSync } = require("node:child_process");
|
||||
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
const baselinePath = path.join(projectRoot, 'security', 'npm-audit-baseline.json');
|
||||
const reportDirectory = path.join(projectRoot, 'security-reports');
|
||||
const summaryJsonPath = path.join(reportDirectory, 'npm-audit-summary.json');
|
||||
const summaryMarkdownPath = path.join(reportDirectory, 'npm-audit-summary.md');
|
||||
const projectRoot = path.resolve(__dirname, "..");
|
||||
const baselinePath = path.join(
|
||||
projectRoot,
|
||||
"security",
|
||||
"npm-audit-baseline.json",
|
||||
);
|
||||
const reportDirectory = path.join(projectRoot, "security-reports");
|
||||
const summaryJsonPath = path.join(reportDirectory, "npm-audit-summary.json");
|
||||
const summaryMarkdownPath = path.join(reportDirectory, "npm-audit-summary.md");
|
||||
|
||||
const severityRank = {
|
||||
info: 0,
|
||||
@@ -17,29 +21,32 @@ const severityRank = {
|
||||
};
|
||||
|
||||
function npmCommand() {
|
||||
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
return process.platform === "win32" ? "npm.cmd" : "npm";
|
||||
}
|
||||
|
||||
function readBaseline() {
|
||||
const raw = fs.readFileSync(baselinePath, 'utf8');
|
||||
const raw = fs.readFileSync(baselinePath, "utf8");
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed.entries) ? parsed.entries : [];
|
||||
}
|
||||
|
||||
function runAudit(extraArgs) {
|
||||
const result = spawnSync(npmCommand(), ['audit', '--json', ...extraArgs], {
|
||||
const result = spawnSync(npmCommand(), ["audit", "--json", ...extraArgs], {
|
||||
cwd: projectRoot,
|
||||
encoding: 'utf8',
|
||||
encoding: "utf8",
|
||||
env: process.env,
|
||||
});
|
||||
|
||||
if (![0, 1].includes(result.status ?? 0)) {
|
||||
process.stderr.write(result.stderr || result.stdout || 'npm audit failed.\n');
|
||||
process.stderr.write(
|
||||
result.stderr || result.stdout || "npm audit failed.\n",
|
||||
);
|
||||
process.exit(result.status ?? 1);
|
||||
}
|
||||
|
||||
const combinedOutput = `${result.stdout || ''}\n${result.stderr || ''}`.trim();
|
||||
const jsonStart = combinedOutput.indexOf('{');
|
||||
const combinedOutput =
|
||||
`${result.stdout || ""}\n${result.stderr || ""}`.trim();
|
||||
const jsonStart = combinedOutput.indexOf("{");
|
||||
if (jsonStart === -1) {
|
||||
if ((result.status ?? 0) === 0) {
|
||||
return {
|
||||
@@ -58,7 +65,7 @@ function runAudit(extraArgs) {
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('npm audit returned no JSON payload.');
|
||||
throw new Error("npm audit returned no JSON payload.");
|
||||
}
|
||||
|
||||
return JSON.parse(combinedOutput.slice(jsonStart));
|
||||
@@ -67,7 +74,7 @@ function runAudit(extraArgs) {
|
||||
function toFindings(report, scope) {
|
||||
return Object.entries(report.vulnerabilities || {}).map(([pkg, entry]) => {
|
||||
const advisories = (entry.via || [])
|
||||
.filter((item) => item && typeof item === 'object' && item.title)
|
||||
.filter((item) => item && typeof item === "object" && item.title)
|
||||
.map((item) => ({
|
||||
source: item.source,
|
||||
title: item.title,
|
||||
@@ -88,10 +95,11 @@ function toFindings(report, scope) {
|
||||
}
|
||||
|
||||
function matchBaseline(finding, baselineEntries) {
|
||||
return baselineEntries.find((entry) =>
|
||||
entry.package === finding.package &&
|
||||
entry.scope === finding.scope &&
|
||||
entry.severity === finding.severity
|
||||
return baselineEntries.find(
|
||||
(entry) =>
|
||||
entry.package === finding.package &&
|
||||
entry.scope === finding.scope &&
|
||||
entry.severity === finding.severity,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,54 +108,60 @@ function formatFinding(finding, baselineEntry) {
|
||||
const notes = [];
|
||||
|
||||
if (finding.advisories.length) {
|
||||
notes.push(`advisories: ${finding.advisories.map((item) => item.title).join(' | ')}`);
|
||||
notes.push(
|
||||
`advisories: ${finding.advisories.map((item) => item.title).join(" | ")}`,
|
||||
);
|
||||
}
|
||||
if (finding.effects.length) {
|
||||
notes.push(`effects: ${finding.effects.join(', ')}`);
|
||||
notes.push(`effects: ${finding.effects.join(", ")}`);
|
||||
}
|
||||
if (finding.nodes.length) {
|
||||
notes.push(`nodes: ${finding.nodes.join(', ')}`);
|
||||
notes.push(`nodes: ${finding.nodes.join(", ")}`);
|
||||
}
|
||||
if (baselineEntry) {
|
||||
notes.push(`baseline: ${baselineEntry.reason} (review by ${baselineEntry.reviewBy})`);
|
||||
notes.push(
|
||||
`baseline: ${baselineEntry.reason} (review by ${baselineEntry.reviewBy})`,
|
||||
);
|
||||
}
|
||||
|
||||
return `- ${headline}\n ${notes.join('\n ')}`;
|
||||
return `- ${headline}\n ${notes.join("\n ")}`;
|
||||
}
|
||||
|
||||
function writeReports(payload) {
|
||||
fs.mkdirSync(reportDirectory, { recursive: true });
|
||||
fs.writeFileSync(summaryJsonPath, JSON.stringify(payload, null, 2) + '\n');
|
||||
fs.writeFileSync(summaryJsonPath, JSON.stringify(payload, null, 2) + "\n");
|
||||
|
||||
const sections = [
|
||||
'# npm audit summary',
|
||||
'',
|
||||
"# npm audit summary",
|
||||
"",
|
||||
`- generatedAt: ${payload.generatedAt}`,
|
||||
`- blockingFindings: ${payload.blockingFindings.length}`,
|
||||
`- baselinedDevelopmentFindings: ${payload.baselinedDevelopmentFindings.length}`,
|
||||
`- productionVulnerabilities: ${JSON.stringify(payload.production.metadata.vulnerabilities)}`,
|
||||
`- fullAuditVulnerabilities: ${JSON.stringify(payload.full.metadata.vulnerabilities)}`,
|
||||
'',
|
||||
'## Blocking findings',
|
||||
"",
|
||||
"## Blocking findings",
|
||||
...(payload.blockingFindings.length
|
||||
? payload.blockingFindings.map((item) => formatFinding(item, null))
|
||||
: ['- none']),
|
||||
'',
|
||||
'## Baselined development findings',
|
||||
: ["- none"]),
|
||||
"",
|
||||
"## Baselined development findings",
|
||||
...(payload.baselinedDevelopmentFindings.length
|
||||
? payload.baselinedDevelopmentFindings.map((item) => formatFinding(item.finding, item.baseline))
|
||||
: ['- none']),
|
||||
? payload.baselinedDevelopmentFindings.map((item) =>
|
||||
formatFinding(item.finding, item.baseline),
|
||||
)
|
||||
: ["- none"]),
|
||||
];
|
||||
|
||||
fs.writeFileSync(summaryMarkdownPath, sections.join('\n') + '\n');
|
||||
fs.writeFileSync(summaryMarkdownPath, sections.join("\n") + "\n");
|
||||
}
|
||||
|
||||
const baselineEntries = readBaseline();
|
||||
const productionAudit = runAudit(['--omit=dev']);
|
||||
const productionAudit = runAudit(["--omit=dev"]);
|
||||
const fullAudit = runAudit([]);
|
||||
|
||||
const productionFindings = toFindings(productionAudit, 'production');
|
||||
const fullFindings = toFindings(fullAudit, 'development');
|
||||
const productionFindings = toFindings(productionAudit, "production");
|
||||
const fullFindings = toFindings(fullAudit, "development");
|
||||
|
||||
const baselinedDevelopmentFindings = [];
|
||||
const blockingFindings = [];
|
||||
@@ -159,7 +173,11 @@ for (const finding of productionFindings) {
|
||||
}
|
||||
|
||||
for (const finding of fullFindings) {
|
||||
if (productionFindings.some((prodFinding) => prodFinding.package === finding.package)) {
|
||||
if (
|
||||
productionFindings.some(
|
||||
(prodFinding) => prodFinding.package === finding.package,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -191,8 +209,10 @@ const payload = {
|
||||
writeReports(payload);
|
||||
|
||||
if (blockingFindings.length) {
|
||||
process.stderr.write(`Security audit failed with ${blockingFindings.length} blocking finding(s).\n`);
|
||||
process.stderr.write(
|
||||
`Security audit failed with ${blockingFindings.length} blocking finding(s).\n`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
process.stdout.write('Security audit policy passed.\n');
|
||||
process.stdout.write("Security audit policy passed.\n");
|
||||
+40
-23
@@ -1,17 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const childProcess = require('node:child_process');
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const childProcess = require("node:child_process");
|
||||
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
const tsconfigPath = path.join(projectRoot, 'tsconfig.json');
|
||||
const bootstrapPrefix = path.join(projectRoot, '.codex-cache', 'ts-compiler');
|
||||
const projectRoot = path.resolve(__dirname, "..");
|
||||
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
||||
const bootstrapPrefix = path.join(projectRoot, ".codex-cache", "ts-compiler");
|
||||
|
||||
function resolveTypeScript() {
|
||||
const candidatePaths = [
|
||||
path.join(projectRoot, 'node_modules', 'typescript'),
|
||||
path.join(bootstrapPrefix, 'node_modules', 'typescript'),
|
||||
path.join(projectRoot, "node_modules", "typescript"),
|
||||
path.join(bootstrapPrefix, "node_modules", "typescript"),
|
||||
];
|
||||
|
||||
for (const candidate of candidatePaths) {
|
||||
@@ -22,20 +22,30 @@ function resolveTypeScript() {
|
||||
|
||||
ensureDir(bootstrapPrefix);
|
||||
const install = childProcess.spawnSync(
|
||||
'npm',
|
||||
['install', '--prefix', bootstrapPrefix, '--no-save', '--ignore-scripts', '--no-package-lock', 'typescript@5.5.4'],
|
||||
"npm",
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
bootstrapPrefix,
|
||||
"--no-save",
|
||||
"--ignore-scripts",
|
||||
"--no-package-lock",
|
||||
"typescript@5.5.4",
|
||||
],
|
||||
{
|
||||
cwd: projectRoot,
|
||||
stdio: 'inherit',
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
},
|
||||
);
|
||||
|
||||
if (install.status !== 0) {
|
||||
throw new Error(`Unable to bootstrap TypeScript compiler (exit ${install.status ?? 'unknown'})`);
|
||||
throw new Error(
|
||||
`Unable to bootstrap TypeScript compiler (exit ${install.status ?? "unknown"})`,
|
||||
);
|
||||
}
|
||||
|
||||
return require(path.join(bootstrapPrefix, 'node_modules', 'typescript'));
|
||||
return require(path.join(bootstrapPrefix, "node_modules", "typescript"));
|
||||
}
|
||||
|
||||
const ts = resolveTypeScript();
|
||||
@@ -54,7 +64,9 @@ function cleanDir(dirPath) {
|
||||
function loadConfig() {
|
||||
const rawConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
||||
if (rawConfig.error) {
|
||||
throw new Error(ts.flattenDiagnosticMessageText(rawConfig.error.messageText, '\n'));
|
||||
throw new Error(
|
||||
ts.flattenDiagnosticMessageText(rawConfig.error.messageText, "\n"),
|
||||
);
|
||||
}
|
||||
|
||||
const parsed = ts.parseJsonConfigFileContent(
|
||||
@@ -72,24 +84,24 @@ function loadConfig() {
|
||||
},
|
||||
fileNames: parsed.fileNames.filter((fileName) => {
|
||||
const normalized = path.resolve(fileName);
|
||||
if (!normalized.startsWith(path.join(projectRoot, 'src'))) {
|
||||
if (!normalized.startsWith(path.join(projectRoot, "src"))) {
|
||||
return false;
|
||||
}
|
||||
return !normalized.endsWith('.d.ts');
|
||||
return !normalized.endsWith(".d.ts");
|
||||
}),
|
||||
outDir: path.resolve(projectRoot, parsed.options.outDir || 'build'),
|
||||
outDir: path.resolve(projectRoot, parsed.options.outDir || "build"),
|
||||
};
|
||||
}
|
||||
|
||||
function outputPathFor(fileName, outDir) {
|
||||
const relative = path.relative(path.join(projectRoot, 'src'), fileName);
|
||||
const relative = path.relative(path.join(projectRoot, "src"), fileName);
|
||||
const ext = path.extname(relative);
|
||||
const base = relative.slice(0, relative.length - ext.length);
|
||||
return path.join(outDir, `${base}.js`);
|
||||
}
|
||||
|
||||
function transpileFile(fileName, compilerOptions, outDir) {
|
||||
const sourceText = fs.readFileSync(fileName, 'utf8');
|
||||
const sourceText = fs.readFileSync(fileName, "utf8");
|
||||
const transpiled = ts.transpileModule(sourceText, {
|
||||
compilerOptions,
|
||||
fileName,
|
||||
@@ -98,15 +110,18 @@ function transpileFile(fileName, compilerOptions, outDir) {
|
||||
|
||||
const outputFile = outputPathFor(fileName, outDir);
|
||||
ensureDir(path.dirname(outputFile));
|
||||
fs.writeFileSync(outputFile, transpiled.outputText, 'utf8');
|
||||
fs.writeFileSync(outputFile, transpiled.outputText, "utf8");
|
||||
|
||||
if (transpiled.sourceMapText) {
|
||||
fs.writeFileSync(`${outputFile}.map`, transpiled.sourceMapText, 'utf8');
|
||||
fs.writeFileSync(`${outputFile}.map`, transpiled.sourceMapText, "utf8");
|
||||
}
|
||||
|
||||
if (transpiled.diagnostics?.length) {
|
||||
for (const diagnostic of transpiled.diagnostics) {
|
||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
const message = ts.flattenDiagnosticMessageText(
|
||||
diagnostic.messageText,
|
||||
"\n",
|
||||
);
|
||||
process.stderr.write(`[transpile warning] ${fileName}: ${message}\n`);
|
||||
}
|
||||
}
|
||||
@@ -120,7 +135,9 @@ function main() {
|
||||
transpileFile(fileName, compilerOptions, outDir);
|
||||
}
|
||||
|
||||
process.stdout.write(`Transpiled ${fileNames.length} source files to ${outDir}\n`);
|
||||
process.stdout.write(
|
||||
`Transpiled ${fileNames.length} source files to ${outDir}\n`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user