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

@quantidia/sdk

v1.1.6

Published

Quantidia SDK for digital signature integrations (Fortify, Nexu, cloud signing)

Readme

@quantidia/sdk

JavaScript SDK for integrating Quantidia digital signature into any web application.

npm version license


CDN Integration (no build step)

Add the script tag before your app code. The SDK exposes window.Quantidia once loaded.

<script src="https://cdn.jsdelivr.net/npm/@quantidia/sdk/dist/quantidia-sdk.umd.min.js"></script>

Quick integration guide

1. Load and initialize

<script src="https://cdn.jsdelivr.net/npm/@quantidia/sdk/dist/quantidia-sdk.umd.min.js"></script>
<script>
  // Wait for the SDK to be available on window.Quantidia
  function waitForSdk(maxTries = 60, delayMs = 100) {
    return new Promise((resolve, reject) => {
      function check(triesLeft) {
        if (window.Quantidia) return resolve(window.Quantidia);
        if (triesLeft <= 0) return reject(new Error("SDK did not load"));
        setTimeout(() => check(triesLeft - 1), delayMs);
      }
      check(maxTries);
    });
  }

  async function main() {
    const SDK = await waitForSdk();

    SDK.init({
      baseUrl: "https://YOUR_QUANTIDIA_URL/integration",
      apiBase: "https://YOUR_QUANTIDIA_URL",
      view: "full", // "full" | "restricted" | "gateway"
      flow: "SSO_SIGN",
      quantidiaJava: {
        force: false,
        certificates: "https://localhost:9895/rest/certificates",
        sign: "https://localhost:9895/rest/sign",
      },
    });

    // SDK is ready
  }

  document.addEventListener("DOMContentLoaded", main);
</script>

2. Load PDF documents into the SDK

// From a file input
const input = document.getElementById("pdf-input");
input.addEventListener("change", async (e) => {
  const files = Array.from(e.target.files);

  SDK.clearDocuments();
  const docIds = await SDK.addDocuments(files);

  console.log("Loaded doc IDs:", docIds);
});
// From a URL (fetch → File)
async function fileFromUrl(url, filename) {
  const res = await fetch(url);
  const blob = await res.blob();
  return new File([blob], filename, { type: "application/pdf" });
}

const file = await fileFromUrl("./documents/contract.pdf", "contract.pdf");
SDK.clearDocuments();
const docIds = await SDK.addDocuments([file]);

3. Open the signing modal

With username and password

await SDK.openSigningWithLogin({
  authLogin: {
    authReference: {
      environmentId: "your-environment-id",
      userId: "external-user-id",       
      subscriptionId: "subscription-id", 
      companyId: "company-id",           
    },
    authLogin: {
      username: "[email protected]",
      password: "userpassword",
    },
  },
  headersOverride: {
    apiKey: "your-api-key",
    acceptLanguage: "es-AR",
  },
  docId: docIds[0],
  docIds: docIds,
});

With an access token

await SDK.openSigningWithLogin({
  authLogin: {
    authReference: {
      environmentId: "your-environment-id",
    },
    authLogin: {
      access_token: "eyJhbGci...",
    },
  },
  headersOverride: {
    apiKey: "your-api-key",
  },
  docId: docIds[0],
  docIds: docIds,
});

Custom signature position (optional)

By default the signature is placed at x: 200, y: 200 on page 1, sized 150x100 (PDF points). To control it, pass signatureRect alongside the auth params:

await SDK.openSigningWithLogin({
  // ...auth params
  docId: docIds[0],
  docIds,
  signatureRect: {
    page: 2, // 1-based page number
    x: 100,  // top-left corner, in PDF points
    y: 300,
    w: 200,  // optional, box width (default 150)
    h: 80,   // optional, box height (default 100)
  },
});

Coordinates use the top-left corner of the page as the origin (x grows right, y grows down), in PDF points — the same unit as the page size (e.g. an A4 page is 595 x 842). signatureRect is also accepted by SDK.openSigning({ pdfUrl, signatureRect }).


NPM / ES Module

Installation

npm install @quantidia/sdk

Imports

The package ships two entry points:

| Entry point | Contents | |---|---| | @quantidia/sdk | OpenAPI REST client (generated) | | @quantidia/sdk/ui | Signing UI — init, openSigningWithLogin, openSigning, addDocument(s), removeDocument, clearDocuments, close, listSignedDocuments, getSignedDocumentBytes, removeSignedDocument, clearSignedDocuments |

import {
  init,
  addDocuments,
  clearDocuments,
  openSigningWithLogin,
} from "@quantidia/sdk/ui";

TypeScript types are included — no @types package needed.


1. Initialize

Call init() once, before any other function. The same options apply as in the CDN version.

init({
  baseUrl: "https://YOUR_QUANTIDIA_URL/integration",
  apiBase: "https://YOUR_QUANTIDIA_URL",
  view: "full",        // "full" | "restricted" | "gateway"
  flow: "SSO_SIGN",   
  quantidiaJava: {
    force: false,
    certificates: "https://localhost:9895/rest/certificates",
    sign: "https://localhost:9895/rest/sign",
  },
});

