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

@hexdn/sdk

v0.4.0

Published

Trusted-server API client and playback helpers for HexDN.

Downloads

853

Readme

@hexdn/sdk

Typed HexDN API access and playback helpers for trusted servers. It has no runtime dependencies and works with standard Fetch and Web APIs in Node, Bun, and Workers. Keep the environment API key on your server; browser playback and uploads use their own scoped capabilities.

Before direct browser uploads, have your HexDN operator register your website for uploads once. Registration applies and verifies storage CORS automatically; there is no separate tenant storage configuration. Origin provisioning is currently an operator task, not a method on the public server SDK.

import { HexDN } from "@hexdn/sdk";

const hexdn = new HexDN({ apiKey: configuration.hexdnApiKey });

const asset = await hexdn.assets.create(
  {
    externalId: applicationVideo.id,
    outputs: [
      { type: "playback", access: "protected", renditions: "adaptive" },
    ],
  },
  { idempotencyKey: applicationUploadRequest.id },
);

// Your authorized application endpoint can return this scoped capability to
// @hexdn/upload. Attach asset.id and the requested output IDs to your own content.
return Response.json({ upload: asset.upload });

Asset/task creation and output creation generate an idempotency key when one is omitted. Supply a stable application key when an operation must survive retries across application requests. The SDK never chooses hidden outputs or product policy.

For an application that manages upload preparation and part tickets on its backend, use assets.createUpload instead of assembling a multipart plan or calling create and prepare separately:

const { asset, upload, plan } = await hexdn.assets.createUpload(
  {
    externalId: applicationVideo.id,
    outputs: [
      { type: "playback", access: "protected", renditions: "adaptive" },
    ],
  },
  sourceByteLength,
  { idempotencyKey: applicationUploadRequest.id, signal: request.signal },
);

The helper validates the source size, prepares the scoped upload, and returns the asset, upload capability, and multipart plan. A retry can also return an already completed upload; inspect upload.status before scheduling transfers. Keep the same application idempotency key across retries. For the direct @hexdn/upload flow above, uploadSource already handles preparation, reconciliation, transfer, and completion in the browser.

If your application reserves quota or creates durable records before contacting HexDN, validate the input first with the same checks used by createUpload:

import { validateAssetUploadInput } from "@hexdn/sdk";

validateAssetUploadInput(assetInput, sourceByteLength);

This pure function runs synchronously, makes no network requests, and throws HexDNError for invalid source sizes or request fields. It requires no API key and leaves the supplied input unchanged.

For protected playback, authorize the viewer in your endpoint, resolve the persisted playback ID, and return an SDK-ready source:

// Inside POST /api/videos/:videoId/playback in your server router:
const viewer = await application.requireViewer(request);
const video = await application.authorizeVideo(viewer, requestedVideoId);

const source = await hexdn.playback.createSource(
  video.playbackId,
  {},
  { signal: request.signal },
);

return Response.json(source, {
  headers: { "Cache-Control": "private, no-store" },
});

Pass that route to the React player as sourceEndpoint="/api/videos/42/playback", or to createPlaybackSourceEndpoint from @hexdn/playback. The browser receives only the authorized source envelope. The application supplies its normal viewer authentication and video lookup; those functions remain outside the SDK.

Viewer/session attribution and credential TTLs are optional advanced settings; ordinary playback uses the service defaults. Supply them only when your access policy needs them.

The helper validates playback/session URL scope and supplies the proof-header configuration expected by @hexdn/playback. Use the same authorized endpoint for renewal. Credentials and viewing attempts have separate lifecycles; this SDK does not create analytics attempts. Public ready outputs already provide a manifest URL and need no credential request. Lower-level playback.createSession, playback.createToken, and playback.revokeSession expose the documented control operations.

For signed playback, persist the ready output's signed playback result with your video and pass it to createSignedSource. No manifest or token URL assembly is needed:

// Inside POST /api/videos/:videoId/playback in your server router:
const viewer = await application.requireViewer(request);
const video = await application.authorizeVideo(viewer, requestedVideoId);
// video.playback is the SignedPlaybackResult from the ready playback output.
const source = await hexdn.playback.createSignedSource(
  video.playback,
  {},
  { signal: request.signal },
);
return Response.json(source, {
  headers: { "Cache-Control": "private, no-store" },
});

Use this same endpoint for acquisition and renewal. The helper validates the playback/version scope, signs the manifest and optional preview URLs, and returns expiresAt for the player to schedule renewal. Keep the persisted ready descriptor current when HexDN returns a replacement output version. Credential renewal preserves the playback identity and does not create an analytics attempt.

Playback-origin restrictions are optional. If your environment has playback origins configured, include your application's origin; an empty playback-origin list does not restrict origins. Upload and analytics origins are configured separately.

