npm-sdk.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. 'use strict';
  2. //
  3. // Programmatic / embedded SDK entry for @colbymchenry/codegraph (issue #354).
  4. //
  5. // The CLI/MCP `bin` (npm-shim.js) execs the per-platform bundle's OWN Node 24 so
  6. // the tool never depends on the user's runtime. Embedded library consumers are
  7. // the opposite case: they already run their own Node and just want the compiled
  8. // API — `require("@colbymchenry/codegraph")` returning the CodeGraph class et al.
  9. //
  10. // The compiled library + its production dependencies (web-tree-sitter,
  11. // tree-sitter-wasms, …) ship INSIDE the per-platform bundle, at
  12. // @colbymchenry/codegraph-<platform>-<arch>/lib/dist/index.js
  13. // (with the deps in the sibling lib/node_modules). Re-exporting that bundle keeps
  14. // the main package thin — no second 50 MB copy of the grammars — while making the
  15. // SDK work in the consumer's process. Types are a separate concern: the main
  16. // package ships its own dist/**/*.d.ts tree (pointed at by `types`), built from
  17. // the same release so it can never skew from the runtime it re-exports.
  18. //
  19. // node:sqlite (Node >= 22.5) is required to OPEN a graph, but only lazily inside
  20. // the SQLite adapter — so loading this module is safe on older Node, and the
  21. // node:sqlite requirement surfaces with an actionable error only when a DB is
  22. // actually opened. Heavy extraction additionally wants the bundled launcher's
  23. // --liftoff-only flag (the WASM Zone-OOM guard, issues #293/#298); an embedded
  24. // host that drives large indexing should pass that flag to its own Node.
  25. var path = require('path');
  26. var os = require('os');
  27. var fs = require('fs');
  28. var target = process.platform + '-' + process.arch; // e.g. darwin-arm64, linux-x64
  29. var pkg = '@colbymchenry/codegraph-' + target;
  30. module.exports = require(resolveLibrary());
  31. // Locate the compiled library entry inside the installed per-platform bundle.
  32. // Throws an actionable error (rather than a bare MODULE_NOT_FOUND) when no bundle
  33. // is present, so an embedded consumer knows exactly what to install.
  34. function resolveLibrary() {
  35. // 1) The npm-installed optional dependency — the normal case.
  36. try {
  37. return require.resolve(pkg + '/lib/dist/index.js');
  38. } catch (e) {
  39. /* fall through to the self-healed cache */
  40. }
  41. // 2) A bundle the CLI shim self-healed from GitHub Releases into the cache
  42. // (issue #303). Same node/lib/bin layout as the npm package. We only REUSE a
  43. // cached bundle here — unlike the CLI shim we never trigger a network
  44. // download from inside require(), which must stay synchronous and cheap.
  45. var cached = cachedLibrary();
  46. if (cached) return cached;
  47. throw new Error(
  48. 'codegraph: the programmatic API is unavailable because the platform bundle\n' +
  49. '(' + pkg + ') is not installed.\n' +
  50. 'The compiled library ships inside that per-platform optional dependency.\n' +
  51. 'Fixes:\n' +
  52. ' - install from the official npm registry so the matching bundle is fetched:\n' +
  53. ' npm i @colbymchenry/codegraph --registry=https://registry.npmjs.org\n' +
  54. ' - or run the CLI once (e.g. `npx @colbymchenry/codegraph status`) to\n' +
  55. ' self-heal the bundle into ~/.codegraph, then require() will find it.'
  56. );
  57. }
  58. function cachedLibrary() {
  59. try {
  60. var version = require(path.join(__dirname, 'package.json')).version;
  61. var base = process.env.CODEGRAPH_INSTALL_DIR || path.join(os.homedir(), '.codegraph');
  62. var lib = path.join(base, 'bundles', target + '-' + version, 'lib', 'dist', 'index.js');
  63. if (fs.existsSync(lib)) return lib;
  64. } catch (e) {
  65. /* no readable cache → caller reports the install guidance */
  66. }
  67. return null;
  68. }