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

@veridia/functions-sdk

v1.0.29

Published

TypeScript SDK for developing and testing Veridia integration functions

Readme

@veridia/functions-sdk

TypeScript types and ambient declarations for writing handlers that run inside the Veridia functions runtime.

The SDK ships:

  • Handler types (ConnectionHandler, ActionHandler, DestinationHandler, plus pre-typed Kafka/HTTP aliases).
  • Event/response shapes (KafkaEvent, HttpEvent, HttpResponse, FunctionContext, FunctionResponse).
  • Error classes (InvalidEventPayload, ValidationError, EventNotSupported, RetryError, FinalError).
  • An ambient .d.ts (@veridia/functions-sdk/globals) that types the values the runtime injects into every handler module (veridiaClient, veridia, the five error classes).

Your handler runs in a sandboxed Deno isolate. The SDK is types-only — no runtime code from this package executes inside your function.

Requirements

Deno 2.x. The runtime is Deno-based; you write Deno modules, not Node ones.

Installation

Add the SDK to your deno.json import map:

{
  "imports": {
    "@veridia/functions-sdk": "npm:@veridia/functions-sdk@^1"
  }
}

Or use deno add:

deno add npm:@veridia/functions-sdk

To get types for the runtime-injected globals (veridiaClient, veridia, error classes), add this once at the top of your handler module — anywhere TypeScript sees it is enough:

import type {} from "@veridia/functions-sdk/globals";

Quick start

import type { ActionHandler } from "@veridia/functions-sdk";
import type {} from "@veridia/functions-sdk/globals";

type Secrets = { SLACK_WEBHOOK_URL: string };
type Parameters = { userId: string; message: string };

export const handler: ActionHandler<Parameters, Secrets> = async (
  parameters,
  secrets,
  context,
) => {
  console.log("sending slack message", { userId: parameters.userId });

  await fetch(secrets.SLACK_WEBHOOK_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text: parameters.message }),
  });

  veridiaClient.track(
    "userId",
    parameters.userId,
    "Slack Notification Sent",
    crypto.randomUUID(),
    new Date().toISOString(),
    { message: parameters.message },
  );
};

A handler module is just an ES module with a named handler export. The runtime invokes it once per inbound event.

Handler types

Every handler is (event | parameters, secrets, context) => Promise<TResponse>. secrets is passed explicitly — type it as a literal record to get autocomplete on keys. context is FunctionContext (tenant id, function id, idempotency key, etc.).

Connection — Kafka batch

import type { KafkaBatchConnectionHandler } from "@veridia/functions-sdk";

type Secrets = { API_KEY: string };
type OrderPayload = {
  orderId: string;
  userId: string;
  total: number;
  currency: string;
  placedAt: string;
};

export const handler: KafkaBatchConnectionHandler<Secrets> = async (
  batch,
  secrets,
  context,
) => {
  for (const event of batch) {
    const order = event.value as OrderPayload;

    veridiaClient.identify("userId", order.userId, {
      lastOrderId: order.orderId,
      lastOrderTotal: order.total,
    });

    veridiaClient.track(
      "userId",
      order.userId,
      "Order Placed",
      order.orderId,
      order.placedAt,
      { total: order.total, currency: order.currency },
    );
  }
};

KafkaEvent:

interface KafkaEvent {
  topic: string;
  partition: number;
  offset: string;
  key: string;
  value: unknown;                  // cast to your payload type
  headers: Record<string, string>;
  timestamp: string;
}

Connection — HTTP

import type { HttpConnectionHandler } from "@veridia/functions-sdk";

export const handler: HttpConnectionHandler = async (event, _secrets, _context) => {
  const body = JSON.parse(event.body ?? "{}") as { userId: string; email: string };
  veridiaClient.identify("userId", body.userId, { email: body.email });
  return { status: 204 };
};

HttpEvent / HttpResponse:

interface HttpEvent {
  method: string;
  path: string;
  headers: Record<string, string>;
  query: Record<string, string>;
  body?: string;
}

interface HttpResponse {
  status: number;
  statusText?: string;
  headers?: Record<string, string>;
  body?: string;
}

Action

Runs side effects from explicit parameters. Same shape as Connection but the input is a parameters object rather than an event:

import type { ActionHandler } from "@veridia/functions-sdk";

export const handler: ActionHandler<{ to: string; subject: string }, { API_KEY: string }> = async (
  parameters,
  secrets,
) => {
  await fetch("https://api.example.com/email", {
    method: "POST",
    headers: { Authorization: `Bearer ${secrets.API_KEY}` },
    body: JSON.stringify(parameters),
  });
};

Destination

Forwards an event to an external system:

import type { DestinationHandler } from "@veridia/functions-sdk";

type Event = { identifierId: string; eventType: string; properties: Record<string, unknown> };
type Secrets = { API_KEY: string; BASE_URL: string };