| Option | Type | Required | Description | |---|---|---|---| | baseUrl | string | Yes | Base URL of the signing integration endpoint | | apiBase | string | Yes | Base URL of the API (without path) | | view | string | No | Signing UI view mode ("full" default) | | flow | string | No (recommended) | Which SDK flow to run. Currently only "SSO_SIGN" (login + sign, today's only flow) exists | | quantidiaJava | object | No | Local Nexu / Quantidia Java configuration | | quantidiaJava.force | boolean | No | Always route signing through the local Java agent | | quantidiaJava.certificates | string | No | Local agent certificates endpoint | | quantidiaJava.sign | string | No | Local agent sign endpoint |


2. Load documents

// From a file input element
fileInput.addEventListener("change", async (e) => {
  const files = Array.from(e.target.files);

  clearDocuments();
  const docIds = await addDocuments(files);

  console.log("Loaded doc IDs:", docIds);
});
// From a URL
async function fileFromUrl(url, filename) {
  const res = await fetch(url);
  const blob = await res.blob();
  return new File([blob], filename, { type: "application/pdf" });
}

const file = await fileFromUrl("/documents/contract.pdf", "contract.pdf");
clearDocuments();
const docIds = await addDocuments([file]);

addDocuments(files: File[]) returns Promise<string[]> — the list of document IDs to pass to the signing call.


3. Open the signing modal

With username and password

try {
  const result = await openSigningWithLogin({
    authLogin: {
      authReference: {
        environmentId: "your-environment-id",
        userId: "external-user-id",        
        subscriptionId: "subscription-id", 
        companyId: "company-id",           
      },
      authLogin: {
        username: "[email protected]",
        password: "userpassword",
      },
    },
    headersOverride: {
      apiKey: "your-api-key",
      acceptLanguage: "es-AR",
    },
    docId: docIds[0],
    docIds,
  });

  console.log("Signed:", result);
} catch (err) {
  console.error("Signing failed or cancelled:", err.message);
}

With an access token

const result = await openSigningWithLogin({
  authLogin: {
    authReference: {
      environmentId: "your-environment-id",
    },
    authLogin: {
      access_token: "eyJhbGci...",
    },
  },
  headersOverride: {
    apiKey: "your-api-key",
  },
  docId: docIds[0],
  docIds,
});

openSigningWithLogin returns a Promise that resolves when the user completes signing and rejects if the user cancels or an error occurs.

Both openSigningWithLogin and openSigning also accept an optional signatureRect: { page, x, y, w?, h? } to control where the signature is placed — see Custom signature position above.


4. Retrieve signed documents

Signed PDFs never leave the browser automatically — they're kept in an in-memory store so the integrator decides when and how to pick them up. There are two ways to get them:

a) From the resolved promise. The signed field on the result already lists the signed documents (metadata only, no bytes):

const result = await SDK.openSigningWithLogin({ /* ... */ });
console.log(result.signed);
// [{ id, name, mime, size, createdAt, sourceDocId }, ...]

b) On demand, via the store API. These are plain functions on SDK — same names whether you're using the CDN build (window.Quantidia) or the npm/ESM @quantidia/sdk/ui import:

// List everything currently stored (metadata only)
const docs = SDK.listSignedDocuments();
// [{ id, name, mime, size, createdAt, sourceDocId }, ...]

// Get the raw bytes for one signed document
const bytes = SDK.getSignedDocumentBytes(docs[0].id); // Uint8Array | null

// Remove one signed document from memory once you're done with it
SDK.removeSignedDocument(docs[0].id);

// Or clear everything at once
SDK.clearSignedDocuments();

Triggering a browser download (CDN example — no build tooling needed) — wrap the bytes in a Blob, turn that into an object URL, and click a hidden <a download>:

function downloadSignedDocument(meta) {
  const bytes = SDK.getSignedDocumentBytes(meta.id);
  if (!bytes) return;

  const blob = new Blob([bytes], { type: meta.mime || "application/pdf" });
  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = meta.name || "signed.pdf";
  a.click();

  URL.revokeObjectURL(url); // safe to revoke right after click() has fired
}

// Call this once the modal has closed, e.g. after openSigningWithLogin resolves/rejects:
SDK.listSignedDocuments().forEach(downloadSignedDocument);

To instead upload the signed PDF to your own backend rather than downloading it, skip the <a> and just fetch() the Blob (or the raw Uint8Array) to your endpoint — see examples/html-cdn/index.html for a full working page that renders a download link per signed document as soon as the modal closes.

getSignedDocumentBytes returns a copy of the bytes each time — the original stays in the store until you explicitly remove it. The store is also cleared automatically every time a new signing session is opened (openSigning / openSigningWithLogin), so make sure you've picked up any bytes you need before starting a new one.

For source documents loaded via addDocuments, the equivalent cleanup helpers are removeDocument(docId) and clearDocuments().


Bundler notes

Vite / webpack / Rollup — no special configuration needed from @quantidia/sdk ≥ 1.0.8.

If you are pinned to an older version (< 1.0.8), add a manual alias in vite.config.js to work around an incorrect exports path in those releases:

// vite.config.js  (only needed for @quantidia/sdk < 1.0.8)
import { defineConfig } from "vite";
import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default defineConfig({
  resolve: {
    alias: {
      "@quantidia/sdk/ui": path.resolve(
        __dirname,
        "node_modules/@quantidia/sdk/dist/ui.js"
      ),
    },
  },
});

Full working example

See examples/html-cdn/index.html for a complete browser integration using only a <script> tag.


License

MIT © Quantidia