mrkeyoor.com_
Sat 08 Aug 20:59 UTC
npmCLI & Toolingupdated 08 Aug 2026

precinct

precinct is a Node source-analysis dispatcher that extracts dependency specifiers from one file or syntax tree. It detects a JavaScript module style and hands the input to the matching detective, or you can force parsers for ESM, CommonJS, AMD, TypeScript, TSX, CSS, Sass, SCSS, Less, Stylus, and Vue. The main function analyzes supplied content; paperwork reads one path synchronously and infers its type from the extension. Results are plain strings, not resolved files or a dependency graph.

Verdict

precinct is a practical format switchboard for Node tooling, and version 13 is actively maintained. Do not mistake its string array for resolution or graph analysis, and avoid paying for all detectives when your inputs are only ESM.

API stability4/5The core contract remains small: precinct accepts source or an AST, paperwork accepts a filename, and both return string arrays. Version 13 publishes included types and a documented options table. Major releases can still be disruptive because the package tracks many parser dependencies and current engines jumped to specific Node 20.19 and 22.12 minimums. The mutable precinct.ast side channel is also weaker than returning parse state directly.
Docs5/5The README documents ESM and CommonJS loading, content versus file usage, every public option, the precinct.ast side channel, custom parsers, core-module filtering, all supported type aliases and extension rules, and the CLI flags. It clearly says that paperwork reads a file and that the result is dependency strings. The main missing detail is failure diagnostics: source parsing and unsupported types can produce an empty array without exposing the caught error.
Maintenance5/5Version 13.0.1 was published July 15, 2026, the repository was pushed August 4, 2026, and GitHub reports 3 open issues and pull requests. The package has already moved its parser and runtime floor to current Node lines and depends on current TypeScript 6 and PostCSS 8 releases. That is strong evidence of active upkeep, though each detective remains another compatibility surface that can drift.
Ecosystem4/5precinct recorded 4,766,166 downloads for the fetched week and unifies a broad family of detective packages for ESM, CommonJS, AMD, TypeScript, Vue, CSS, and four preprocessors. It is also a natural lower-level piece for packages such as dependency-tree and Madge. The tradeoff is a 15-package runtime dependency set and only 234 GitHub stars, suggesting much of its reach is transitive through tooling rather than direct application use.

Use it if

  • You need one API to scan dependency strings across JavaScript, TypeScript, Vue, CSS, and several preprocessors
  • You are building a Node CLI, audit, codemod prepass, or graph tool and already handle file discovery and module resolution elsewhere
  • You want to pass an existing JavaScript AST or swap in a parser through node-source-walk options
  • You need simple per-file dependency arrays and can force a detective when automatic JavaScript detection is ambiguous
Skip it if

Setup reality

Version 13.0.1 is Node-only and requires Node >=20.19.0 or >=22.12.0. The package is an ES module with a default export and a named paperwork export. On supported recent Node versions, the README also shows CommonJS loading as const {default: precinct} = require('precinct'); older CommonJS runtimes are outside the engine range. TypeScript declarations ship with the package. Installation is heavier than the tiny public API suggests because all format detectives are installed up front: AMD, CommonJS, ESM, TypeScript and TSX, PostCSS, Sass, SCSS, Less, Stylus, Vue 2, module-definition, node-source-walk, plus TypeScript and Commander. The main precinct(content) path parses JavaScript once with node-source-walk, sniffs the module format, and returns [] if parsing fails; the side-channel precinct.ast becomes null in that case. For non-JavaScript text, pass type explicitly because it must not go through the JavaScript parser. paperwork(filename) uses synchronous readFileSync, infers most types from the extension, and sniffs .js and .jsx. It scans one file only. You still need globs or a crawler, and a resolver if raw strings must become files. Mixed ESM and CommonJS collection is off by default, so set es6.mixedImports when both forms matter. CSS url() references are also off by default. includeCore applies only to paperwork and defaults to true. The precinct.ast property is overwritten by every call, which makes it useful for debugging but unsafe as per-call state in concurrent work; use the AST you supplied or parse separately when identity matters. Unknown types and unsupported syntax return an empty list rather than a detailed diagnostic. A custom parser can be passed under walker.parser for JavaScript, but per-detective options live under the matching type key. Finally, Vue support is routed through detective-vue2, so validate modern SFCs before treating an empty or partial result as authoritative.

