diff --git a/src/domain/graph/builder/helpers.ts b/src/domain/graph/builder/helpers.ts index 15451b76..3d1be287 100644 --- a/src/domain/graph/builder/helpers.ts +++ b/src/domain/graph/builder/helpers.ts @@ -132,8 +132,7 @@ export function loadPathAliases(rootDir: string): PathAliases { try { const raw = fs .readFileSync(configPath, 'utf-8') - .replace(/\/\/.*$/gm, '') - .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\/|\/\/.*$/gm, (_, str) => str ?? '') .replace(/,\s*([\]}])/g, '$1'); const config = JSON.parse(raw) as { compilerOptions?: { baseUrl?: string; paths?: Record }; diff --git a/src/domain/graph/builder/pipeline.ts b/src/domain/graph/builder/pipeline.ts index 7418163b..47f54ffc 100644 --- a/src/domain/graph/builder/pipeline.ts +++ b/src/domain/graph/builder/pipeline.ts @@ -9,6 +9,7 @@ import { performance } from 'node:perf_hooks'; import { closeDb, getBuildMeta, initSchema, MIGRATIONS, openDb } from '../../../db/index.js'; import { detectWorkspaces, loadConfig } from '../../../infrastructure/config.js'; import { info, warn } from '../../../infrastructure/logger.js'; +import { CODEGRAPH_VERSION } from '../../../shared/version.js'; import type { BuildGraphOpts, BuildResult } from '../../../types.js'; import { getActiveEngine } from '../../parser.js'; import { setWorkspaces } from '../resolve.js'; @@ -57,6 +58,13 @@ function checkEngineSchemaMismatch(ctx: PipelineContext): void { ); ctx.forceFullRebuild = true; } + const prevVersion = getBuildMeta(ctx.db, 'codegraph_version'); + if (prevVersion && prevVersion !== CODEGRAPH_VERSION) { + info( + `Codegraph version changed (${prevVersion} → ${CODEGRAPH_VERSION}), promoting to full rebuild.`, + ); + ctx.forceFullRebuild = true; + } } function loadAliases(ctx: PipelineContext): void { diff --git a/src/domain/graph/builder/stages/finalize.ts b/src/domain/graph/builder/stages/finalize.ts index f90b8b0a..3badf394 100644 --- a/src/domain/graph/builder/stages/finalize.ts +++ b/src/domain/graph/builder/stages/finalize.ts @@ -3,21 +3,14 @@ * * WASM cleanup, stats logging, drift detection, build metadata, registry, journal. */ -import fs from 'node:fs'; import path from 'node:path'; import { performance } from 'node:perf_hooks'; import { closeDb, getBuildMeta, setBuildMeta } from '../../../../db/index.js'; import { debug, info, warn } from '../../../../infrastructure/logger.js'; +import { CODEGRAPH_VERSION } from '../../../../shared/version.js'; import { writeJournalHeader } from '../../journal.js'; import type { PipelineContext } from '../context.js'; -const __builderDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1')); -const CODEGRAPH_VERSION = ( - JSON.parse( - fs.readFileSync(path.join(__builderDir, '..', '..', '..', '..', '..', 'package.json'), 'utf-8'), - ) as { version: string } -).version; - export async function finalize(ctx: PipelineContext): Promise { const { db, allSymbols, rootDir, isFullBuild, hasEmbeddings, config, opts, schemaVersion } = ctx; diff --git a/src/shared/version.ts b/src/shared/version.ts new file mode 100644 index 00000000..fe6f0a69 --- /dev/null +++ b/src/shared/version.ts @@ -0,0 +1,10 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const __sharedDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1')); + +export const CODEGRAPH_VERSION: string = ( + JSON.parse(fs.readFileSync(path.join(__sharedDir, '..', '..', 'package.json'), 'utf-8')) as { + version: string; + } +).version; diff --git a/tests/unit/builder.test.ts b/tests/unit/builder.test.ts index 2d15c664..a7140e2a 100644 --- a/tests/unit/builder.test.ts +++ b/tests/unit/builder.test.ts @@ -200,6 +200,28 @@ describe('loadPathAliases', () => { fs.rmSync(dir, { recursive: true, force: true }); }); + it('preserves // inside string values (e.g. $schema URLs)', () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-jsonc-url-')); + fs.writeFileSync( + path.join(dir, 'tsconfig.json'), + `{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + // A comment + "compilerOptions": { + /* Language & Environment */ + "baseUrl": "./src", + "paths": { + "@/*": ["*"] + } + } +}`, + ); + const aliases = loadPathAliases(dir); + expect(aliases.baseUrl).toContain('src'); + expect(aliases.paths['@/*']).toBeDefined(); + fs.rmSync(dir, { recursive: true, force: true }); + }); + it('prefers tsconfig.json over jsconfig.json', () => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-both-')); fs.writeFileSync(