Available resource groups: assets, tasks, outputs, uploads, playback, webhookEndpoints, events, and analytics. Public API types are exported as components, operations, and paths, generated from the maintained HexDN OpenAPI contract and included in the published package.

Provision browser analytics once per origin configuration on your server:

const key = await hexdn.analytics.collectionKeys.create({
  origins: ["https://app.example"],
});
const publicAnalytics = hexdn.analytics.collectionConfig(key.id);

Use your application's exact origins (scheme, host and port), without wildcards. Pass publicAnalytics to @hexdn/analytics or the React player's analytics prop, adding a stable video identity when it is not already available. The helper makes no requests and derives routing from this client. Production browser integrations can also use just { collectionKey: key.id }. Keep the environment API key private.

const metrics = await hexdn.analytics.metrics({
  from: "2026-01-01", // Inclusive UTC day.
  to: "2026-02-01", // Exclusive UTC day.
  videoId: applicationVideo.id,
  groupBy: "day",
});
const keys = await hexdn.analytics.collectionKeys.list();

For a page of videos, pass videoIds once instead of requesting each video's metrics separately:

const period = await hexdn.analytics.metrics({
  from: "2026-08-01",
  to: "2026-09-01",
  videoIds: videos.map((video) => video.id),
});
const totals = await hexdn.analytics.totals({
  videoIds: videos.map((video) => video.id),
});
// One video is also supported: hexdn.analytics.totals({ videoId }).

Lists accept 1–100 identifiers and cannot be combined with videoId. Duplicates are removed in first-requested order. Period batches imply video grouping, reject day grouping and limits, and return one row per selected ID in that order. Grouped period rows keep their identifier in value; totals use videoId. Every row includes hasData: false means no accepted aggregate is available, with zero counters and null timestamps. It does not establish zero watching for a video that was not instrumented.

Period queries reject dates older than the rolling 13-calendar-month retention window. Totals accumulate starts and playing_ms independently of period retention, and accept no dates, grouping or limits. Their trackingSince is the earliest included UTC activity or attempt-cohort day; it does not promise the video's entire history was tracked or restore data pruned before totals began. updatedAt is the latest aggregate write time, not an ingestion watermark. Reads reflect reports after queue consumption, so collection is eventually visible. These counters summarize accepted client measurements; they are not authoritative proof of human watching or tenant-defined public views.

Analytics collection keys are browser-visible configuration; these management and query methods remain environment-authenticated. Analytics response types come from the maintained OpenAPI contract.

Verify and decode webhooks from the original request bytes:

import { verifyWebhookEvent } from "@hexdn/sdk";

const rawBody = new Uint8Array(await request.arrayBuffer());
const { event, deliveryId } = await verifyWebhookEvent({
  headers: request.headers,
  rawBody,
  signingSecrets: configuration.hexdnWebhookSecrets,
});

The helper verifies HMAC-SHA256 using WebCrypto, supports secret rotation, and rejects timestamps more than 300 seconds in the past or future. It validates the versioned envelope, required headers, and matching event, subject, root, and data identities. The returned event is typed and accepts optional additive fields. Previously queued output.playable deliveries retain their legacy event type after validation; new events use the current contract.

Verification failures expose HexDNWebhookVerificationError.code and detail. Your endpoint decides which events matter to your product. Atomically persist event.id with application changes before acknowledging delivery; repeated events must not apply those changes twice. Use deliveryId for delivery diagnostics. verifyWebhookSignature remains available when only signature verification is needed.

Requests default to a 15-second timeout per attempt and a 1 MiB JSON response limit, including streamed bodies. GET and explicitly idempotent requests may retry once on transient failure. Unkeyed credential creation and upload completion are not replayed automatically: an uncertain completion must be reconciled against authoritative state. Pass requestTimeoutMs and signal for tighter operation budgets. HexDNError exposes code, status, retryable, requestId, and available server details without attaching credentials.

Typed resource methods validate requests and responses against the maintained API contract, including identity bindings. They reject obsolete request fields before sending them. Application authorization and product validation remain your responsibility. Advanced adapters can use requestJson({ pathname, method, expectedStatuses, decode, ... }) for an operation outside those methods, supplying their own response decoder.

For internal Lab integrations, pass env: "lab" to the constructor. Omit it for production. This selects the HexDN service; the API key still identifies the tenant environment. Browser analytics configuration inherits this selection.

pnpm --filter @hexdn/sdk build
pnpm --filter @hexdn/sdk check:generated
pnpm --filter @hexdn/sdk typecheck
pnpm --filter @hexdn/sdk test

Build synchronizes the public declaration source from the existing contracts workspace. Published code and declarations do not depend on that private package.