Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#!/usr/bin/env node

import { run } from './cli/index.js';
import { CodegraphError } from './shared/errors.js';
import { CodegraphError, toErrorMessage } from './shared/errors.js';

run().catch((err: unknown) => {
if (err instanceof CodegraphError) {
console.error(`codegraph [${err.code}]: ${err.message}`);
if (err.file) console.error(` file: ${err.file}`);
} else {
const message = err instanceof Error ? err.message : String(err);
console.error(`codegraph: fatal error — ${message}`);
console.error(`codegraph: fatal error — ${toErrorMessage(err)}`);
}
process.exit(1);
});
7 changes: 4 additions & 3 deletions src/cli/commands/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { collectFile } from '../../db/query-builder.js';
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
import { BATCH_COMMANDS, multiBatchData, splitTargets } from '../../features/batch.js';
import { batch } from '../../presentation/batch.js';
import { ConfigError } from '../../shared/errors.js';
import { ConfigError, toErrorMessage } from '../../shared/errors.js';
import type { CommandDefinition } from '../types.js';

interface MultiBatchItem {
Expand Down Expand Up @@ -58,8 +58,9 @@ export const command: CommandDefinition = {
targets = splitTargets(positionalTargets as unknown as string[]);
}
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
throw new ConfigError(`Failed to parse targets: ${message}`, { cause: err as Error });
throw new ConfigError(`Failed to parse targets: ${toErrorMessage(err)}`, {
cause: err as Error,
});
}

if (!targets || targets.length === 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/cli/commands/plot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import { toErrorMessage } from '../../shared/errors.js';
import { openGraph } from '../shared/open-graph.js';
import type { CommandDefinition } from '../types.js';

Expand Down Expand Up @@ -51,8 +52,7 @@ export const command: CommandDefinition = {
try {
plotCfg = JSON.parse(fs.readFileSync(opts.config as string, 'utf-8')) as PlotConfig;
} catch (e: unknown) {
const message = e instanceof Error ? e.message : String(e);
console.error(`Failed to load config: ${message}`);
console.error(`Failed to load config: ${toErrorMessage(e)}`);
process.exitCode = 1;
return;
}
Expand Down
13 changes: 5 additions & 8 deletions src/domain/graph/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'node:path';
import { debug } from '../../infrastructure/logger.js';
import { loadNative } from '../../infrastructure/native.js';
import { normalizePath } from '../../shared/constants.js';
import { toErrorMessage } from '../../shared/errors.js';
import type { BareSpecifier, BatchResolvedMap, ImportBatchItem, PathAliases } from '../../types.js';

// ── package.json exports resolution ─────────────────────────────────
Expand Down Expand Up @@ -64,9 +65,7 @@ function getPackageExports(packageDir: string): any {
_exportsCache.set(packageDir, exports);
return exports;
} catch (e) {
debug(
`readPackageExports: failed to read package.json in ${packageDir}: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`readPackageExports: failed to read package.json in ${packageDir}: ${toErrorMessage(e)}`);
_exportsCache.set(packageDir, null);
return null;
}
Expand Down Expand Up @@ -519,7 +518,7 @@ export function resolveImportPath(
return remapJsToTs(normalized, rootDir);
} catch (e) {
debug(
`resolveImportPath: native resolution failed, falling back to JS: ${e instanceof Error ? e.message : String(e)}`,
`resolveImportPath: native resolution failed, falling back to JS: ${toErrorMessage(e)}`,
);
}
}
Expand All @@ -541,7 +540,7 @@ export function computeConfidence(
return native.computeConfidence(callerFile, targetFile, importedFrom || null);
} catch (e) {
debug(
`computeConfidence: native computation failed, falling back to JS: ${e instanceof Error ? e.message : String(e)}`,
`computeConfidence: native computation failed, falling back to JS: ${toErrorMessage(e)}`,
);
}
}
Expand Down Expand Up @@ -582,9 +581,7 @@ export function resolveImportsBatch(
}
return map;
} catch (e) {
debug(
`batchResolve: native batch resolution failed: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`batchResolve: native batch resolution failed: ${toErrorMessage(e)}`);
return null;
}
}
Expand Down
17 changes: 5 additions & 12 deletions src/domain/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Tree } from 'web-tree-sitter';
import { Language, Parser, Query } from 'web-tree-sitter';
import { debug, warn } from '../infrastructure/logger.js';
import { getNative, getNativePackageVersion, loadNative } from '../infrastructure/native.js';
import { toErrorMessage } from '../shared/errors.js';
import type {
EngineMode,
ExtractorOutput,
Expand Down Expand Up @@ -438,9 +439,7 @@ async function backfillTypeMap(
try {
code = fs.readFileSync(filePath, 'utf-8');
} catch (e) {
debug(
`backfillTypeMap: failed to read ${filePath}: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`backfillTypeMap: failed to read ${filePath}: ${toErrorMessage(e)}`);
return { typeMap: new Map(), backfilled: false };
}
}
Expand All @@ -457,9 +456,7 @@ async function backfillTypeMap(
try {
extracted.tree.delete();
} catch (e) {
debug(
`backfillTypeMap: WASM tree cleanup failed: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`backfillTypeMap: WASM tree cleanup failed: ${toErrorMessage(e)}`);
}
}
}
Expand Down Expand Up @@ -573,18 +570,14 @@ export async function parseFilesAuto(
symbols._typeMapBackfilled = true;
}
} catch (e) {
debug(
`batchExtract: typeMap backfill failed: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`batchExtract: typeMap backfill failed: ${toErrorMessage(e)}`);
} finally {
// Free the WASM tree to prevent memory accumulation across repeated builds
if (extracted?.tree && typeof extracted.tree.delete === 'function') {
try {
extracted.tree.delete();
} catch (e) {
debug(
`batchExtract: WASM tree cleanup failed: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`batchExtract: WASM tree cleanup failed: ${toErrorMessage(e)}`);
}
}
}
Expand Down
17 changes: 5 additions & 12 deletions src/infrastructure/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { toErrorMessage } from '../shared/errors.js';
import type { CodegraphConfig } from '../types.js';
import { debug, warn } from './logger.js';

