You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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
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.
No bin entry. Nothing puts axiomcode on PATH, so there is no command after install. Adding it exposes the next one.
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.
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.
#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.
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.
Activity
swapnilpaliwal-sd commentedon Sep 18, 2026
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
$0is not a symlink, which covers every existing invocation (bin/axiomcode by path, npm run, the suites).files,binanddependenciesaffect 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.shasserts 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-runrunsprepare, whose output prints over the JSON, so the test passes--ignore-scriptsand 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.shalready does.build: make the published package installable and runnable
build: make the published package installable and runnable
build: engines ship on npm as @axiomcode/engine-<os>-<cpu> (#904)