feat(npm): restore programmatic/embedded SDK API (#354)#603
Merged
Conversation
The 0.9.x thin-installer turned @colbymchenry/codegraph into a bin-only
shim: require("@colbymchenry/codegraph") threw MODULE_NOT_FOUND and no
types shipped, breaking embedded library consumers (e.g. Electron apps)
upgrading from 0.8.0.
Restore programmatic use without re-bloating the thin shim or duplicating
the ~49 MB of grammars the per-platform bundle already carries:
- main -> npm-sdk.js re-exports the installed per-platform bundle's compiled
library (lib/dist/index.js) at runtime, reusing that bundle's own deps; it
falls back to a self-healed cache bundle, else throws an actionable error.
- types -> ship the .d.ts tree only (~590 KB) in the main package, built from
the same release so it can never skew from the runtime it re-exports.
- exports map resolves the `types` condition (nodenext) and the default entry.
- DatabaseConnection + QueryBuilder are now top-level exports, so embedded
callers get the building blocks from the package entry instead of deep
dist/ imports (which the shim no longer ships).
The CLI/MCP `bin` keeps execing the bundled Node; only library consumers run
on their own runtime, which must be Node 22.5+ for the built-in node:sqlite.
Validated end-to-end: built a real darwin-arm64 bundle, packed the npm
packages, installed them into a throwaway consumer, and confirmed require()
plus a full init/indexAll/searchNodes round-trip and the low-level
DatabaseConnection/QueryBuilder path all work on the host Node; types resolve
under both nodenext and classic node resolution; and the CLI shim still
launches. New hermetic tests cover npm-sdk resolution, cache fallback, and the
missing-bundle error.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #354.
Problem
The 0.9.x thin-installer made
@colbymchenry/codegrapha bin-only shim — the compiled library moved into the per-platformoptionalDependencybundle and the main package re-exported nothing. So for anyone embedding CodeGraph as a library (the issue author runs it inside an Electron app, upgrading from 0.8.0):require("@colbymchenry/codegraph")→MODULE_NOT_FOUNDtypes, nomain, noexportsFix
Restore programmatic use without re-bloating the thin shim or duplicating the ~49 MB of tree-sitter grammars the per-platform bundle already carries:
main→npm-sdk.jsre-exports the installed per-platform bundle's compiled library (lib/dist/index.js) at runtime, reusing that bundle's ownnode_modules. Falls back to a self-healed cache bundle (issue no prebuilt bundle for darwin-arm64 #303 path), else throws an actionable "install from the official registry" error instead of a bareMODULE_NOT_FOUND.types→ ship the.d.tstree only (~590 KB) in the main package, built from the same release so it can never skew from the runtime it re-exports.exportsmap resolves thetypescondition (nodenext) and the default entry.DatabaseConnection+QueryBuilderare now top-level exports, so embedded callers get the building blocks from the package entry rather than deepdist/imports (which the shim no longer ships). Everything else the issue lists (CodeGraph,initGrammars/loadGrammarsForLanguages,FileLock) was already a top-level export.The CLI/MCP
binkeeps exec'ing the bundled Node — only library consumers run on their own runtime, which must be Node 22.5+ for the built-innode:sqlite(Electron qualifies when its Node is ≥22.5).node:sqliteis touched lazily, sorequire()itself loads fine on older Node and only errors when a graph is actually opened.Note on what is not restored
The
config.jsmodule (validateConfig/createDefaultConfig/CodeGraphConfig) the issue mentions was removed in 0.9.x when CodeGraph went zero-config (indexing is driven by.gitignore); it isn't reintroduced here.Validation
End-to-end against real packed artifacts (not mocks):
darwin-arm64bundle (build-bundle.sh) and packed the npm packages (pack-npm.sh).node_modulesfrom exactly those artifacts and, on the host Node (v22.20.0):require("@colbymchenry/codegraph")exposesCodeGraph,DatabaseConnection,QueryBuilder,initGrammars,FileLock,getDatabasePath,MCPServer, default =CodeGraph.CodeGraph.init→indexAll(real tree-sitter, 1 file / 3 nodes / 3 edges) →searchNodes, plus the low-levelDatabaseConnection.open+new QueryBuilderpath.nodenext(exercisesexports.types) and classicnoderesolution with realistic settings (skipLibCheck: true+@types/node).--version,status).npm test: 1090 passing; the only failures are the 5 pre-existingnpm-shim.test.tsdownload-fallback cases, which fail identically onorigin/main(unrelated, environmental). New__tests__/npm-sdk.test.tscovers SDK resolution, cache fallback, and the missing-bundle error.🤖 Generated with Claude Code