Brings the whole project into git (previously only the on-ramp feature and a few parallel files were tracked). Includes: wallet core (src/), CashScript contracts/, the Capacitor shell (shells/), scripts/, tests, and the docs corpus (wiki/, snapshots/, Parameters/, Archive/, KnowledgeBase text). Excluded via .gitignore: node_modules/, dist/, .env (secrets), testnet WIF key files (.chipnet-*.json, devWallets.ts), KnowledgeBase/RAW media (~9.6 GB), transcripts/ (session logs), and machine-local config (.claude/*.local, *.lock). Secret-scanned before commit — no credentials in the tree. Note: src/swapMath.ts, src/swapBuilder.ts, contracts/OpenMintToken.cash are legacy (OP_RETURN era) but still imported; committed as-is, flagged for a separate removal once de-referenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
102 lines
3.4 KiB
JavaScript
102 lines
3.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* scan-code.mjs — produces wiki/code-map.md
|
|
*
|
|
* Purpose: cheap, deterministic index of the codebase so future Claude
|
|
* sessions can locate symbols without a directory walk. Per CLAUDE.md:
|
|
* "Create scripts to navigate source code and reduce claude processing
|
|
* time and token burn."
|
|
*
|
|
* Outputs a single markdown file with:
|
|
* - Tree of src/, contracts/, test/, scripts/, wiki/
|
|
* - Per-file: exported symbols (TS), pragma + contract names (CashScript),
|
|
* line count, first doc-comment line.
|
|
*
|
|
* Intentionally zero external deps — runs on plain Node.
|
|
*/
|
|
import { readdirSync, readFileSync, statSync, writeFileSync, existsSync } from 'node:fs';
|
|
import { join, relative, extname } from 'node:path';
|
|
|
|
const ROOT = join(import.meta.dirname, '..');
|
|
const TARGETS = ['src', 'contracts', 'test', 'scripts', 'wiki'];
|
|
const OUT = join(ROOT, 'wiki', 'code-map.md');
|
|
|
|
const IGNORE = new Set(['node_modules', 'dist', '.git', 'coverage', '.regtest-data']);
|
|
|
|
function walk(dir, out = []) {
|
|
for (const entry of readdirSync(dir)) {
|
|
if (IGNORE.has(entry)) continue;
|
|
const full = join(dir, entry);
|
|
const st = statSync(full);
|
|
if (st.isDirectory()) walk(full, out);
|
|
else out.push(full);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function describe(file) {
|
|
const ext = extname(file);
|
|
const src = readFileSync(file, 'utf8');
|
|
const lines = src.split('\n');
|
|
const lineCount = lines.length;
|
|
const summary = { lineCount, symbols: [], doc: '' };
|
|
|
|
// First non-empty non-shebang line containing a comment marker
|
|
for (const line of lines.slice(0, 20)) {
|
|
const t = line.trim();
|
|
if (!t || t.startsWith('#!')) continue;
|
|
if (t.startsWith('//') || t.startsWith('/*') || t.startsWith('*') || t.startsWith('pragma')) {
|
|
summary.doc = t.replace(/^[/*\s]+/, '').slice(0, 120);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ext === '.ts' || ext === '.mjs' || ext === '.js') {
|
|
const reExport = /^\s*export\s+(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+([A-Za-z0-9_]+)/gm;
|
|
let m;
|
|
while ((m = reExport.exec(src)) !== null) summary.symbols.push(m[1]);
|
|
}
|
|
if (ext === '.cash') {
|
|
const reContract = /^\s*contract\s+([A-Za-z0-9_]+)\s*\(/gm;
|
|
const reFn = /^\s*function\s+([A-Za-z0-9_]+)\s*\(/gm;
|
|
let m;
|
|
while ((m = reContract.exec(src)) !== null) summary.symbols.push(`contract:${m[1]}`);
|
|
while ((m = reFn.exec(src)) !== null) summary.symbols.push(`fn:${m[1]}`);
|
|
}
|
|
return summary;
|
|
}
|
|
|
|
const sections = [];
|
|
for (const target of TARGETS) {
|
|
const targetPath = join(ROOT, target);
|
|
if (!existsSync(targetPath)) continue;
|
|
const files = walk(targetPath)
|
|
.filter((f) => /\.(ts|mjs|js|cash|md)$/.test(f))
|
|
.sort();
|
|
if (files.length === 0) continue;
|
|
|
|
const rows = [];
|
|
for (const f of files) {
|
|
const rel = relative(ROOT, f).replaceAll('\\', '/');
|
|
const { lineCount, symbols, doc } = describe(f);
|
|
const sym = symbols.length ? symbols.join(', ') : '—';
|
|
rows.push(`| \`${rel}\` | ${lineCount} | ${sym} | ${doc || '—'} |`);
|
|
}
|
|
|
|
sections.push(
|
|
`### ${target}/\n\n| File | Lines | Exports | First doc line |\n|---|---|---|---|\n${rows.join('\n')}\n`
|
|
);
|
|
}
|
|
|
|
const stamp = new Date().toISOString();
|
|
const out = `# Code Map
|
|
|
|
_Auto-generated by \`scripts/scan-code.mjs\` at ${stamp}_
|
|
|
|
_Do not edit by hand. Regenerate with \`npm run scan\`._
|
|
|
|
${sections.join('\n')}
|
|
`;
|
|
|
|
writeFileSync(OUT, out);
|
|
console.log(`Wrote ${relative(ROOT, OUT)}`);
|