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

scanforge

v1.1.0

Published

Official Node.js SDK for the scan-forge OCR service

Readme

scanforge

npm version License: MIT

Official Node.js SDK for the scan-forge OCR service — an on-premise, AI-powered drop-in replacement for ABBYY Recognition Server.

Installation

npm install scanforge

Requires Node.js 18+ (uses built-in fetch and FormData).

Quick Start

import { ScanForge } from 'scanforge';

const client = new ScanForge({ apiKey: 'sf_live_...' });

// Extract text from a PDF
const result = await client.ocr('faktura.pdf');
console.log(result.text);

// Detect barcodes
const barcodes = await client.barcodes('dokument.pdf');
barcodes.forEach(b => console.log(b.value, b.type));

// Convert a scan to DOCX
await client.convert('skan.png', { output: 'wynik.docx' });

API Reference

new ScanForge(config)

Creates a new client instance.

| Parameter | Type | Required | Default | |---|---|---|---| | config.apiKey | string | Yes | — | | config.baseUrl | string | No | https://api.scanforge.tech |

const client = new ScanForge({
  apiKey: 'sf_live_...',
  baseUrl: 'https://ocr.your-server.com', // for self-hosted deployments
});

client.ocr(filePath, options?)

Extracts text from a PDF or image file. The call submits an asynchronous OCR job on the server and transparently polls until it finishes, then resolves with the result — you don't need to manage the job lifecycle yourself.

Parameters

| Parameter | Type | Default | Description | |---|---|---|---| | filePath | string | — | Path to input file (PDF, PNG, JPG, TIFF) | | options.language | string | 'pol' | OCR language code | | options.pageNumber | number | — | Process a single page (0-indexed) | | options.pageRange | string | — | 1-indexed, inclusive page selector: '3' or '1-5'. Takes precedence over pageNumber. Omit for the whole document. | | options.separatePages | boolean | false | Return per-page output | | options.pollIntervalMs | number | 1500 | How often to poll the job while waiting | | options.timeoutMs | number | 600000 | Overall timeout (10 min) before throwing |

Returns Promise<OcrResult>

interface OcrResult {
  text: string;
  pages: number;
  metadata: Record<string, unknown>;
}

Example

const result = await client.ocr('invoice.pdf', { language: 'eng' });
console.log(result.text);   // extracted text
console.log(result.pages);  // number of pages processed

// Only OCR pages 1 through 5:
const partial = await client.ocr('long.pdf', { pageRange: '1-5' });

Low-level async API

ocr() and convert() are convenience wrappers over the async job API. If you want to submit a job and poll for it yourself (e.g. to show progress, or to hand polling off to a queue), use the low-level methods directly.

client.submitOcr(filePath, options?)

Uploads the file and submits an async OCR job, returning immediately. Accepts the same options as ocr() (language, pageNumber, pageRange, separatePages).

Returns Promise<{ jobId: string; status: 'queued' | 'running' | 'succeeded' | 'failed' }>

client.getOcrJob(jobId)

Fetches the current state of a job.

Returns Promise<OcrJob>

interface OcrJob {
  jobId: string;
  status: 'queued' | 'running' | 'succeeded' | 'failed';
  createdAt?: string;
  updatedAt?: string;
  result?: OcrSyncResponse; // present only when status === 'succeeded'
  error?: string;           // present only when status === 'failed'
}

Example

const { jobId } = await client.submitOcr('invoice.pdf', { pageRange: '1-5' });
let job = await client.getOcrJob(jobId);
while (job.status === 'queued' || job.status === 'running') {
  await new Promise((r) => setTimeout(r, 1500));
  job = await client.getOcrJob(jobId);
}
if (job.status === 'failed') throw new Error(job.error);
console.log(job.result.text);

client.barcodes(filePath, options?)

Detects and decodes barcodes (1D and 2D) in a document.

Parameters

| Parameter | Type | Default | Description | |---|---|---|---| | filePath | string | — | Path to input file | | options.pageNumber | number | 0 | Page to scan (0 = all pages) |

Returns Promise<BarcodeResult[]>

interface BarcodeResult {
  value: string;  // decoded barcode content
  type: string;   // symbology e.g. 'EAN-13', 'QR-Code', 'CODE-128'
  page: number;   // 1-indexed page number
}

Example

const barcodes = await client.barcodes('shipment.pdf');
for (const b of barcodes) {
  console.log(b.value, b.type, b.page);
}

client.convert(filePath, options)

Converts a PDF or image to an editable document format (DOCX or XLSX). The output format is determined by the file extension of options.output. Like ocr(), this runs as an asynchronous server job that the client polls to completion before writing the file.

Parameters

| Parameter | Type | Default | Description | |---|---|---|---| | filePath | string | — | Path to input file | | options.output | string | — | Destination path (.docx or .xlsx) | | options.language | string | 'pol' | OCR language code | | options.pageRange | string | — | 1-indexed, inclusive page selector: '3' or '1-5' | | options.pollIntervalMs | number | 1500 | How often to poll the job while waiting | | options.timeoutMs | number | 600000 | Overall timeout (10 min) before throwing |

Returns Promise<void> — writes the converted file to options.output.

Example

// Convert to Word document
await client.convert('scan.pdf', { output: 'result.docx' });

// Convert to Excel spreadsheet (preserves table structure)
await client.convert('table.pdf', { output: 'data.xlsx' });

Error Handling

All methods throw ScanForgeError on failure.

import { ScanForge, ScanForgeError } from 'scanforge';

const client = new ScanForge({ apiKey: 'sf_live_...' });

try {
  const result = await client.ocr('document.pdf');
} catch (err) {
  if (err instanceof ScanForgeError) {
    console.error(err.message);  // human-readable message
    console.error(err.status);   // HTTP status code (if applicable)
    console.error(err.body);     // raw response body from the server
  }
}

| Error condition | status | |---|---| | Invalid API key | 401 | | Unsupported file type | 422 | | Server error | 5xx | | Network / connection failure | undefined |


Configuration

Self-hosted deployment

Point the client at your own scan-forge server:

const client = new ScanForge({
  apiKey: 'sf_live_...',
  baseUrl: 'https://ocr.internal.example.com',
});

Environment variables (recommended)

Keep secrets out of your source code:

const client = new ScanForge({
  apiKey: process.env.SCANFORGE_API_KEY,
  baseUrl: process.env.SCANFORGE_URL, // optional
});

Requirements


License

MIT © Moonforge