mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-11-01 10:41:52 +08:00
java headers are generated and enforced by spotless licenseHeader from the root copyright file; the typescript surfaces had no such control - dc3-cli carried zero headers across 32 files and dc3-web was missing one hand-written file: - add scripts/add-license-header.mjs (shared by both packages) that reads the same root copyright and emits block comments for ts and html-comment headers for vue, with a --check mode for ci - wire headers / headers:check npm scripts; unplugin-generated ambient d.ts files are exempt (the generator owns their file head) - backfill all 32 dc3-cli sources and operation.ts / type.d.ts verified: headers:check green on both packages, cli 67/67 tests + build + lint, web 687/687 tests + lint + format
64 lines
2.3 KiB
JavaScript
64 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Adds the project AGPL header to source files that lack it. Shared by
|
|
* dc3-web and dc3-cli via lint-staged and the `headers` npm script;
|
|
* the header text is generated from the root COPYRIGHT file so the
|
|
* Java (spotless licenseHeader) and TypeScript surfaces never drift.
|
|
*
|
|
* Usage:
|
|
* node scripts/add-license-header.mjs <file>... fix specific files
|
|
* node scripts/add-license-header.mjs --check <file>... exit 1 if any lack the header
|
|
*/
|
|
import {readFileSync, writeFileSync} from 'node:fs';
|
|
import {resolve, dirname, join} from 'node:path';
|
|
import {fileURLToPath} from 'node:url';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const args = process.argv.slice(2);
|
|
const checkOnly = args[0] === '--check';
|
|
const files = checkOnly ? args.slice(1) : args;
|
|
|
|
if (!files.length) {
|
|
console.error('usage: add-license-header.mjs [--check] <file>...');
|
|
process.exit(2);
|
|
}
|
|
|
|
// Locate the repository root (two levels above dc3-web/scripts or dc3-cli/scripts).
|
|
// The script lives in dc3-web/scripts; the root holds COPYRIGHT.
|
|
const repoRoot = resolve(here, '..', '..');
|
|
const copyrightPath = join(repoRoot, 'COPYRIGHT');
|
|
const body = readFileSync(copyrightPath, 'utf8').trimEnd();
|
|
|
|
// Build the block comment the same way the maven antrun step does for Java:
|
|
// wrap lines with " * " and enclose in /* */.
|
|
const header = `/*
|
|
${body
|
|
.split('\n')
|
|
.map((line) => (line ? ` * ${line}` : ' *'))
|
|
.join('\n')}
|
|
*/
|
|
`;
|
|
|
|
let missing = 0;
|
|
for (const file of files) {
|
|
const src = readFileSync(file, 'utf8');
|
|
const isVue = file.endsWith('.vue');
|
|
const vueHeader = `<!--\n${header
|
|
.split('\n')
|
|
.slice(1, -1) // strip the /* and */ lines
|
|
.map((line) => (line === ' *' ? ' -' : ` -${line.slice(1)}`))
|
|
.join('\n')}\n-->\n`;
|
|
const existing = isVue ? src.startsWith('<!--\n - Copyright 2016-present') : src.startsWith('/*\n * Copyright 2016-present');
|
|
if (existing) continue;
|
|
const shebang = src.startsWith('#!') ? src.slice(0, src.indexOf('\n') + 1) : '';
|
|
const rest = shebang ? src.slice(shebang.length) : src;
|
|
if (checkOnly) {
|
|
console.error(`missing license header: ${file}`);
|
|
missing++;
|
|
} else {
|
|
writeFileSync(file, `${shebang}${isVue ? vueHeader : header}${rest.startsWith('\n') ? rest.slice(1) : rest}`);
|
|
console.log(`header added: ${file}`);
|
|
}
|
|
}
|
|
if (checkOnly && missing) process.exit(1);
|