Commit Graph

2 Commits

  • fix(extract-import-map): apply NodeNext .js→.ts rewrite (#294)
    Fixes the silent near-edgeless-graph regression on any modern ESM
    TypeScript project. Reported in #294 with full repro + root-cause
    analysis.
    
    ### Why this matters
    
    Under `moduleResolution: NodeNext` (or `Node16` / `Bundler` with
    explicit extensions — the default for new TS-ESM projects since 2023),
    TypeScript does NOT rewrite import specifiers during compilation:
    
      // src/index.ts — real, idiomatic NodeNext source
      import { x } from './config.js';   // on disk: config.ts
    
    Before this fix, `probeWithExtensions` only tried APPENDING extensions
    to the import specifier:
    
      './config.js' → not in fileSet
      './config.js.ts', './config.js.tsx', './config.js.js', ... → all miss
      → returns null → edge dropped at merge as dangling
    
    Net result on the reporter's repro: a knowledge graph with hundreds of
    file nodes and almost no `imports` edges between them — silently
    removing exactly the dependency structure the graph is meant to show.
    
    ### Fix
    
    New `NODENEXT_REWRITES` table maps each compiled-output extension to
    the TypeScript source extensions that could have produced it:
    
      .js   → [.ts, .tsx, .js, .jsx]
      .jsx  → [.tsx, .jsx]
      .mjs  → [.mts, .mjs, .ts]
      .cjs  → [.cts, .cjs, .ts]
    
    `probeWithExtensions` now applies the rewrite when the import already
    ends with one of these extensions and no such file exists on disk. The
    rewrite runs BEFORE the legacy append-extensions loop — otherwise
    `./foo.js` would generate the nonsense candidate `foo.js.ts` and the
    append loop would never reach the actual `foo.ts`.
    
    ### Disambiguation
    
    If both `config.ts` and `config.js` exist on disk (rare, but possible
    during a partial migration), `import './config.js'` still resolves to
    the .js — that's an exact-disk match and what NodeNext compilation
    actually does. The rewrite only kicks in when the .js doesn't exist.
    
    ### Tests
    
    6 new tests in `test_extract_import_map.test.mjs`:
    - The main #294 case (`.js → .ts`)
    - `.jsx → .tsx` and `.mjs → .mts` rewrites
    - Disambiguation when both `.ts` and `.js` exist on disk
    - Pure-JS projects still work (real `.js → .js` imports)
    - Historical no-extension probes unaffected
    - Missing files still return null (rewrite can't invent targets)
    
    Total: 202 tests passing (was 196).
    
    Closes #294
  • Merge pull request #204 from Lum1104/feat/semantic-batching-and-output-chunking
    fix(#159): semantic batching + bundled importMap + Phase 1 speedup