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

@ontrails/library

v0.2.3

Published

Render a Trails topo as an idiomatic TypeScript library.

Readme

@ontrails/library

Render a Trails topo as an idiomatic TypeScript library.

@ontrails/library is a peer surface for plain TypeScript consumers. It reads the same contract that CLI, MCP, and HTTP read, then renders that graph into function calls, package-facing errors, schema exports, and generated package files.

The package is publishable as the runtime dependency for generated Trails libraries. Generated packages can depend on it while keeping their consumer-facing API idiomatic and package-local.

Generated runtime dependencies default to a caret range of the installed compiler's package version, such as ^0.2.0 for a 0.2.0 compiler. Set libraryDependency when generating into an owned workspace or choosing a different runtime range.

API

import { compile, deriveLibraryApi, surface } from '@ontrails/library';

const renderingPlan = deriveLibraryApi(app);
const client = await surface(app);
const files = compile(app, {
  appExportName: 'app',
  appImportPath: '@acme/app',
  packageName: '@acme/generated',
});
  • deriveLibraryApi(graph, options) is the pure derivation. It returns the rendering plan that decides which public trails become library exports, how export names are derived, which trails are excluded, and where export-name collisions exist.
  • surface(graph, options) returns an in-memory callable client. The root call lane unwraps Result.ok into a return value and maps Result.err into typed LibraryError subclasses.
  • compile(graph, options) returns a stable file plan for a generated package. Writing those files is intentionally a thin apply step outside the compiler.

Generated package shape

Generated packages use one package with subpath exports:

.          consumer-fluent root functions and createX factories
./result   no-throw Result-returning functions
./schemas  authored Zod schemas and optional schema-owned type aliases
./trails   the Trails-native topo entrypoint

Stateless trails render to root named exports. Resource-bearing trails render behind a generated createX(options) factory so callers can provide resource configuration once and call several related methods from the same client.

Generated root and /result subpaths share one internal client module, so importing both subpaths does not open separate root library surfaces.

Typed signatures

Topo artifacts carry durable contract facts, but they do not preserve erased source-level TypeScript generics. Generated packages therefore stay honest by defaulting method signatures to unknown unless the caller binds a rendered trail id to the source trail export that owns its schema types:

const files = compile(app, {
  appExportName: 'app',
  appImportPath: '../fixture-app',
  packageName: '@acme/generated',
  trailTypeExports: {
    'widget.ping': 'pingTrail',
  },
  typeImportPath: '../fixture-trails',
});

With that binding, /schemas emits aliases such as WidgetPingInput = TrailInput<typeof pingTrail> and the root and /result subpaths use those aliases in their public signatures.

Typed layer inputs are rendered into the same public method input object as trail fields. When a layer field collides with a trail field or reserved surface name, the generated library input uses the same deterministic <layerName><Field> rename rule as other object-shaped surfaces. Runtime calls validate the rendered input, strip layer-owned fields before trail validation, and route them to the layer's own input slot. When a source trail type binding is provided, generated signatures widen layer-rendered inputs with Record<string, unknown> until layer input type exports have a source-level owner.

Errors

The root API throws package-facing LibraryError subclasses. This is a surface mapping, not an implementation behavior change: implementations still return Result.

The /result subpath preserves the no-throw envelope:

import { widgetPing } from '@acme/generated/result';

const result = await widgetPing(input);

The mapper is built with the shared Trails error taxonomy, so new categories must be covered before the package can typecheck.

Governance and dogfood

Library-derived facts are embedded in TopoGraph.library by Topography. Warden's library-render-coherence rule checks that serialized rendering facts do not drift from the graph, including missing target trails and export name collisions.

Run the focused package checks while changing the surface:

bun run library:smoke
bun run library:dogfood:warden

library:dogfood:warden compiles the Warden topo into a generated package, typechecks that generated package, runs a generated consumer test through root, /result, /schemas, and /trails, then dry-run packs it.