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: 5 additions & 0 deletions .changeset/refresh-deps-node22.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stainless-code/codemap": patch
---

Refresh runtime and toolchain dependencies. `better-sqlite3` 13 requires Node `>=22`, so published `engines.node` is now `>=22.12.0` (Node 20 dropped). `oxc-parser` 0.147 plus a heritage extractor skip for oxc's dummy recovery of invalid `interface extends`. Audit overrides pin patched `hono`, `@hono/node-server`, and `postcss`.
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Codemap is in **bootstrap / extraction** phase. Before large PRs, please open an issue so we can align on:

- **Core vs adapter** — core should stay small; language-specific logic belongs in **adapters** (see [docs/roadmap.md](../docs/roadmap.md)).
- **Runtimes** — **Node** `^20.19.0 || >=22.12.0` and **Bun** `>=1.0.31` (`package.json` **engines**); SQLite is **`better-sqlite3`** on Node and **`bun:sqlite`** on Bun ([docs/architecture.md](../docs/architecture.md), [docs/packaging.md § Node vs Bun](../docs/packaging.md#node-vs-bun)). Maintainers use **Bun 1.4.0** (`packageManager`).
- **Runtimes** — **Node** `>=22.12.0` and **Bun** `>=1.0.31` (`package.json` **engines**); SQLite is **`better-sqlite3`** on Node and **`bun:sqlite`** on Bun ([docs/architecture.md](../docs/architecture.md), [docs/packaging.md § Node vs Bun](../docs/packaging.md#node-vs-bun)). Maintainers use **Bun 1.4.0** (`packageManager`).

## Dev workflow

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ bun add @stainless-code/codemap
# or: npm install @stainless-code/codemap
```

**Engines:** Node **`^20.19.0 || >=22.12.0`** and/or Bun **`>=1.0.31`**.
**Engines:** Node **`>=22.12.0`** and/or Bun **`>=1.0.31`**.

---

Expand Down
776 changes: 360 additions & 416 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The `templates/` directory ships three subtrees — two parallel agent trees plu

Published tarballs match **`package.json` `files`**: **`CHANGELOG.md`**, **`dist/`**, **`templates/`** (no `src/`). **`bun run pack`**, then point the consumer at **`file:…/stainless-code-codemap-*.tgz`**, or use **`file:/path/to/repo`** after build, or **`bun link`**. If **`better-sqlite3`** fails in the consumer, **`npm rebuild better-sqlite3`** (native addon must match that Node).

**Engines** (`package.json`): **Node** `^20.19.0 || >=22.12.0` (matches **`oxc-parser`**; **`better-sqlite3`** is prebuilt for current Node majors only). **Bun** `>=1.0.0`. **Native bindings:** `better-sqlite3`, `lightningcss`, `oxc-parser`, `oxc-resolver` (NAPI); **`tinyglobby`** and **`zod`** are JS-only. **`zod`** validates `<state-dir>/config.{ts,js,json}` at runtime (**`codemapUserConfigSchema`** in **`src/config.ts`**); see [architecture.md § User config](./architecture.md#user-config).
**Engines** (`package.json`): **Node** `>=22.12.0` (matches **`better-sqlite3` 13** `engines.node` `>=22` and **`oxc-parser`**'s 22.12 floor). **Bun** `>=1.0.31`. **Native bindings:** `better-sqlite3`, `lightningcss`, `oxc-parser`, `oxc-resolver` (NAPI); **`tinyglobby`** and **`zod`** are JS-only. **`zod`** validates `<state-dir>/config.{ts,js,json}` at runtime (**`codemapUserConfigSchema`** in **`src/config.ts`**); see [architecture.md § User config](./architecture.md#user-config).

## Node vs Bun

Expand Down
28 changes: 15 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,30 @@
},
"dependencies": {
"@clack/prompts": "1.7.0",
"@modelcontextprotocol/sdk": "1.29.0",
"better-sqlite3": "12.11.1",
"@modelcontextprotocol/sdk": "1.30.0",
"better-sqlite3": "13.0.3",
"chokidar": "5.0.0",
"lightningcss": "1.33.0",
"oxc-parser": "0.140.0",
"oxc-parser": "0.147.0",
"oxc-resolver": "11.24.2",
"package-manager-detector": "1.7.0",
"package-manager-detector": "1.8.0",
"tinyglobby": "0.2.17",
"zod": "4.4.3"
},
"devDependencies": {
"@arethetypeswrong/cli": "0.18.5",
"@changesets/changelog-github": "1.0.0",
"@changesets/cli": "3.0.1",
"@types/better-sqlite3": "7.6.13",
"@types/better-sqlite3": "9.6.0",
"@types/bun": "1.4.0",
"@types/node": "26.1.1",
"@types/node": "26.2.0",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"husky": "9.1.7",
"lint-staged": "17.1.0",
"oxfmt": "0.59.0",
"oxlint": "1.74.0",
"publint": "0.3.21",
"tsdown": "0.22.12",
"lint-staged": "17.3.0",
"oxfmt": "0.64.0",
"oxlint": "1.79.0",
"publint": "0.3.24",
"tsdown": "0.22.14",
"typedoc": "0.28.20",
"typedoc-plugin-frontmatter": "1.3.1",
"typedoc-plugin-markdown": "4.12.0",
Expand All @@ -128,16 +128,18 @@
},
"overrides": {
"@ai-sdk/provider-utils": "4.0.33",
"hono": ">=4.12.25",
"@hono/node-server": "1.19.17",
"hono": ">=4.12.34",
"js-yaml": "4.3.1",
"nanoid": "3.3.18",
"path-to-regexp": "6.3.0",
"postcss": ">=8.5.23",
"qs": ">=6.15.2",
"tar": "7.5.22"
},
"engines": {
"bun": ">=1.0.31",
"node": "^20.19.0 || >=22.12.0"
"node": ">=22.12.0"
},
"packageManager": "bun@1.4.0",
"contributing": ".github/CONTRIBUTING.md"
Expand Down
2 changes: 1 addition & 1 deletion src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ export interface SymbolRow {
body_hash?: string | null;
}

// SQLite 3.32+ (2020+) default; bun:sqlite + better-sqlite3 12.x both ship
// SQLite 3.32+ (2020+) default; bun:sqlite + better-sqlite3 13.x both ship
// with newer SQLite. Older builds default to 999.
const SQLITE_MAX_VARS = 32766;
// Cap rows per batch even when col_count would allow more — keeps per-batch
Expand Down
25 changes: 23 additions & 2 deletions src/extractors/heritage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,32 @@ class Dog extends Animal<string> {}
expect(rows[0]?.type_args).toBe("string");
});

it("records unresolved row for complex extends expression", () => {
it("skips invalid interface extends that oxc recovers as a dummy expression", () => {
const src = `
interface Weird extends (A | B) {}
`;
const result = parseSync("x.ts", src);
const result = parseSync("x.ts", src, {
lang: "ts",
preserveParens: false,
});
const lineMap = buildLineMap(src);
const rows = extractHeritageFromSource("x.ts", result.program, lineMap);
expect(rows).toHaveLength(0);
expect(
result.errors.some((e) =>
e.message.includes("only extend an identifier/qualified-name"),
),
).toBe(true);
});

it("records unresolved row for a real complex class extends expression", () => {
const src = `
class C extends (foo()) {}
`;
const result = parseSync("x.ts", src, {
lang: "ts",
preserveParens: false,
});
const lineMap = buildLineMap(src);
const rows = extractHeritageFromSource("x.ts", result.program, lineMap);
expect(rows).toHaveLength(1);
Expand Down
20 changes: 18 additions & 2 deletions src/extractors/heritage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ function unwrapExpression(node: any): any {
return cur;
}

/** oxc 0.146+ recovers invalid interface `extends` as a zero-span `ThisExpression`. */
function isRecoveredDummyExpression(expr: any, heritageNode: any): boolean {
if (!expr) return true;
const start = expr.start;
const end = expr.end;
if (typeof start !== "number" || typeof end !== "number" || start === end) {
return true;
}
const hs = heritageNode?.start;
const he = heritageNode?.end;
if (typeof hs === "number" && typeof he === "number") {
return start < hs || end > he;
}
return false;
}

function bestEffortSimpleName(node: any): string | null {
const unwrapped = unwrapExpression(node);
if (!unwrapped) return null;
Expand Down Expand Up @@ -132,10 +148,10 @@ function recordHeritageBase(
const expr = unwrapExpression(
heritageNode?.expression ?? heritageNode?.typeName ?? heritageNode,
);
if (isRecoveredDummyExpression(expr, heritageNode)) return;
const base = heritageBaseFromTypeRef(expr, heritageNode);
if (!base) {
const simple = bestEffortSimpleName(expr);
if (!simple) return;
const simple = bestEffortSimpleName(expr) ?? "(expression)";
pushHeritageRow(ctx, {
child_file_path: child.file_path,
child_name: child.name,
Expand Down