export const handler: DestinationHandler<Event, Secrets> = async (event, secrets) => {
  await fetch(`${secrets.BASE_URL}/events`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${secrets.API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(event),
  });
};

Error handling

Throw one of the SDK's error classes to signal a structured failure. The runtime classifies the response based on which class you threw. Anything else becomes "UnknownError".

| Class | When to use | |---|---| | InvalidEventPayload | The incoming event is malformed or missing required fields | | ValidationError | The data fails business-level validation | | EventNotSupported | The event type is not handled by this function | | RetryError | A transient upstream failure occurred; the invocation should be retried | | FinalError | A terminal failure; the invocation should not be retried |

The classes are available as runtime globals inside your handler (no import needed), and as named imports from @veridia/functions-sdk for tooling/tests:

import type { DestinationHandler } from "@veridia/functions-sdk";
import type {} from "@veridia/functions-sdk/globals";

export const handler: DestinationHandler<MyEvent, Secrets> = async (event, secrets) => {
  if (!event.userId) throw new InvalidEventPayload("userId is required");

  try {
    await fetch(secrets.ENDPOINT, { /* … */ });
  } catch (err) {
    throw new RetryError(`upstream failed: ${err}`);
  }
};

Runtime-injected globals

The runtime makes a small set of values available to every handler module without an import. Pull in the ambient declarations once with import type {} from "@veridia/functions-sdk/globals"; and you'll get types for:

| Global | Type | Purpose | |---|---|---| | veridiaClient | VeridiaClient | identify(...) profiles and track(...) events | | veridia | VeridiaServices | Channel + profile services (render templates, send in-app, resolve canonical ids, etc.) | | console | log collector | log / info / warn / error / debug; captured into FunctionResponse.logs | | Buffer | node:buffer.Buffer | Pre-bound for compatibility with npm packages that expect it | | InvalidEventPayload, ValidationError, EventNotSupported, RetryError, FinalError | error classes | See Error handling |

veridiaClient.identify(identifierType, identifierId, attributes) and veridiaClient.track(identifierType, identifierId, eventType, eventId, eventTime, properties) are queued; the runtime flushes them as part of the function response.

Importing dependencies

You can import any npm, JSR, or Deno-registered package directly in your handler module. The runtime resolves bare specifiers as npm packages automatically, so all four forms are equivalent and supported:

import _ from "lodash";                          // resolved as npm:lodash
import _ from "npm:lodash";                      // npm explicit
import { decode } from "jsr:@std/encoding/hex";  // jsr explicit
import { SMTPClient } from "https://deno.land/x/[email protected]/mod.ts";  // deno.land/x
import crypto from "node:crypto";                // node built-ins via Deno's node compat

Allowed prefixes:

  • npm: — any package on the npm registry (default for bare specifiers).
  • jsr: — any package on JSR.
  • node: — Node built-ins via Deno's node compatibility layer (node:crypto, node:buffer, node:zlib, node:timers, node:net, node:tls, …).
  • https://deno.land/... and https://jsr.io/... — direct URL imports from the two allowlisted hosts.

Other HTTPS hosts (esm.sh, unpkg, raw GitHub, etc.) are blocked by the runtime. Relative imports (./helpers.ts) don't work — each function is a single module file.

Persistent state across invocations

Top-level state in your handler module is preserved for the lifetime of a warm worker. Plain Maps, Sets, or module-level let bindings all work — there's no SDK-provided cache abstraction, because you don't need one:

import type { ActionHandler } from "@veridia/functions-sdk";

type Token = { value: string; expiresAt: number };
const tokens = new Map<string, Token>();

export const handler: ActionHandler<Parameters, Secrets> = async (parameters, secrets) => {
  let token = tokens.get(secrets.CLIENT_ID);
  if (!token || token.expiresAt < Date.now()) {
    const res = await fetch("https://auth.example.com/token", {
      method: "POST",
      body: JSON.stringify({
        client_id: secrets.CLIENT_ID,
        client_secret: secrets.CLIENT_SECRET,
      }),
    });
    const { access_token } = await res.json();
    token = { value: access_token, expiresAt: Date.now() + 50 * 60 * 1000 };
    tokens.set(secrets.CLIENT_ID, token);
  }

  await fetch("https://api.example.com/do-thing", {
    headers: { Authorization: `Bearer ${token.value}` },
    method: "POST",
    body: JSON.stringify(parameters),
  });
};

The state is per-worker and in-memory — it disappears on cold start and is not shared between workers or regions.

Exports

| Import path | Contents | |---|---| | @veridia/functions-sdk | Handler / event / response types, error classes, VeridiaClient / VeridiaServices types | | @veridia/functions-sdk/globals | Ambient .d.ts declarations for veridiaClient, veridia, and the error classes |

License

MIT