Patterns

Extract dependencies from JavaScript sourcescan-javascript-source

import precinct from 'precinct'

const dependencies = precinct(`
  import express from 'express'
  import {readFile} from 'node:fs/promises'
`)

console.log(dependencies)

Without type, precinct parses and sniffs JavaScript. A parse failure returns an empty array and sets precinct.ast to null.

Read and scan one filescan-file-path

import {paperwork} from 'precinct'

const dependencies = paperwork('src/server.ts')
console.log(dependencies)

paperwork uses readFileSync and analyzes one file. It does not recurse or resolve returned specifiers.

Exclude Node core modulesexclude-node-builtins

import {paperwork} from 'precinct'

const externalOnly = paperwork('src/server.js', {includeCore: false})

includeCore is a paperwork option and defaults to true. Both fs-style and node:fs-style built-ins are filtered.

Force ESM detectionforce-esm-parser

import precinct from 'precinct'

const dependencies = precinct(source, {type: 'esm'})

Accepted aliases include es6, esm, and mjs. Forcing a type avoids module-definition sniffing when the input is known.

Collect ESM and CommonJS in one filescan-mixed-modules

const dependencies = precinct(source, {
  type: 'esm',
  es6: {mixedImports: true}
})

mixedImports defaults to false. The option lives under es6 even when the forced type uses the esm alias.

Scan TypeScript or TSXscan-typescript

const tsDependencies = precinct(tsSource, {type: 'ts'})
const tsxDependencies = precinct(tsxSource, {type: 'tsx'})

paperwork infers these from .ts and .tsx. TypeScript is installed as a runtime dependency in precinct 13.

Extract SCSS dependenciesscan-scss

const dependencies = precinct(`
  @use 'theme/colors';
  @import 'components/button';
`, {type: 'scss'})

Pass the type for non-JavaScript content so precinct does not send it through the JavaScript parser.

Include CSS url referencesinclude-css-assets

const dependencies = precinct(cssSource, {
  type: 'css',
  css: {url: true}
})

url() references such as fonts and images are excluded by default. @import dependencies are still handled by the CSS detective.

Ignore lazy AMD require callsscan-amd-eager-only

const dependencies = precinct(amdSource, {
  type: 'amd',
  amd: {skipLazyLoaded: true}
})

The option only affects inner lazy require calls in AMD. It does not change CommonJS require detection.

Analyze an existing JavaScript ASTscan-existing-ast

import precinct from 'precinct'

const ast = parser.parse(source, {sourceType: 'module'})
const dependencies = precinct(ast, {type: 'esm'})

The AST must match what the selected detective and node-source-walk expect. Passing it avoids reparsing source.

Use a custom JavaScript parsersupply-custom-parser

import * as babelParser from '@babel/parser'
import precinct from 'precinct'

const dependencies = precinct(source, {
  walker: {
    parser: {
      parse(code, options) {
        return babelParser.parse(code, {...options, sourceType: 'unambiguous'})
      }
    }
  }
})

The custom parser must expose parse(source, options). This walker option applies to the automatic JavaScript parse path, not stylesheet detectives.

Scan a file from the command linerun-precinct-cli

npx precinct --type ts src/index.ts

# Mixed ESM and CommonJS
npx precinct --es6-mixed-imports src/index.js

The CLI prints dependencies for one filename. It does not crawl directories or resolve a project graph.

Alternatives

PackageRegistryPick it when
madgenpmYou want a ready-made dependency graph, circular-dependency reporting, and visual output rather than a one-file scanner
dependency-treenpmYou want recursive dependency resolution from an entry file and a nested graph object
es-module-lexernpmYou only analyze JavaScript ESM and want a focused lexer with import ranges instead of every stylesheet detective
@babel/parsernpmYou need a complete JavaScript or TypeScript AST and will write dependency extraction for the exact syntax you support