mrkeyoor.com_
Sat 08 Aug 21:03 UTC
npmCLI & Toolingupdated 08 Aug 2026

parse-imports-exports

parse-imports-exports scans a JavaScript or TypeScript source string and returns a compact inventory of its module boundary. One function identifies static imports, dynamic imports with literal paths, require calls, reexports, ESM declarations, TypeScript type-only forms, interfaces, namespaces, and CommonJS assignments. Results are grouped by syntax kind and module specifier, with source offsets and optional line-column positions. It is designed for dependency analysis and code tooling that does not need a complete syntax tree or evaluation.

Verdict

A useful specialized scanner when input is valid and the exact import/export categories match your tooling job. Choose a full parser when malformed code, transformations, resolution, or unfamiliar syntax must be handled correctly.

API stability2/5There is only one runtime function, and version 0.2.4 supports both import and require with bundled types, which keeps the entry point simple. The returned contract is much larger: it has more than twenty optional syntax-specific properties, path-keyed arrays, branded names and positions, plus an errors map. Because the project remains below 1.0, consumers should isolate that shape behind their own adapter instead of spreading direct property access throughout a codebase.
Docs4/5The README gives an unusually comprehensive input sample and shows the corresponding result for static, dynamic, CommonJS, reexport, TypeScript type, interface, namespace, and declaration forms. It also documents every performance option and states the well-formatted-source limitation up front. Documentation is still one long page with no separate explanation of error recovery, end-offset semantics, resolver boundaries, or a compatibility matrix for newer proposal syntax.
Maintenance3/5Version 0.2.4 and the repository's latest push both date to February 16, 2025. The repository is not archived and GitHub reports 2 open issues and pull requests, but there has been no visible repository push for roughly eighteen months as of this guide. The exact parse-statements 1.0.11 dependency reduces surprise from upstream drift, while also making future parser fixes dependent on a new release here.
Ecosystem3/5The package recorded 4,968,139 downloads for the fetched week, publishes ESM and CommonJS builds, includes TypeScript declarations, and understands both modern ESM and several TypeScript and CommonJS forms. Its direct community footprint is small at 8 GitHub stars, and it deliberately does not provide AST tooling, path resolution, transforms, or editor integration. High installation volume therefore looks more transitive than community-led.

Use it if

  • You need a quick dependency inventory from already valid, consistently formatted JavaScript or TypeScript
  • Your tool must distinguish value imports, type-only imports, dynamic imports, require calls, reexports, and CommonJS assignments
  • You need source ranges for module statements but do not want the memory and traversal cost of a full AST
  • You ship for both ESM and CommonJS and want included TypeScript declarations from one small API
Skip it if

Setup reality

Install the package and import the single parseImportsExports function. Version 0.2.4 declares ESM internally but publishes conditional import and require entry points, so both import {parseImportsExports} from 'parse-imports-exports' and const {parseImportsExports} = require('parse-imports-exports') are supported. Types are included. There is one runtime dependency, parse-statements, pinned exactly to 1.0.11. The difficult part is not installation but consuming the result correctly. The function does not return one flat dependency list. It returns separate optional maps for namedImports, namespaceImports, dynamicImports, requires, typeNamedImports, typeNamespaceImports, typeDynamicImports, six reexport groups, and several local export groups. A missing group is undefined, not an empty object. Each module path maps to a non-empty array because the same specifier can occur more than once. Aliases are keyed by the local or exported name, with by holding the original name. Source start and end offsets are always present; includeLineColumn adds strings such as 3:12 at extra processing cost. The parser records syntax problems in errors rather than promising a complete result from malformed input, so decide whether any error invalidates your analysis. Its own README requires syntactically correct, well-formatted input, making a Prettier or compiler pass a sensible upstream boundary. Options can skip CommonJS exports, dynamic imports, regular-expression literals, require calls, or string-literal shielding for speed. The last two ignore options can create false positives if source text contains import-like tokens inside skipped literals, so enable them only when the input grammar makes that safe. This tool also stops at syntax discovery: feed raw specifiers into a separate resolver if you need actual files, package export conditions, tsconfig paths, or a dependency graph.

Patterns

Parse imports and exportsparse-module-boundary

import {parseImportsExports} from 'parse-imports-exports'

const result = parseImportsExports(`
  import {readFile as read} from 'node:fs/promises'
  export const load = (path) => read(path, 'utf8')
`)

console.log(result.namedImports, result.declarationExports)

Every result group is optional and absent groups are undefined. Treat result.errors as a failed or partial analysis according to your tool's policy.

List static import specifierslist-static-dependencies

