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

visura-parser

v1.3.0

Published

Deterministic parsing of text-based Italian Visura camerale PDFs

Readme

visura-parser

Visura Parser is a TypeScript library for deterministic parsing of Italian Visure camerali. It accepts text-based PDF bytes and returns typed data in the documented output schema.

The project is inspired by INDA's Visura Parser: the PDF must be text based.

Motivation

When working with Italian companies, you often need structured data about them. We wanted an open source parser that we could inspect, test, and improve.

This came up at Silkware, where we work with and onboard Italian companies. The Visura camerale is easy for companies to obtain and share, and it contains enough official registry data to make structured extraction useful.

Disclaimer

This library is developed with substantial help from AI coding agents. Contributions must meet the same fixture, correctness, and review requirements regardless of how the code was written. The parser should be treated as a best-effort tool, so it may fail for Visure layouts that are not in the private corpus. Feel free to open an issue if you encounter a layout that is not supported, or contribute yourself.

Requirements

  • Node.js 20 or newer for consumers
  • Bun 1.3.12 for contributors

Usage

Install the ESM package in your application:

npm install visura-parser
import { readFile } from 'node:fs/promises';
import { parseVisura, VisuraParseError } from 'visura-parser';

try {
  const bytes = new Uint8Array(await readFile('visura.pdf'));
  const data = await parseVisura(bytes, { filename: 'visura.pdf' });
  console.log(data.companyName, data.reaNumber);
} catch (error) {
  if (error instanceof VisuraParseError) {
    console.error(error.code);
  } else {
    throw error;
  }
}

The parser performs no filesystem or network access. filename is optional and is copied to filename; it is not inferred from the PDF.

Missing fields are omitted. Counts and monetary amounts are numbers; explicit availability values are booleans. Dates use ISO YYYY-MM-DD. Official Italian role names are preserved in structured officer and shareholder records. When the source prints them, individual officers and shareholders also include birth date, birthplace, birth-province code, citizenship, and residence address. Current secondary offices and local business units are returned in localUnits, in their printed order. When present, a local unit may also include its type, trade name, secondary activity, local ATECO code, ATECO classifications, activity declarations, and licences or authorisations. These filing and authorisation values preserve the printed source prose. Classification versions are included only when the source prints an explicit version heading. The local atecoCode is selected from the first PRIMARIA or PREVALENTE classification in source order, or the first unqualified classification; it is omitted for secondary-only classifications. See the local-unit corpus findings for field coverage and layout constraints. See the example output and the schema.

Ordinary, historical, evasion reports, and the supported shareholder Visura block are recognized. A block has no reportType. Image-only PDFs, password-required inputs, invalid PDFs, and unrelated documents produce typed errors; there is no OCR or language-model fallback.

Development

Parse a local PDF and print its JSON without building first:

bun run parse -- "/path/to/visura.pdf"

The command writes JSON to stdout and errors to stderr. It exits with code 1 on a read or parse failure, or 2 for invalid arguments. Use --help for usage. The output can contain personal data; keep it local and out of Git.

bun install
bun run check

Useful commands:

| Command | Purpose | | ----------------------- | ------------------------------------------- | | bun run build | Compile the package into dist/ | | bun run typecheck | Check TypeScript without emitting files | | bun run test | Run the test suite once | | bun run test:watch | Run tests while files change | | bun run lint | Run ESLint | | bun run format | Format supported files | | bun run package:check | Inspect the built npm package and its types |

To verify the supplied private corpus without logging document values:

bun run corpus:check -- /path/to/visure-examples --reference

The reference gate accounts for all 346 inputs: 341 supported text-based documents, three textless PDFs, one invalid PDF, and one unrelated PDF. It validates the complete schema, checks core identity presence, and compares repeated parses. Omit --reference for another folder.

Each run saves successful parser outputs in a fresh corpus-output/run-…/ directory, ignored by Git. A source named example.pdf produces example.pdf.json. The JSON summary includes the absolute outputDirectory path. Rejected inputs have no output file; their counts remain in the summary. These files can contain personal data, just like the source PDFs.

Contributing

Read the contributor guide before adding fixtures. Real Visure often contain personal data and must not be committed.

The public tests and synthetic fixtures work without access to the private corpus. To measure the built package on Node.js:

bun run benchmark
bun run benchmark -- /path/to/local/pdfs 3

The benchmark prints aggregate timings and result hashes, without filenames or document values. See the performance review and audit for the measurement method, findings, and remaining work.

License

MIT