1
0

dump-graph.mjs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #!/usr/bin/env node
  2. /**
  3. * Dump a .codegraph/codegraph.db graph by NATURAL KEYS (no rowids, no
  4. * timestamps), sorted — two dumps diff clean iff the graphs are semantically
  5. * identical. The byte-identical gate used by every perf/kernel PR:
  6. *
  7. * node scripts/dump-graph.mjs <repo-or-db> > a.dump
  8. * node scripts/dump-graph.mjs <repo-or-db> > b.dump
  9. * diff a.dump b.dump
  10. *
  11. * Volatile fields excluded: nodes.updated_at, files.modified_at/indexed_at/
  12. * content_hash+size (environment-dependent), edges.id / unresolved_refs.id
  13. * (insertion rowids), and unresolved_refs.status (resolution bookkeeping —
  14. * kept, actually: status is deterministic given the same input; excluded only
  15. * if it proves flaky. We keep status.)
  16. */
  17. import { DatabaseSync } from 'node:sqlite';
  18. import * as fs from 'node:fs';
  19. import * as path from 'node:path';
  20. const arg = process.argv[2];
  21. if (!arg) {
  22. console.error('usage: dump-graph.mjs <repo-root-or-db-path>');
  23. process.exit(2);
  24. }
  25. let dbPath = arg;
  26. if (fs.statSync(arg).isDirectory()) {
  27. dbPath = path.join(arg, '.codegraph', 'codegraph.db');
  28. }
  29. const db = new DatabaseSync(dbPath, { readOnly: true });
  30. function dump(title, sql) {
  31. const rows = db.prepare(sql).all();
  32. const lines = rows.map((r) => JSON.stringify(r)).sort();
  33. process.stdout.write(`== ${title} (${lines.length})\n`);
  34. for (const l of lines) process.stdout.write(l + '\n');
  35. }
  36. dump(
  37. 'nodes',
  38. `SELECT id, kind, name, qualified_name, file_path, language, start_line, end_line,
  39. start_column, end_column, docstring, signature, visibility, is_exported,
  40. is_async, is_static, is_abstract, decorators, type_parameters, return_type
  41. FROM nodes`
  42. );
  43. dump(
  44. 'edges',
  45. `SELECT source, target, kind, metadata, line, col, provenance FROM edges`
  46. );
  47. dump(
  48. 'refs',
  49. `SELECT from_node_id, reference_name, reference_kind, line, col, candidates,
  50. file_path, language, status, name_tail
  51. FROM unresolved_refs`
  52. );
  53. dump('files', `SELECT path, language, node_count FROM files`);