npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

entri

v0.1.0

Published

Explain and resolve Node.js package entry points without executing package code.

Downloads

131

Readme

Languages: English · Čeština · Deutsch · Polski · Русский · Українська · Українська

entri

npm version license

Explain and resolve Node.js package entry points safely using native resolution rules—without importing, executing, or loading target package code.


Why entri?

In modern Node.js development, determining which file is executed when you import or require a package can be surprisingly complex due to the combination of exports fields, main paths, conditional maps, and file extensions.

Typically, finding out which entry point is chosen requires executing or loading the module, which is unsafe (due to lifecycle scripts or side effects) and heavyweight.

entri provides a lightweight, pure-metadata way to determine exactly how Node.js resolves any package from any directory, utilizing Node's built-in resolution mechanism.

Key Features

  • 🚀 Zero Code Execution: Evaluates target files metadata-only. Never executes modules or registers side-effects.
  • 🔄 ESM & CommonJS Modes: Support for both import (ESM) and require (CommonJS) condition flows.
  • 📦 Modern Exports Resolution: Fully implements Node's subpath exports, imports, and conditions.
  • 🔍 Hierarchy Inspection: Auto-detects parent package scopes and extracts versions/paths.
  • 💻 CLI Included: Test package entry points instantly from your terminal.

How It Works

graph TD
    A[Start Resolution] --> B{Valid specifier?}
    B -- No --> C[Throw INVALID_REQUEST]
    B -- Yes --> D{Resolve Mode?}
    D -- require --> E[Node.js createRequire.resolve]
    D -- import --> F[Node.js import.meta.resolve]
    E --> G[Resolved Entry Path]
    F --> G
    G --> H{inspectPackageEntry?}
    H -- No --> I[Return Entry Path]
    H -- Yes --> J[Search package.json in dirname of Entry Path]
    J --> K{Found package.json?}
    K -- Yes --> L[Parse and Return PackageEntry Object]
    K -- No --> M[Walk directory hierarchy upwards]
    M --> N{Found package.json in parent?}
    N -- Yes --> L
    N -- No --> O[Throw ENTRY_NOT_FOUND]

Installation

Install using your preferred package manager:

# npm
npm install entri

# yarn
yarn add entri

# pnpm
pnpm add entri

CLI Usage

The package exposes a command-line interface (entri) to instantly inspect entry points.

entri <package-name> [options]

Options

  • --require - Resolve using CommonJS require rules instead of the default ESM import rules.
  • --json - Output the result as a formatted JSON object.
  • --help, -h - Display CLI usage instructions.

Examples

Basic output:

$ npx entri typescript
[email protected]
mode:         import
package.json: /path/to/node_modules/typescript/package.json
entry:        /path/to/node_modules/typescript/lib/typescript.js

JSON output for scripts integration:

$ npx entri typescript --require --json
{
  "packageName": "typescript",
  "packageJson": "/path/to/node_modules/typescript/package.json",
  "entry": "/path/to/node_modules/typescript/lib/typescript.js",
  "mode": "require",
  "packageVersion": "5.8.3"
}

API Reference

resolvePackageEntry(specifier, options?)

Resolves the absolute path to the entry point file of a package.

Parameters

  • specifier (string): The npm package name (e.g. "typescript", "lodash", or scoped packages like "@types/node").
  • options (ResolveOptions) (Optional):
    • from (string): The absolute directory path to resolve the package from. Defaults to process.cwd().
    • mode ('import' | 'require'): Resolution conditions to use. Defaults to 'import'.

Returns

string - The absolute path of the resolved entry file.

Example

import { resolvePackageEntry } from "entri";

try {
  const entry = resolvePackageEntry("typescript", { 
    from: process.cwd(), 
    mode: "import" 
  });
  console.log("Resolved entry:", entry);
} catch (error) {
  console.error("Resolution failed:", error.message);
}

inspectPackageEntry(specifier, options?)

Resolves the package entry point and walks up the tree to find its associated package.json and package version.

Parameters

  • Same parameters as resolvePackageEntry.

Returns

Promise<PackageEntry> - A promise resolving to the package details:

  • packageName (string): The package name resolved from metadata.
  • packageJson (string): The absolute path to the package's package.json file.
  • entry (string): The absolute path of the resolved entry point file.
  • mode ('import' | 'require'): Resolution conditions used.
  • packageVersion (string | undefined): The version defined in package.json if available.

Example

import { inspectPackageEntry } from "entri";

const info = await inspectPackageEntry("typescript", { mode: "require" });
console.log(`Resolved: ${info.packageName}@${info.packageVersion}`);
console.log(`Entry path: ${info.entry}`);
console.log(`Metadata path: ${info.packageJson}`);

Types

export type ResolveMode = "import" | "require";

export interface ResolveOptions {
  from?: string;
  mode?: ResolveMode;
}

export interface PackageEntry {
  packageName: string;
  packageJson: string;
  entry: string;
  mode: ResolveMode;
  packageVersion?: string;
}

Error Handling

All resolution and validation errors throw a custom PackageEntryError object containing a descriptive message and an error .code.

import { PackageEntryError } from "entri";

try {
  await inspectPackageEntry("invalid-package-xyz");
} catch (error) {
  if (error instanceof PackageEntryError) {
    console.log("Error code:", error.code);
    // "PACKAGE_NOT_FOUND" | "ENTRY_NOT_FOUND" | "INVALID_REQUEST"
  }
}

Error Codes

| Code | Description | |---|---| | INVALID_REQUEST | The provided package name/specifier is malformed or invalid (e.g. relative path, empty). | | PACKAGE_NOT_FOUND | The package could not be resolved from the reference directory (check install status/path). | | ENTRY_NOT_FOUND | The package was found, but its entry point is missing, or package metadata could not be retrieved. |


Contributing & Development

We welcome improvements and feedback. To set up the project locally:

  1. Clone the repository
  2. Install dependencies:
    npm install
  3. Run TypeScript build compiler:
    npm run build
  4. Run tests:
    npm test

License

This project is licensed under the MIT License - see the LICENSE file for details.