0.7.4

Fixed

  • Preserve file permissions from tarballs during extraction, fixing EACCES for native executables like tsgo
  • Run package scripts directly with node so package #imports resolve correctly
  • Detect native binaries and execute them directly instead of wrapping in a Node.js loader
  • Propagate non-zero exit codes from mix npm.run and mix npm.exec to the shell
  • Accept lockfiles without a policy section in --frozen install
  • Include optionalDependencies in lockfile consistency check for --frozen install

0.7.3

  • Skip browser field during resolution when its target extension is not in the resolvable set (fixes daisyUI resolving to .css when bundling JS)
  • Resolve package subpaths directly when no exports map is present, instead of falling back to root entry

0.7.2

Fixed

  • Extract tarballs with a non-package/ root directory, such as DefinitelyTyped @types/* packages, into the package root.

0.7.1

Fixed

  • Skip package versions with blocked transitive exotic dependencies during dependency solving instead of aborting resolution before a safe version can be selected.

0.7.0

Breaking changes

  • Reorganize supporting modules under domain namespaces. Compatibility wrapper modules were not retained because npm_ex is still pre-1.0.
  • Direct exotic dependencies such as git:, GitHub shorthands, URLs, and file: specs now require an explicit exotic_deps allowlist entry.
  • Transitive exotic dependencies from published package metadata are blocked by default.
  • Lockfiles written without the current dependency security policy are treated as stale.

Security hardening

  • Block transitive git, file, and URL dependency specs from published package metadata by default
  • Add config :npm support for registry, token, mirror, cache dir, install dir, registry policy, package age warnings, and exotic dependency policy
  • Move dependency analysis modules under NPM.Dependency.* and node_modules path helpers under NPM.NodeModules.Path
  • Move supply-chain security helpers under NPM.Security.*
  • Move lockfile helper modules under NPM.Lockfile.*
  • Move package metadata helpers under NPM.Package.*
  • Route JSON decoding through NPM.JSON across library modules
  • Move health, doctor, environment, and engine checks under NPM.Diagnostics.*
  • Move registry and .npmrc helpers under NPM.Registry.* and NPM.Config.*
  • Move install/runtime helpers under NPM.Install.* and NPM.Node.*
  • Enforce registry origin allowlists for packuments and tarballs
  • Record dependency security policy in npm.lock and invalidate locks generated with weaker policy
  • Block direct exotic dependencies unless their exact specs are listed in exotic_deps
  • Warn when registry metadata shows newly created packages or freshly published versions
  • Add NPM.Security.Compromised and mix npm.audit --osv/--compromised for OSV-backed malicious package checks
  • Merge OSV advisory writes into the shared compromised-package cache and fail online audit on OSV query errors

Migration map

BeforeAfter
NPM.AuditNPM.Security.Audit
NPM.CVENPM.Security.CVE
NPM.ExoticDepsNPM.Security.ExoticDeps
NPM.ProvenanceNPM.Security.Provenance
NPM.SupplyChainNPM.Security.SupplyChain
NPM.PackageJSONNPM.Package.JSON
NPM.ManifestNPM.Package.Manifest
NPM.ManifestDiffNPM.Package.Manifest.Diff
NPM.PackageFilesNPM.Package.Files
NPM.PackageQualityNPM.Package.Quality
NPM.PackageSpecNPM.Package.Spec
NPM.PublishConfigNPM.Package.PublishConfig
NPM.RepositoryNPM.Package.Repository
NPM.PeopleNPM.Package.People
NPM.KeywordsNPM.Package.Keywords
NPM.LicenseNPM.Package.License
NPM.FundingNPM.Package.Funding
NPM.FundNPM.Package.Fund
NPM.DepGraphNPM.Dependency.Graph
NPM.GraphOpsmerged into NPM.Dependency.Graph
NPM.DepTreeNPM.Dependency.Tree
NPM.DepSortNPM.Dependency.Sort
NPM.DepRangeNPM.Dependency.Range
NPM.DepConflictNPM.Dependency.Conflict
NPM.DepFreshnessNPM.Dependency.Freshness
NPM.DepStatsNPM.Dependency.Stats
NPM.DepCheckNPM.Dependency.UsageCheck
NPM.DepPathNPM.NodeModules.Path
NPM.PhantomDepNPM.Dependency.Phantom
NPM.PeerDep / NPM.PeerDepsNPM.Dependency.Peer
NPM.PeerDepsCheckNPM.Dependency.Peer.Check
NPM.PackageDuplicate / NPM.Dependency.Duplicatemerged into NPM.Dependency.Dedupe
NPM.PackageUpdate / NPM.Dependency.Updatemerged into NPM.Dependency.Outdated
NPM.LockfileCheckNPM.Lockfile.Check
NPM.LockfileStatsNPM.Lockfile.Stats
NPM.LockMergeNPM.Lockfile.Merge
NPM.PackageLockNPM.Lockfile.PackageLock
NPM.ShrinkwrapNPM.Lockfile.Shrinkwrap
NPM.HealthNPM.Diagnostics.Health
NPM.DoctorNPM.Diagnostics.Doctor
NPM.EnvCheckNPM.Diagnostics.EnvCheck
NPM.EngineCheckNPM.Diagnostics.EngineCheck
NPM.RegistryUrlNPM.Registry.URL
NPM.RegistryMirrorNPM.Registry.Mirror
NPM.ScopeRegistryNPM.Registry.Scope
NPM.TokenNPM.Registry.Token
NPM.NpmrcNPM.Config.Npmrc
NPM.NpmrcMergeNPM.Config.Npmrc.Merge
NPM.LinkerNPM.Install.Linker
NPM.LinkNPM.Install.Link
NPM.PruneNPM.Install.Prune
NPM.RebuildNPM.Install.Rebuild
NPM.CINPM.Install.CI
NPM.ScriptInstallNPM.Install.ScriptInstall
NPM.ScriptRunnerNPM.Install.ScriptRunner
NPM.LifecycleNPM.Install.Lifecycle
NPM.HooksNPM.Install.Hooks
NPM.NodeRunnerNPM.Node.Runner
NPM.ExecNPM.Node.Exec
NPM.BinNPM.Node.Bin
NPM.BinResolverNPM.Node.BinResolver

0.6.1

  • Harden tarball extraction against path traversal and absolute-path entries
  • Preserve install-script metadata in npm.lock
  • Warn when dependencies declare ignored lifecycle scripts
  • Document that npm_ex does not run package lifecycle hooks automatically, mitigating install-time credential stealers

0.6.0

0.5.3

  • Add NPM.PackageResolver.relative_import_path/3 — compute relative import paths between files within a project root, with guaranteed .//../ prefix

0.5.2

  • Add NPM.PackageResolver — Node.js module resolution algorithm (specifier parsing, node_modules traversal, package.json entry points, extension probing)
  • Fix ETS race condition in NPM.Resolver cache initialization
  • Fix NPM.Cache.ensure/5 spec and docs to include {:ok, :missing_optional} return
  • Fix dead code in NPM.PeerDeps version matching (redundant boolean case)
  • Fix NPM.FileSize.by_extension/1 dead || branch (Path.extname never returns nil)
  • Fix NPM.DepSort.install_order/1 dead {:error, :cycle} branch
  • Fix crash in NPM.Install.Linker nested version resolution on unparseable versions
  • Replace blanket rescue _ with specific exception types across the codebase
  • Flatten nesting in expand_all_optional_deps, solver_dependencies, select_group
  • Bump ex_dna ~> 1.1~> 1.3

0.5.1

  • Platform-agnostic lockfile: npm.lock now includes all optional platform bindings, not just the current platform
  • Only install matching platform bindings into node_modules at link time
  • Lockfiles are now portable across OS/arch — same as npm's package-lock.json behavior

0.5.0

0.4.6

  • Add packument disk cache (~/.npm_ex/packuments/) with 1h TTL — avoids refetching registry metadata on repeat installs
  • Skip resolution entirely when lockfile matches package.json and node_modules is intact

0.4.5

  • Switch default linker strategy from symlink to copy, fixing ESM module resolution for cached packages
  • Fix NodeRunner entrypoint resolution to follow bin symlinks correctly
  • Cache platform binding selection results, reducing resolve time from ~35s to ~1.5s for packages like oxfmt
  • Generalize platform binding family detection for both old-style (@oxfmt/darwin-arm64) and new-style (@oxfmt/binding-darwin-arm64) naming
  • Avoid grouping non-platform optional dependencies (e.g. @babel/core) as platform variants

0.4.4

  • Fix npm registry packument decoding for optional platform dependency inspection
  • Select the correct platform-specific optional binding for packages like oxfmt and oxlint
  • Keep mix npm.exec running binaries through Node instead of shell string spawning
  • Preserve optional_dependencies in npm.lock
  • Skip linking crashes when optional packages are unavailable

0.4.3

  • Fix mix npm.exec to resolve binaries via NPM.Node.Exec.which/2 and run them through Node instead of shell string spawning
  • Preserve optional_dependencies in npm.lock
  • Skip linking missing optional packages instead of crashing during install
  • Add focused test coverage for exec environment, cached Node runner execution, optional runtime linking, and resolver optional dependency handling

0.4.2

  • Speculative parallel prefetch of transitive dependencies before solving — fetches the full dep tree breadth-first with 16 concurrent requests
  • Deduplicate format_size/format_bytes across 8 modules into NPM.Format.bytes/1

0.4.1

  • Fix mix tasks crashing with unknown registry: Req.Finch when host app hasn't started the HTTP stack

0.4.0

New Mix Tasks (21 new, 43 total)

Install UX

  • mix deps-style output after install — packages listed as * name version (npm registry)
  • Progress reporting for resolution, fetching, and linking steps
  • Structured error messages with actionable suggestions
  • Lockfile diff output showing added/removed/updated packages on install
  • Project setup checklist (NPM.ProjectInit)

Dependency Analysis (30+ modules)

  • NPM.DepGraph — adjacency list, fan-in/out, cycle detection, orphans
  • NPM.GraphOps — transitive closure, shortest path, impact scoring
  • NPM.DepSort — topological sorting, parallel install levels
  • NPM.DepRange — classify ranges (exact, caret, tilde, star, file, git, url)
  • NPM.DepConflict — detect version conflicts between dependency groups
  • NPM.DepFreshness — classify package freshness (current, outdated, ancient)
  • NPM.DepStats — aggregate statistics (scope distribution, version breakdown)
  • NPM.DepPath — resolve bin and module paths within node_modules
  • NPM.DepCheck — verify installed tree matches lockfile
  • NPM.PhantomDep — detect undeclared (phantom) dependencies
  • NPM.HoistingConflict — detect version conflicts from hoisting
  • NPM.PeerDep / NPM.PeerDepsCheck — peer dependency validation
  • NPM.PackageUpdate — compute available major/minor/patch updates
  • NPM.OutdatedReport — npm outdated-style table formatting
  • NPM.SnapshotDiff — lockfile snapshot comparison
  • NPM.Package.Manifest.Diff — diff two package.json files
  • NPM.IntegrityCheck — verify installed packages match lockfile
  • NPM.LockfileCheck / NPM.LockfileStats — lockfile validation and metrics

Package Metadata (20+ modules)

Security & Supply Chain

  • NPM.CVE — CVE detection and scoring
  • NPM.SBOM — software bill of materials generation
  • NPM.SupplyChain — supply chain risk assessment
  • NPM.Provenance — package provenance verification
  • NPM.DeprecationAnalysis — deprecation severity analysis

Configuration

Infrastructure

Other

  • devDependencies support (--save-dev, --production)
  • optionalDependencies support (--save-optional)
  • --save-exact flag for pinning exact versions
  • node_modules/.bin/ executable linking
  • overrides support in package.json
  • Custom registry URL via NPM_REGISTRY env var
  • Auth token support via NPM_TOKEN env var
  • SHA-256 integrity verification (in addition to SHA-512 and SHA-1)
  • Retry with exponential backoff for failed HTTP requests
  • file: dependency references
  • 2,697 tests (up from 64)

0.3.1

0.3.0

  • mix npm.remove — remove a package from package.json
  • mix npm.list — show installed packages with versions
  • mix npm.install --frozen — fail if lockfile is stale (CI mode)
  • Fix scoped package parsing (@scope/pkg@^1.0 was splitting incorrectly)
  • Timing output for resolve and install steps
  • Rename install/2 to add/2 in the public API
  • Expand test suite to 64 tests

0.2.0

  • Global package cache at ~/.npm_ex/cache/ — download once, reuse across projects
  • node_modules/ linking via symlinks (unix) or copies (Windows)
  • Hoisted flat layout
  • Switch from :httpc to Req for HTTP
  • Add mix npm.get task
  • Add credo, ex_slop, ex_dna, dialyzer
  • Add unit and integration tests
  • Add GitHub Actions CI

0.1.0

Initial release.

  • mix npm.install — resolve and install all deps from package.json
  • mix npm.install <pkg> — add a package and install
  • PubGrub dependency resolution via hex_solver
  • npm registry client with abbreviated packuments
  • SHA-512 integrity verification
  • npm.lock lockfile for reproducible installs