Expand Down Expand Up @@ -309,9 +310,7 @@ function resolveWorkspaceEntry(pkgDir: string): string | null {
if (fs.existsSync(candidate)) return candidate;
}
} catch (e) {
debug(
`resolveWorkspaceEntry: package.json probe failed for ${pkgDir}: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`resolveWorkspaceEntry: package.json probe failed for ${pkgDir}: ${toErrorMessage(e)}`);
}
return null;
}
Expand Down Expand Up @@ -345,9 +344,7 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
}
}
} catch (e) {
debug(
`detectWorkspaces: failed to parse pnpm-workspace.yaml: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`detectWorkspaces: failed to parse pnpm-workspace.yaml: ${toErrorMessage(e)}`);
}
}

Expand All @@ -366,9 +363,7 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
patterns.push(...ws.packages);
}
} catch (e) {
debug(
`detectWorkspaces: failed to parse package.json workspaces: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`detectWorkspaces: failed to parse package.json workspaces: ${toErrorMessage(e)}`);
}
}
}
Expand All @@ -384,9 +379,7 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
patterns.push(...lerna.packages);
}
} catch (e) {
debug(
`detectWorkspaces: failed to parse lerna.json: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`detectWorkspaces: failed to parse lerna.json: ${toErrorMessage(e)}`);
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/infrastructure/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { createRequire } from 'node:module';
import os from 'node:os';
import { EngineError } from '../shared/errors.js';
import { EngineError, toErrorMessage } from '../shared/errors.js';
import type { NativeAddon } from '../types.js';
import { debug } from './logger.js';

Expand All @@ -28,7 +28,7 @@ function detectLibc(): 'gnu' | 'musl' {
return 'musl';
}
} catch (e) {
debug(`detectLibc: failed to read /lib: ${e instanceof Error ? e.message : String(e)}`);
debug(`detectLibc: failed to read /lib: ${toErrorMessage(e)}`);
}
return 'gnu';
}
Expand Down Expand Up @@ -96,9 +96,7 @@ export function getNativePackageVersion(): string | null {
const pkgJson = _require(`${pkg}/package.json`) as { version?: string };
return pkgJson.version || null;
} catch (e) {
debug(
`getNativePackageVersion: failed to read package.json for ${pkg}: ${e instanceof Error ? e.message : String(e)}`,
);
debug(`getNativePackageVersion: failed to read package.json for ${pkg}: ${toErrorMessage(e)}`);
return null;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/shared/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ export class BoundaryError extends CodegraphError {
this.name = 'BoundaryError';
}
}

/** Safely extract a string message from an unknown thrown value. */
export function toErrorMessage(e: unknown): string {
return e instanceof Error ? e.message : String(e);
}
Loading