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

@cemiar/document-analysis

v1.0.20

Published

Cemiar package for document analysis API

Readme

@cemiar/document-analysis

SDK for Cemiar Document Analysis API. Provides document comparison, coverage validation, and data extraction capabilities for insurance documents.

Installation

npm install @cemiar/document-analysis

Quick Start

import { DocumentAnalysisApi } from "@cemiar/document-analysis";

const api = new DocumentAnalysisApi(
    process.env.DOCUMENT_ANALYSIS_URL,
    process.env.ACCOUNT_ID
);

// Use the different services
const excelBuffer = await api.comparator.compareRenewalExcel(payload);
const validationResult = await api.coverageValidator.validateFile("intact", file);
const extractedData = await api.extractor.extractDocument(payload);

Modules

The SDK provides three main modules accessible via DocumentAnalysisApi:

| Module | Description | Import Path | |--------|-------------|-------------| | Comparator | Compare insurance renewal documents | @cemiar/document-analysis/comparator | | CoverageValidator | Validate coverage against templates | @cemiar/document-analysis/coverage-validation | | Extractor | Extract structured data from documents | (main export) | | Common | Shared utilities and types | @cemiar/document-analysis/common |


Comparator

Compare insurance renewal documents and generate comparison reports.

Methods

compareRenewalExcel(payload): Promise<Buffer>

Generate an Excel comparison report between two policy versions.

import { DocumentAnalysisApi } from "@cemiar/document-analysis";
import { RenewalComparisonPayload } from "@cemiar/document-analysis/comparator";
import fs from "fs";

const api = new DocumentAnalysisApi(endpoint, accountId);

const payload: RenewalComparisonPayload = {
    before: {
        base64: fs.readFileSync("old-policy.pdf").toString("base64"),
        year: "2024",
        premium: 1200.00
    },
    after: {
        base64: fs.readFileSync("new-policy.pdf").toString("base64"),
        year: "2025",
        premium: 1350.00
    },
    client: {
        name: "John Doe",
        address: ["123 Main St", "Montreal, QC H1A 1A1"],
        language: "fr"
    },
    policyNumber: "POL-123456",
    type: "habitation",
    coverageValidations: [], // Optional: include validation results
    operationId: "op-123"    // Optional: for tracking
};

const excelBuffer = await api.comparator.compareRenewalExcel(payload);
fs.writeFileSync("comparison.xlsx", excelBuffer);

compareRenewalHtml(payload): Promise<Buffer>

Generate an HTML comparison report between two policy versions.

const htmlBuffer = await api.comparator.compareRenewalHtml(payload);
fs.writeFileSync("comparison.html", htmlBuffer);

Types

interface RenewalComparisonPayload {
    before: RenewalComparisonStatePayload;
    after: RenewalComparisonStatePayload;
    client: RenewalComparisonClientPayload;
    policyNumber: string;
    type?: string;
    insurer?: string;
    coverageValidations?: CoverageValidationTableResponse[];
    operationId?: string;
}

interface RenewalComparisonStatePayload {
    base64: string;  // Base64-encoded PDF
    year: string;
    premium: number;
}

interface RenewalComparisonClientPayload {
    name: string;
    address: string[];
    language: Language;  // "en" | "fr"
}

Coverage Validator

Validate insurance documents against coverage templates to detect missing or insufficient coverage.

Methods

validateFile(insurer, file): Promise<CoverageValidationTemplateResponse>

Validate a PDF document against an insurer's coverage template.

import { DocumentAnalysisApi } from "@cemiar/document-analysis";
import fs from "fs";

const api = new DocumentAnalysisApi(endpoint, accountId);

const file = {
    name: "policy.pdf",
    buffer: fs.readFileSync("policy.pdf")
};

const result = await api.coverageValidator.validateFile("intact", file);

// Process results
for (const table of result.results) {
    console.log(`Table: ${table.tableName}`);
    
    for (const group of table.results) {
        console.log(`  Group: ${group.groupName || "Default"}`);
        
        for (const coverage of group.results) {
            console.log(`    Coverage: ${coverage.coverageName}`);
            
            for (const check of coverage.checks) {
                if (check.isError) {
                    console.log(`      ❌ ${check.type}: ${check.message}`);
                } else {
                    console.log(`      ✅ ${check.type}`);
                }
            }
        }
    }
}

// Check for errors
if (result.error) {
    console.error(`Validation error: ${result.error.type} - ${result.error.message}`);
}

Types

interface CoverageValidationTemplateResponse {
    results: CoverageValidationTableResponse[];
    error?: CoverageValidationError;
}

interface CoverageValidationTableResponse {
    tableName: string;
    results: CoverageValidationGroupResponse[];
}

interface CoverageValidationGroupResponse {
    groupName?: string;
    results: CoverageValidationResponse[];
}

interface CoverageValidationResponse {
    coverageName: string;
    formName?: string;
    checks: CoverageValidationCheckResponse[];
}

interface CoverageValidationCheckResponse {
    type: CoverageValidationCheckType;
    isError: boolean;
    message?: string;
}

Enums

enum CoverageValidationCheckType {
    MINIMUM_COVERAGE = "MINIMUM_COVERAGE",  // Coverage meets minimum requirements
    PARTIAL_COVERAGE = "PARTIAL_COVERAGE",  // Coverage is partial/limited
    PRESENT = "PRESENT"                     // Coverage is present in document
}

