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

@europeum-ebsi/api-contract

v1.0.0-rc.2

Published

Generated types and scope grammar for the EBSI API's wire contract

Readme

EBSI API contract

Generated types and access-token scope grammar for @europeum-ebsi/api's wire contract.

Table of Contents

  1. Installation
  2. Usage
  3. License

Installation

npm install @europeum-ebsi/api-contract

Usage

Types

paths / components / operations / webhooks are generated from openapi.yaml (@europeum-ebsi/api's hand-written, spectral-linted OpenAPI 3.1 spec) via openapi-typescript. A small set of generic helpers look up a single endpoint's request/response shape by its path and HTTP method without hand-navigating the full paths tree:

import type { RequestBody, SuccessResponse } from "@europeum-ebsi/api-contract";

type CreateAccessTokenBody = RequestBody<"/auth/token", "post">;
type AccessTokenResponse = SuccessResponse<"/auth/token", "post">;

Regenerate src/api-types.ts with pnpm run gen:api-types whenever openapi.yaml changes -- openapi.yaml documents @europeum-ebsi/api's actual implemented behaviour, not the other way around.

Not every route the API serves is part of the contract: GET / (a plain-text liveness string), GET /health (the Terminus health check, superseded for external monitoring by the documented GET /alive), and this document's own discovery endpoints (GET /openapi.json / GET /openapi.yaml) are deliberately left undocumented, since they're infrastructure rather than API surface.

OpenAPI template

openapi.yaml is a Mustache template. The tags are placed so that the raw file stays valid YAML, and only two kinds are supported (no unescaped variables, partials or comments):

  • Sections named after a feature flag key, for the parts of the spec that document a feature behind that flag. They are rendered only when the flag is on ({{#flag}}) or off ({{^flag}}).
  • Variables in UPPER_SNAKE_CASE, such as {{DID_REGISTRY_CONTRACT_ADDRESS}}, for the values that depend on the environment.
description: |
  Always documented.
  {{#my-flag}}
  Documented only when `my-flag` is on.
  {{/my-flag}}
  {{^my-flag}}
  Documented only when `my-flag` is off.
  {{/my-flag}}
  The default contract address is `{{DID_REGISTRY_CONTRACT_ADDRESS}}`.

@europeum-ebsi/api-contract/openapi exports the renderer. A flag that isn't given is considered off. The optional third argument gives the values of the variables; a variable that isn't given is rendered as <NAME>, e.g. <DID_REGISTRY_CONTRACT_ADDRESS>. A name can't be used both as a flag and as a variable:

import { readFileSync } from "node:fs";
import {
  getOpenApiFeatureFlags,
  getOpenApiVariables,
  renderOpenApi,
} from "@europeum-ebsi/api-contract/openapi";

const template = readFileSync("openapi.yaml", "utf8");

getOpenApiFeatureFlags(template); // ["my-flag"]
getOpenApiVariables(template); // ["DID_REGISTRY_CONTRACT_ADDRESS"]
renderOpenApi(template, { "my-flag": true });
renderOpenApi(
  template,
  { "my-flag": true },
  { DID_REGISTRY_CONTRACT_ADDRESS: "0x..." },
);

@europeum-ebsi/api renders it at startup with the values of its feature flags and the configured contract addresses when serving GET /openapi.yaml and GET /openapi.json. The types generated by pnpm run gen:api-types come from the rendering with all the flags on, and pnpm run lint lints the renderings with all the flags on and all of them off.

Scopes

@europeum-ebsi/api-contract/scopes exports the access-token scope grammar (parsing, combinability rules, DCQL credential-query id derivation) shared between @europeum-ebsi/api's own authorisation logic and any client building requests against it (e.g. @europeum-ebsi/sdk).

import { parseScopeString } from "@europeum-ebsi/api-contract/scopes";

parseScopeString("openid did-registry:write");

It also exports, per registry, the scope each contract function requires (DID_REGISTRY_FUNCTION_SCOPE, ISSUERS_REGISTRY_FUNCTION_SCOPE, POLICIES_REGISTRY_FUNCTION_SCOPE, SCHEMAS_REGISTRY_FUNCTION_SCOPE, TIMESTAMP_FUNCTION_SCOPE, TRACK_AND_TRACE_FUNCTION_SCOPE): the API's Ledger service rejects any function not listed, and clients use them to mint the right token. The tables are checked at compile time against each contract's ABI (see the FunctionScopes type). Look a function up with functionScope(table, functionName):

import {
  DID_REGISTRY_FUNCTION_SCOPE,
  functionScope,
} from "@europeum-ebsi/api-contract/scopes";

functionScope(DID_REGISTRY_FUNCTION_SCOPE, "insertDidDocument"); // "did-registry:invite"

License

Copyright (C) 2026 European Union

This program is free software: you can redistribute it and/or modify it under the terms of the EUROPEAN UNION PUBLIC LICENCE v. 1.2 as published by the European Union.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the EUROPEAN UNION PUBLIC LICENCE v. 1.2 for further details.

You should have received a copy of the EUROPEAN UNION PUBLIC LICENCE v. 1.2. along with this program. If not, see https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12.