const parsed = parseImportsExports(source)
const staticPaths = new Set([
  ...Object.keys(parsed.namedImports ?? {}),
  ...Object.keys(parsed.namespaceImports ?? {}),
  ...Object.keys(parsed.typeNamedImports ?? {}),
  ...Object.keys(parsed.typeNamespaceImports ?? {})
])

console.log([...staticPaths])

This includes type-only dependencies. Side-effect imports are represented in namedImports with position data but no default or names fields.

Read named imports and aliasesinspect-import-aliases

const parsed = parseImportsExports(
  "import {readFile as read, writeFile} from 'node:fs/promises'"
)

const entry = parsed.namedImports?.['node:fs/promises']?.[0]
for (const [localName, details] of Object.entries(entry?.names ?? {})) {
  console.log({localName, importedName: details.by ?? localName})
}

The names object is keyed by the local binding. An alias stores its original imported name in by.

Inspect default and namespace importsinspect-default-namespace

const parsed = parseImportsExports(
  "import React, * as ReactNS from 'react'"
)
const entry = parsed.namespaceImports?.react?.[0]
console.log(entry?.default, entry?.namespace)

Imports containing * as are placed in namespaceImports. A plain default import without a namespace is placed in namedImports.

Find dynamic imports and require callslist-runtime-loads

const parsed = parseImportsExports(source)
const lazyEsm = Object.keys(parsed.dynamicImports ?? {})
const commonJs = Object.keys(parsed.requires ?? {})

console.log({lazyEsm, commonJs})

The scanner records literal module paths. Computed expressions such as import(prefix + name) cannot become a concrete path entry.

Collect all reexport sourceslist-reexports

const parsed = parseImportsExports(source)
const groups = [
  parsed.namedReexports, parsed.namespaceReexports, parsed.starReexports,
  parsed.typeNamedReexports, parsed.typeNamespaceReexports, parsed.typeStarReexports
]
const sources = new Set(groups.flatMap((group) => Object.keys(group ?? {})))
console.log([...sources])

Reexports are separate from imports because they affect a package's public surface even when no local binding is created.

List exported runtime declarationslist-declaration-exports

const parsed = parseImportsExports(`
  export const port = 3000
  export async function start() {}
  export class Server {}
`)

for (const [name, item] of Object.entries(parsed.declarationExports ?? {})) {
  console.log(name, item.kind)
}

kind distinguishes const, class, async function, generators, enums, destructuring, declare forms, and other supported declaration shapes.

Separate TypeScript type exportsinspect-type-exports

const parsed = parseImportsExports(`
  export type ID = string
  export interface User { id: ID }
  export namespace Models {}
`)

console.log({
  aliases: Object.keys(parsed.typeExports ?? {}),
  interfaces: Object.keys(parsed.interfaceExports ?? {}),
  namespaces: Object.keys(parsed.namespaceExports ?? {})
})

These groups describe declarations only. The package does not parse members or resolve relationships between the declared types.

Detect CommonJS assignmentsinspect-commonjs-exports

const parsed = parseImportsExports(`
  module.exports = createApp()
  module.exports.version = '1.0.0'
`)

console.log(parsed.commonJsNamespaceExport)
console.log(parsed.commonJsExports?.version)

module.exports = value and property assignments use separate fields. This is syntax detection, not Node runtime evaluation.

Add line and column positionsinclude-line-columns

const parsed = parseImportsExports(source, {includeLineColumn: true})
const first = parsed.namedImports?.react?.[0]
console.log(first?.startLineColumn, first?.endLineColumn)

Line-column strings are optional and requested explicitly. Numeric start and end offsets remain available on every recognized statement.

Recover the original statement textslice-source-statement

const parsed = parseImportsExports(source)
const item = parsed.namedImports?.react?.[0]
if (item) {
  console.log(source.slice(item.start, item.end))
}

Keep the original source beside the result. Positions are metadata; the parser does not copy full statement text into each entry.

Skip syntax categories you do not needdisable-unneeded-scans

const parsed = parseImportsExports(source, {
  ignoreCommonJsExports: true,
  ignoreDynamicImports: true,
  ignoreRequires: true
})

These flags can reduce work and intentionally remove result groups. Be cautious with ignoreStringLiterals or ignoreRegexpLiterals because import-like text inside skipped literals may be misread.

Alternatives

PackageRegistryPick it when
es-module-lexernpmYou need a widely used low-level ESM lexer with exact import slices and are happy to handle a terser output format
@babel/parsernpmYou need a complete JavaScript or TypeScript AST for transformations, syntax recovery, scopes, and plugin syntax
acornnpmYou want a standards-focused JavaScript parser with a full ESTree-compatible AST and a plugin ecosystem
cjs-module-lexernpmYour main problem is fast CommonJS export and reexport detection rather than combined TypeScript and ESM reporting