Skip to content

npm install of the published package cannot run: parser dist not shipped, no bin entry, bin root walk fails through the node_modules/.bin symlink, no runtime dependencies #886

Description

@swapnilpaliwal-sd

npm install of the published package produces an install that cannot run. Three separate causes, each of which alone is fatal, and none visible from a source checkout.

Symptom

On a machine with node and nothing else, installing the packed tarball and running the CLI fails on every language:

axiomcode: parser not built at .../parser/dist/index.js

After that is fixed, two more failures follow in sequence.

Causes

  1. The built parser is not shipped. package.json has no files field, so npm falls back to ignore rules, and it honours a workspace's own .gitignore too. parser/.gitignore ignores dist/, so parser/dist is dropped while parser/src/test-data ships. Installs clean, fails on first use.

  2. No bin entry. Nothing puts axiomcode on PATH, so there is no command after install. Adding it exposes the next one.

  3. bin/axiomcode cannot find its own root when invoked through a symlink. npm installs a bin entry as a link in node_modules/.bin. The root walk starts at dirname "$0", which is then .bin/, climbs the user's project, finds a package.json with no graph/ beside it, runs out of parents and returns /. The tool then reports parser not built at //parser/dist/index.js and advises npm install && npm run build, which is neither possible nor correct on an installed copy.

  4. No runtime dependencies are declared. dependencies is absent. The parser ships inside this tarball as parser/dist, but parser is a workspace, not a published package, so nothing installs what it requires. First use dies with Cannot find module 'typescript'.

Fix

  • files: list what ships. Explicit inclusion beats ignore rules, and a new build output is then included unless excluded rather than silently dropped.
  • bin: {"axiomcode": "bin/axiomcode"}.
  • bin/axiomcode: resolve $0 through symlinks before the root walk, and fail with a clear message if the marker is never found.
  • dependencies: hoist the parser workspace's runtime dependencies.

Side effect of files: the tarball drops from 81 MB to 3.1 MB (428 MB to 13.6 MB unpacked), because the test corpora stop shipping. All 145 engine rules still ship (java 55, typescript 26, python 38, javascript 26).

Evidence

Verified on a clean cloud VM with no souffle, no gcc, no make and no cmake, asserted absent before and after the node install. With all four fixes, installing only the two tarballs and running against four public OSS projects, one per language:

language time tables
java 11s 40
typescript 7s 63
python 25s 103
javascript 7s 52

Each run reports using packaged engine @axiomcode/engine-linux-x64, so the engine came from the package and nothing was compiled. The native parser dependencies (tree-sitter*) installed from prebuilt binaries with zero node-gyp invocations, so the no-compiler promise holds for the parser as well as the engine.

Relationship to #478

#478 makes the engine installable. These four defects sit in front of it: with them in place the engine is resolved correctly and the run still fails, because the parser half of the package is not installable. They are independent of the engine work and land on main.

Activity

  1. added
    bugSomething isn't working
    buildBuild, packaging and developer setup
    platformOS / toolchain portability
    on Sep 18, 2026
  2. swapnilpaliwal-sd commented on Sep 18, 2026

    @swapnilpaliwal-sd
    ContributorAuthor

    Fix is up in #887.

    For anyone picking this up. All four defects are on main and are independent of the engine packaging work in #478. Order matters only in that both are needed before a release: #478 makes the engine installable, and these four sit in front of it, so with #478 alone the engine resolves correctly from the package and the run still fails on the parser half.

    Compatibility. Nothing changes for a source checkout. The root walk in bin/axiomcode is unchanged when $0 is not a symlink, which covers every existing invocation (bin/axiomcode by path, npm run, the suites). files, bin and dependencies affect the tarball only.

    One thing to keep in step. The runtime dependencies are now duplicated between package.json and parser/package.json, because the parser ships inside this tarball but is a workspace that is never published. graph/test/tools/package-contents-test.sh asserts they match, so adding a parser dependency without hoisting it fails the preflight rather than shipping an install that dies on first use. If the parser is ever published as its own package, this duplication should go away and become a normal dependency.

    Watch out for. npm pack --dry-run runs prepare, whose output prints over the JSON, so the test passes --ignore-scripts and reads the manifest instead of building. Build outputs are asserted only when they exist on disk, so an unbuilt checkout skips rather than fails, and the skip is printed rather than silent, since a silent skip is how the missing parser went unnoticed in the first place.

    Testing an install properly. Stripping souffle from PATH is not enough on a machine where node and souffle share a directory, which is the default under Homebrew: appending node's directory to a cleaned PATH puts souffle back, and the test then proves nothing. Symlink the individual tools into a clean bin dir, as engine-package-test.sh already does.

  3. added 2 commits that reference this issue on Sep 18, 2026
    39c4169
    865be69
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingbuildBuild, packaging and developer setupplatformOS / toolchain portability

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions