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
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) andrequire(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 entriCLI Usage
The package exposes a command-line interface (entri) to instantly inspect entry points.
entri <package-name> [options]Options
--require- Resolve using CommonJSrequirerules instead of the default ESMimportrules.--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.jsJSON 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 toprocess.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'spackage.jsonfile.entry(string): The absolute path of the resolved entry point file.mode('import' | 'require'): Resolution conditions used.packageVersion(string | undefined): The version defined inpackage.jsonif 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:
- Clone the repository
- Install dependencies:
npm install - Run TypeScript build compiler:
npm run build - Run tests:
npm test
License
This project is licensed under the MIT License - see the LICENSE file for details.
