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

@uns-kit/api

v2.0.45

Published

Express-powered API gateway plugin for UnsProxyProcess with JWT/JWKS support.

Readme

@uns-kit/api

@uns-kit/api exposes Express-based HTTP endpoints for UNS deployments. The plugin attaches a createApiProxy method to UnsProxyProcess, handles JWT/JWKS access control, automatically publishes API metadata back into the Unified Namespace, and serves a Swagger UI for every registered endpoint.

Note: Apps built with uns-kit are intended to be managed by the UNS Datahub controller. For the MQTT topic registry published by the API plugin, see ../../docs/uns-topics.md.

uns-kit in context

| Package | Description | | --- | --- | | @uns-kit/core | Base runtime (UnsProxyProcess, MQTT helpers, config tooling, gRPC gateway). | | @uns-kit/api | Express plugin — HTTP endpoints, JWT/JWKS auth, Swagger, UNS metadata. | | @uns-kit/cron | Cron-driven scheduler that emits UNS events on a fixed cadence. | | @uns-kit/cli | CLI for scaffolding new UNS applications. |

Installation

pnpm add @uns-kit/api
# or
npm install @uns-kit/api

@uns-kit/core must also be present — the plugin augments its UnsProxyProcess type.

How it works

  1. Import @uns-kit/api as a side-effect to register the plugin.
  2. Call process.createApiProxy(instanceName, options) to start an Express server.
  3. Register endpoints with api.get(...) or api.post(...).
  4. Listen to apiGetEvent / apiPostEvent to handle incoming requests.

Every registered endpoint is:

  • Automatically secured with JWT/JWKS or a shared secret.
  • Published to the UNS controller as an API metadata record (topic, host, path, method).
  • Added to the Swagger spec served at /<processName>/<instanceName>/swagger.json.

GET endpoint example

import UnsProxyProcess from "@uns-kit/core/uns/uns-proxy-process";
import type { UnsEvents } from "@uns-kit/core";
import "@uns-kit/api";
import { type UnsProxyProcessWithApi } from "@uns-kit/api";

const config = await ConfigFile.loadConfig();
const proc = new UnsProxyProcess(config.infra.host!, { processName: config.uns.processName }) as UnsProxyProcessWithApi;

const api = await proc.createApiProxy("my-service", {
  jwks: { wellKnownJwksUrl: config.uns.jwksWellKnownUrl },
  // or for simple/dev deployments: jwtSecret: "CHANGEME"
});

// Register a GET endpoint
// Signature: api.get(topic, asset, objectType, objectId, attribute, options?)
await api.get(
  "enterprise/site/area/line/",
  "line-3-furnace",
  "energy-resource",
  "main-bus",
  "current",
  {
    tags: ["Energy"],
    apiDescription: "Current reading for line-3-furnace main-bus",
    queryParams: [
      { name: "from",  type: "string", required: false, description: "Start of time range (ISO 8601)", chatCanonical: "from" },
      { name: "to",    type: "string", required: false, description: "End of time range (ISO 8601)",   chatCanonical: "to"   },
      { name: "limit", type: "number", required: false, description: "Maximum records",                chatCanonical: "limit", defaultValue: 100 },
    ],
    chatDefaults: { limit: 100 },
  }
);

// Handle incoming GET requests
api.event.on("apiGetEvent", (event: UnsEvents["apiGetEvent"]) => {
  const { from, to, limit } = event.req.query;
  // fetch your data here
  event.res.json({ status: "ok", data: [] });
});

POST endpoint example

// Register a POST endpoint
// Signature: api.post(topic, asset, objectType, objectId, attribute, options?)
await api.post(
  "enterprise/site/area/line/",
  "line-3-furnace",
  "energy-resource",
  "main-bus",
  "setpoint",
  {
    tags: ["Energy"],
    apiDescription: "Write a new setpoint for line-3-furnace main-bus",
    requestBody: {
      description: "Setpoint payload",
      required: true,
      schema: {
        type: "object",
        required: ["value"],
        properties: {
          value: { type: "number", description: "Target setpoint value" },
          unit:  { type: "string", description: "Unit of measurement, e.g. A" },
        },
      },
    },
  }
);

// Handle incoming POST requests — body is pre-parsed JSON
api.event.on("apiPostEvent", (event: UnsEvents["apiPostEvent"]) => {
  const { value, unit } = event.req.body;
  // write/command logic here
  event.res.json({ status: "ok", received: { value, unit } });
});

Endpoint signature

api.get(topic, asset, objectType, objectId, attribute, options?)
api.post(topic, asset, objectType, objectId, attribute, options?)

| Parameter | Type | Description | |---|---|---| | topic | UnsTopics | UNS topic path prefix (e.g. "enterprise/site/area/line/") | | asset | UnsAsset | Asset identifier (e.g. "line-3-furnace") | | objectType | UnsObjectType | UNS object type (e.g. "energy-resource") | | objectId | UnsObjectId | Object instance id (e.g. "main-bus") | | attribute | UnsAttribute | Attribute name (e.g. "current") | | options | IGetEndpointOptions / IPostEndpointOptions | Tags, description, query params / request body |

Auth options

| Option | When to use | |---|---| | jwks.wellKnownJwksUrl | Production — verifies RS256 tokens from the UNS controller JWKS endpoint | | jwks.activeKidUrl | Optional companion to JWKS — narrows which key ID is active | | jwtSecret | Development / simple deployments — symmetric secret |

Requests that fail auth return 401 Unauthorized. Requests whose token accessRules do not match the endpoint path return 403 Forbidden.

Unregistering an endpoint

await api.unregister(topic, asset, objectType, objectId, attribute, "GET");
await api.unregister(topic, asset, objectType, objectId, attribute, "POST");

This removes the route from Express, the Swagger spec, and the internal UNS endpoint registry.

registerCatchAll (uns-api-global only)

api.registerCatchAll() is reserved for the uns-api-global microservice, which acts as a catch-all gateway for an entire topic namespace. Regular microservices must not call this — use api.get() / api.post() for per-attribute endpoints instead.

Scripts

pnpm run typecheck
pnpm run build

build emits both JavaScript and type declarations to dist/.

License

MIT © Aljoša Vister