enum CoverageValidationInsurer {
    INTACT = "intact"
}

Extractor

Extract structured data from insurance documents.

Methods

extractDocument(payload): Promise<ExtractedDocument>

Extract structured coverage data from a PDF document.

import { DocumentAnalysisApi } from "@cemiar/document-analysis";
import fs from "fs";

const api = new DocumentAnalysisApi(endpoint, accountId);

const result = await api.extractor.extractDocument({
    base64: fs.readFileSync("policy.pdf").toString("base64"),
    insurer: "intact",
    language: "fr",
    operation_id: "op-123"
});

console.log(`Insurer: ${result.insurer}`);
console.log(`Language: ${result.language}`);
console.log(`Premium: ${result.premium}`);

for (const situation of result.situations) {
    console.log(`\nSituation: ${situation.label}`);
    console.log(`  Address: ${situation.address}`);
    
    for (const table of situation.tables) {
        console.log(`  Table Headers: ${table.header.join(" | ")}`);
        for (const row of table.rows) {
            console.log(`    ${row.join(" | ")}`);
        }
    }
}

Types

interface ExtractDocumentPayload {
    base64: string;       // Base64-encoded PDF
    insurer: string;      // Insurer identifier
    language: Language;   // "en" | "fr"
    operation_id: string; // Unique operation ID for tracking
}

interface ExtractedDocument {
    insurer: string;
    language: Language;
    situations: Situation[];
    premium?: number | string;
    globalSituationLabel?: string;
}

interface Situation {
    label: string;
    address?: string;
    other?: string;
    tables: Table[];
}

interface Table {
    header: string[];
    rows: string[][];
}

Common Utilities

Language Type

import { Language } from "@cemiar/document-analysis/common";

const lang: Language = "fr"; // "en" | "fr"

Module Imports

You can import modules directly for tree-shaking:

// Main API
import { DocumentAnalysisApi } from "@cemiar/document-analysis";

// Comparator types and schemas
import { 
    RenewalComparisonPayload,
    RenewalComparisonStatePayload,
    RenewalComparisonClientPayload
} from "@cemiar/document-analysis/comparator";

// Coverage validation types and enums
import {
    CoverageValidationTemplateResponse,
    CoverageValidationTableResponse,
    CoverageValidationResponse,
    CoverageValidationCheckType,
    CoverageValidationInsurer
} from "@cemiar/document-analysis/coverage-validation";

// Common utilities
import { Language } from "@cemiar/document-analysis/common";

Environment Variables

| Variable | Description | |----------|-------------| | DOCUMENT_ANALYSIS_URL | Base URL of the Document Analysis API | | ACCOUNT_ID | Account identifier for API authentication |


Complete Example

import { DocumentAnalysisApi } from "@cemiar/document-analysis";
import { RenewalComparisonPayload } from "@cemiar/document-analysis/comparator";
import fs from "fs";

async function analyzeRenewal() {
    const api = new DocumentAnalysisApi(
        process.env.DOCUMENT_ANALYSIS_URL!,
        process.env.ACCOUNT_ID!
    );

    // Read PDF files
    const oldPolicy = fs.readFileSync("old-policy.pdf");
    const newPolicy = fs.readFileSync("new-policy.pdf");

    // Step 1: Validate coverage on new policy
    const validation = await api.coverageValidator.validateFile("intact", {
        name: "new-policy.pdf",
        buffer: newPolicy
    });

    // Check for coverage issues
    const hasErrors = validation.results.some(table =>
        table.results.some(group =>
            group.results.some(coverage =>
                coverage.checks.some(check => check.isError)
            )
        )
    );

    if (hasErrors) {
        console.warn("⚠️ Coverage validation found issues");
    }

    // Step 2: Extract data from new policy
    const extracted = await api.extractor.extractDocument({
        base64: newPolicy.toString("base64"),
        insurer: "intact",
        language: "fr",
        operation_id: `renewal-${Date.now()}`
    });

    console.log(`Found ${extracted.situations.length} situations`);

    // Step 3: Generate comparison report
    const payload: RenewalComparisonPayload = {
        before: {
            base64: oldPolicy.toString("base64"),
            year: "2024",
            premium: 1200
        },
        after: {
            base64: newPolicy.toString("base64"),
            year: "2025",
            premium: extracted.premium ? Number(extracted.premium) : 0
        },
        client: {
            name: "Jean Dupont",
            address: ["123 Rue Principale", "Montréal, QC H1A 1A1"],
            language: "fr"
        },
        policyNumber: "POL-123456",
        type: "habitation",
        coverageValidations: validation.results,
        operationId: `renewal-${Date.now()}`
    };

    // Generate Excel report
    const excelBuffer = await api.comparator.compareRenewalExcel(payload);
    fs.writeFileSync("renewal-comparison.xlsx", excelBuffer);

    // Generate HTML report
    const htmlBuffer = await api.comparator.compareRenewalHtml(payload);
    fs.writeFileSync("renewal-comparison.html", htmlBuffer);

    console.log("✅ Renewal analysis complete!");
}

analyzeRenewal().catch(console.error);

Building

npm run build

Output will be generated under dist/.