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

@suluk/openapi-compat

v0.1.5

Published

Lossless-where-possible conversion between the OpenAPI v4 'Suluk' candidate and OpenAPI 3.1 (the dialect Scalar/Swagger consume). CANDIDATE tooling.

Readme


CANDIDATE tooling — not official OpenAPI. Suluk is a single-contributor candidate for OpenAPI Specification v4.0 ("Moonwalk"), unaffiliated with the OpenAPI Initiative and unable to ratify anything on the SIG's behalf.

Install

bun add @suluk/openapi-compat

What it does

  • downgrade(v4) → 3.1 — projects a v4 "Suluk" document down to a real OpenAPI 3.1 document, the lever that lets 3.x-only renderers (Scalar, Swagger UI) show a v4 contract. Name-keyed requests become method-keyed Operations, per-location parameterSchema objects expand into parameters[], and the v4 request name is preserved as the operationId (round-trippable).
  • upgrade(3.1) → v4 — the reverse projection. Method-keyed Operations become name-keyed requests; flat parameters[] re-collect into per-location parameterSchema objects.
  • Honest diagnostics, never silent loss. Where v4 exceeds 3.1's expressivity — most notably two requests sharing one method on one path (C003) — downgrade keeps the first and emits a Diagnostic naming what was dropped, instead of losing it quietly. diagnostics is the audit trail.
  • validate31(doc) — checks a document against the vendored official OpenAPI 3.1 meta-schema (plus a real JSON-Schema-2020-12 pass over every Schema Object), proving the downgrade output is 3.1 a renderer will accept.
  • Schema Objects pass through verbatim. v4 and 3.1 share JSON Schema 2020-12 (SPEC C013 == OAS 3.1), so no Schema Object is rewritten in either direction — only the surrounding structure changes.

When to reach for it

  • You have a v4 document and need to feed it to a tool that only speaks OpenAPI 3.x. downgrade is the on-ramp; it's exactly what @suluk/scalar and @suluk/swagger call internally before handing the spec to their bundles.
  • You're ingesting a standard OpenAPI 3.1 (or 3.0, after normalization) document and want it as a v4 contract — the "Upgrade from 3.1" flow in @suluk/editor, or @suluk/better-auth's ingest of Better Auth's own schema.
  • You want a checked, lossless-where-possible round-trip and an explicit list of what 3.1 cannot represent.

Reach for a sibling instead when you want the rendered page, not the converted document: @suluk/scalar and @suluk/swagger produce self-contained HTML (and attach the v4 facet badges a plain downgrade would drop). This package is just the conversion + validation primitive underneath them.

Usage

Downgrade a v4 document to 3.1

import { downgrade, validate31 } from "@suluk/openapi-compat";
import { parseDocument } from "@suluk/core";

const v4 = parseDocument(yamlOrJsonText);          // an OpenAPIv4Document
const { document, diagnostics } = downgrade(v4);   // document is OpenAPI 3.1

// Anything 3.1 couldn't carry losslessly is reported, not dropped silently:
for (const d of diagnostics) {
  console.warn(`[${d.kind}] ${d.path}: ${d.message}`);
}

// Prove it's real 3.1 (validates against the official 3.1 meta-schema):
const v = validate31(document);
if (!v.valid) console.error(v.errors); // [{ path, message }, …]

downgrade returns { document, diagnostics }. Each Diagnostic is { kind, path, message } where kind is "collision" (lossy — two requests clash on one method), "remap" (a $ref/feature was rewritten), or "drop" (unrepresentable, e.g. a non-3.1 HTTP method).

Upgrade a 3.1 document up to v4

import { upgrade } from "@suluk/openapi-compat";

const v4doc = upgrade(spec31); // spec31: a parsed OpenAPI 3.1 document (plain object)
// → OpenAPIv4Document with openapi: "4.0.0-candidate"
// Operations become name-keyed `requests`; operationId becomes the request name.

A document that came from downgrade() carries operationId == the original v4 request name, so the round-trip recovers the original names:

import { downgrade, upgrade } from "@suluk/openapi-compat";

const back = upgrade(downgrade(v4).document); // names + methods recovered through the 3.1 hop

API

| Export | Signature | What it does | | --- | --- | --- | | downgrade | (doc: OpenAPIv4Document) => DowngradeResult | v4 → 3.1; returns { document, diagnostics }. | | upgrade | (doc31: Record<string, unknown>) => OpenAPIv4Document | 3.1 → v4 (the reverse projection). | | validate31 | (document: unknown) => Validation31 | Validate against the official 3.1 meta-schema; { valid, errors }. | | DowngradeResult | { document: Record<string, unknown>; diagnostics: Diagnostic[] } | type — the downgrade output. | | Diagnostic | { kind: "collision" \| "remap" \| "drop"; path: string; message: string } | type — one lossy/rewrite note. | | Validation31 | { valid: boolean; errors: { path: string; message: string }[] } | type — the validation result. |

The package has a single entry point (@suluk/openapi-compat) — no sub-path exports and no CLI.

Boundary

@suluk/openapi-compat is a pure conversion + validation library: three functions, no I/O, no globals, Workers-safe. It does not render a page, fetch a remote document, or host anything — it hands back a converted document and an honest diagnostics list, and the caller decides what to do with them. The rendered surfaces (@suluk/scalar, @suluk/swagger, @suluk/editor) are thin shells on top of it: they downgrade, then attach v4 facet badges and wrap the result in HTML.

The one rule when contributing: downgrade must emit an honest Diagnostic for anything 3.1 cannot express — extend the diagnostics, never the silence.

License

Apache-2.0