spb/drive Public
SPB Drive — self-hosted personal cloud drive (files, previews, sharing) on the MacLustr cluster.
JavaScript 82.7%
CSS 10.6%
Nunjucks 3.6%
Shell 1.8%
SQL 1.3%
1#!/usr/bin/env node2/**3 * ─────────────────────────────────────────────4 * SPB Drive — Personal Cloud Drive5 * ─────────────────────────────────────────────6 * Author : Simon-Pierre Boucher7 * Contact : contact@spboucher.ai8 * File : scripts/inject-headers.mjs9 * Purpose : Prepend the canonical author header to any tracked file missing it10 * License : MIT © Simon-Pierre Boucher11 * ─────────────────────────────────────────────12 */1314import { execSync } from 'node:child_process';15import { readFileSync, writeFileSync } from 'node:fs';1617const LINES = (file, purpose) => [18 '─────────────────────────────────────────────',19 ' SPB Drive — Personal Cloud Drive',20 '─────────────────────────────────────────────',21 ' Author : Simon-Pierre Boucher',22 ' Contact : contact@spboucher.ai',23 ` File : ${file}`,24 ` Purpose : ${purpose}`,25 ' License : MIT © Simon-Pierre Boucher',26 '─────────────────────────────────────────────',27];2829/** Comment wrappers per extension family. */30const STYLES = {31 block: (lines) => `/**\n${lines.map((l) => ` * ${l}`.trimEnd()).join('\n')}\n */\n\n`,32 hash: (lines) => `${lines.map((l) => `# ${l}`.trimEnd()).join('\n')}\n\n`,33 html: (lines) => `<!--\n${lines.map((l) => ` ${l}`.trimEnd()).join('\n')}\n-->\n\n`,34 sql: (lines) => `${lines.map((l) => `-- ${l}`.trimEnd()).join('\n')}\n\n`,35};3637const EXT_STYLE = {38 '.js': 'block', '.mjs': 'block', '.cjs': 'block', '.ts': 'block',39 '.css': 'block', '.scss': 'block',40 '.py': 'hash', '.sh': 'hash', '.bash': 'hash', '.yml': 'hash', '.yaml': 'hash', '.toml': 'hash',41 '.html': 'html', '.njk': 'html', '.md': 'html',42 '.sql': 'sql',43};4445const files = execSync('git ls-files', { encoding: 'utf8' }).split('\n').filter(Boolean);46let injected = 0;4748for (const file of files) {49 const base = file.split('/').pop();50 const dot = base.lastIndexOf('.');51 const style = dot >= 0 ? EXT_STYLE[base.slice(dot).toLowerCase()] : null;52 if (!style) continue;53 let text;54 try { text = readFileSync(file, 'utf8'); } catch { continue; }55 if (text.slice(0, 1200).includes('contact@spboucher.ai')) continue;5657 let header = STYLES[style](LINES(file, 'Part of SPB Drive'));58 let body = text;59 if (body.startsWith('#!')) {60 const nl = body.indexOf('\n') + 1;61 header = body.slice(0, nl) + header;62 body = body.slice(nl);63 }64 writeFileSync(file, header + body);65 console.log(`+ header → ${file}`);66 injected += 1;67}6869console.log(injected > 0 ? `✓ Injected ${injected} header(s).` : '✓ Nothing to inject.');70