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

@ifc-lite/plugin-api

v0.5.0

Published

Dependency-free type surface for ifc-lite file-source plugins

Readme

@ifc-lite/plugin-api

Dependency-free type surface for ifc-lite file-source plugins (CDE integrations).

Plugins implement FileSourceProvider and declare a PluginManifest. The host (the ifc-lite viewer) loads providers, auto-generates settings UI from the manifest's preferences array, and injects a sandboxed PluginContext at runtime.

See the architecture docs for the full design.

Registering your own provider in a viewer build

The viewer registers its built-in providers itself. A host application that builds the viewer from source can add its own FileSourceProvider implementations at build time, without patching viewer source: point the build's entry at a file of your own that calls the viewer's mountViewer (in apps/viewer/src/bootstrap.tsx, which is all the stock main.tsx does) with sourceProviders.

// Your entry, used in place of apps/viewer/src/main.tsx.
import { mountViewer } from './bootstrap';
import { AcmeProvider } from '@acme/ifc-lite-source';

mountViewer(document.getElementById('root')!, {
  sourceProviders: [() => new AcmeProvider()],
});

Each entry is a factory. The viewer constructs and registers each one on its own, after the built-ins, through the same SourceHost.register() path the built-ins use:

  • A manifest whose api does not satisfy PLUGIN_API_VERSION, a name that is already registered (a built-in's included), or an undeclared relay route is refused.
  • A factory that throws is caught.
  • A refused or failed provider is listed in the Sources panel as "failed to register" with the reason. It never stops the built-ins or any other provider from loading.
  • A registered provider gets the same sandboxed PluginContext as a built-in: https-only fetch to its declared permissions.network domains, no ambient credentials, no redirects, bounded retries, and storage namespaced by manifest.name.

This is build-time composition only. The viewer loads no provider code at runtime, and .iflx extensions get no new capabilities from it.

Reporting download progress

The host draws a per-file progress ring from DownloadOptions.onProgress. readWithProgress does the streaming for you: it reads a successful Response body, reports (received, total) about ten times a second, starts at (0, total) and ends at (byteLength, byteLength). The total is the response's Content-Length, else the fallback you pass (the file's listed size), else undefined, which the host shows as a spinner.

import { readWithProgress } from '@ifc-lite/plugin-api';
import type { DownloadOptions, PluginContext } from '@ifc-lite/plugin-api';

async function downloadBytes(
  ctx: PluginContext,
  url: string,
  sizeBytes: number | undefined,
  options?: DownloadOptions,
): Promise<ArrayBuffer> {
  const response = await ctx.fetch(url, { signal: options?.signal });
  if (!response.ok) throw new Error(`download failed: ${response.status}`);
  return readWithProgress(response, options?.onProgress, sizeBytes);
}

The @ifc-lite/source-fixture conformance suite checks that progress only increases and that its last call reports every byte returned.

Providers may report SourceFile.kind, an artifactName distinct from the resource name, and an unavailableReason for resources that cannot be imported. Unavailable rows stay visible with an explanation and cannot be selected. ProviderCapabilities.sourceNamePatterns customizes the catalog filter; an empty list shows every resource, including generated models without an IFC filename.

DownloadOptions.onPhase('preparing') reports preparation before bytes exist; use onProgress only for actual download bytes. Interactive providers may implement SourceAuth.cancelSignIn to invalidate a pending login. Hosts must guard late authentication and download results so cancelled operations cannot publish a new identity or enter the loader.