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

@edvizion/pdfs

v0.1.1

Published

SDK and shared contract for the edvizion-pdfs service.

Readme

@edvizion/pdfs

TypeScript SDK and shared contract for edvizion-pdfs, Edvizion's PDF template rendering service.

This package is internal. It is published to the public npm registry for convenience of installation, not for general use. It is a client for a private Cloudflare Worker that is not publicly reachable — without access to Edvizion's infrastructure, this package cannot do anything useful.

There is no public API, no hosted demo, and no support for outside use.

What it is

The service stores per-organization PDF templates and renders them into PDFs. This package is the client for it, over either transport:

  • Service binding — Worker-to-Worker RPC. Trusted caller, no JWT.
  • HTTP — Bearer JWT, for callers outside the Cloudflare account.

Both expose the same methods, the same arguments, and the same error classes. Moving a caller between transports is an import change.

It also carries the contract: the zod schemas, TypeScript types, and error codes that the service itself validates against. Those are defined once and shared, so the client and the service cannot disagree about a payload shape without a compile error.

Access requirements

| Transport | Requires | | --- | --- | | @edvizion/pdfs/binding | a Worker in the same Cloudflare account as edvizion-pdfs | | @edvizion/pdfs (HTTP) | an AuthKit access token carrying an org_id claim and the right scope |

Service bindings are account-scoped, so the binding transport is unavailable outside Edvizion's account. The HTTP endpoint is deployed but every route except /health and /openapi.json requires a verified token.

Install

npm i @edvizion/pdfs

Quick start

Service binding — add to the calling Worker's wrangler.jsonc:

"services": [
  { "binding": "PDFS", "service": "edvizion-pdfs", "entrypoint": "PDFService" }
]
import { pdfs } from "@edvizion/pdfs/binding";

const client = pdfs(env.PDFS, { tenantID: org.id, userID: user.id });

const bytes = await client.generate({
  templateID: "tpl_standard_record_request",
  type: "record-request",
  payload,
});

HTTP:

import { PDFClient } from "@edvizion/pdfs";

const client = new PDFClient({
  baseURL: "https://api.edvizion.com/pdf",
  token: () => getAccessToken(),
});

const bytes = await client.generate({ templateID, type: "record-request", payload });

entrypoint: "PDFService" is required on the binding — omitting it binds the JWT-protected HTTP handler instead, and every call fails on auth.

Exports

| Import | Contents | Runs in | | --- | --- | --- | | @edvizion/pdfs | PDFClient — HTTP transport | Workers, Node, browser | | @edvizion/pdfs/binding | pdfs(), PDFBindingClient, PDFServiceBinding | Workers only | | @edvizion/pdfs/contract | types, zod schemas, error classes, PDFServiceContract | anywhere |

The contract is re-exported from both transport entry points, so importing it separately is only necessary when you want types without a client.

Documentation

SKILL.md ships with this package and is the complete integration guide: setup, every method, payload contracts, the error table, Liquid template authoring, and testing guidance. It is written to be handed directly to a coding agent — drop it at .claude/skills/edvizion-pdfs/SKILL.md in the consuming repo.

Errors

Both transports throw the same typed errors, rebuilt from a shared error code:

import { TemplateNotFoundError, InvalidTemplatePayloadError } from "@edvizion/pdfs/contract";

try {
  await client.generate({ templateID, payload });
} catch (error) {
  if (error instanceof InvalidTemplatePayloadError) return badRequest(error.issues);
  if (error instanceof TemplateNotFoundError) return notFound();
  throw error;
}

Cross-tenant access returns template_not_found, never a permission error — a response must never reveal that another organization's template exists.

Testing against it

The service is fully unit tested on its own. Consuming apps should test their own logic, not re-verify the service's rules. The binding is a plain structural interface with no Cloudflare types, so stubbing it needs nothing but an object literal:

const stub = { generate: vi.fn(), /* … */ } satisfies PDFServiceBinding;
const client = pdfs(stub, { tenantID: "org_a", userID: "user_a" });

A stub will accept calls the real service rejects. That is expected — a unit test against a double is not an integration test. See SKILL.md.

Versioning

This package and the deployed Worker share the contract, so they are released together. Adding a template type is additive and safe to roll out in either order. Changing an existing payload schema is breaking — tightening a field rejects payloads that previously worked — and requires publishing the SDK and deploying the Worker in lockstep.

License

UNLICENSED — proprietary to Edvizion. Published publicly for installation convenience; no rights are granted for outside use.