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

@primafuture/contrib-kit-core

v1.2.0

Published

Framework-agnostic extension points and contribution registry with deterministic lifecycle orchestration.

Readme

@primafuture/contrib-kit-core

Framework-agnostic extension points and a contribution registry with deterministic activation, replacement, cleanup, and teardown ordering.

Installation

pnpm add @primafuture/contrib-kit-core

Contrib Kit Core is ESM-only and has no framework or runtime dependencies. Import the package root; internal and source subpaths are intentionally not exported.

Basic registry flow

import * as contribKitCore from "@primafuture/contrib-kit-core";

interface MenuContext {
	readonly includeAdmin: boolean;
}

interface MenuItemData {
	readonly label: string;
	readonly adminOnly: boolean;
}

interface MenuItemImplementation {
	render(label: string): string;
}

const menuPoint = contribKitCore.defineExtensionPoint<
	MenuContext,
	MenuItemData,
	MenuItemImplementation
>()({
	pointId: "example/menu-items",
	contractVersion: 1,
	cardinality: "many",
	filter(contribution, context): boolean {
		return context.includeAdmin || !contribution.data.adminOnly;
	},
	selectionPolicy: {
		select(contributions) {
			return contributions.slice(0, 5);
		},
	},
});

const registry = contribKitCore.createExtensionRegistry();
const pointOwner = registry.rootScope.registerPoint(menuPoint);
const registration = registry.registerContribution(menuPoint, {
	contributionId: "example/menu-items/home",
	expectedContractVersion: 1,
	data: { label: "Home", adminOnly: false },
	implementation: {
		render(label): string {
			return label;
		},
	},
});

await registration.whenActive();

const catalog = registry.listContributions(menuPoint);
const visible = registry.resolveContributions(menuPoint, { includeAdmin: false });

console.log(catalog.length, visible[0]?.implementation.render(visible[0].data.label));

await registration.dispose();
await pointOwner.close().whenCleanupFinished();
await registry.dispose();

Admission returns a pending handle and activation starts from the point-local FIFO in a later microtask. Call whenActive() only when the host needs the activation outcome. A rejected activation never enters the committed catalog.

Resolved collection policy

resolveContributions() applies one captured synchronous pipeline:

context validation → filter → ordering → selection

ContributionSelectionPolicy sees the complete ordered view and returns an order-preserving canonical subset. This is the right place for collective membership rules such as limits, companion entries, exclusivity winners, or removal of orphaned structural records.

Define selectionPolicy on the point for the shared default. A point owner may supply a local override while registering a generation, and pointOwner.updatePolicy({ selectionPolicy: null }) clears that override and restores the latest definition default. Selection changes resolved membership only; they never remove committed registrations from listContributions().

Dynamic point availability

A module can subscribe before another independently loaded module registers the point. Core invokes onAvailable for every active generation and pairs it with at most one onUnavailable when that generation closes:

const unsubscribe = registry.observePoint(menuPoint, {
	onAvailable(): void {
		const registration = registry.registerContribution(menuPoint, contributionInput);
		void registration.whenActive();
	},
	onUnavailable(): void {
		// Drop generation-local state; point close owns removal of its catalog.
	},
});

// Detachment does not synthesize cleanup. Dispose module-owned handles first.
unsubscribe();

Observation matches the exact canonical point reference, not only its pointId. See the workspace dynamic-plugin example for explicit handle cleanup across provider unload and reload.

Ownership and cleanup

  • An owner scope owns its child scopes and registered point generations.
  • A registration owns its activation resource; dispose() is idempotent and waits for its captured cleanup outcome.
  • pointOwner.close() removes the exact point generation and exposes separate closed and cleanup outcomes.
  • registry.dispose() traverses the ownership tree in deterministic reverse order.
  • Registry events and snapshots expose committed scalar state. Contribution data, implementation, callbacks, and controllers are not copied into snapshots.

The Core registry is host-owned. Framework adapters may observe or project it, but they must not silently dispose it.

License

ISC © 2026 PrimaFuture.cz s.r.o.