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

@86d-app/registry

v0.0.40

Published

Module registry for 86d — resolve, fetch, and cache modules from local, GitHub, or npm sources

Downloads

169

Readme

[!WARNING] This project is under active development and is not ready for production use.

@86d-app/registry

Git-based module registry for the 86d commerce platform. Enables modules to be sourced from local workspace directories, GitHub repositories, or npm packages.

Overview

The registry provides the module resolution layer for 86d stores. When a store's config.json lists modules, the registry determines where each module lives and how to fetch it.

Key features:

  • Resolve modules and templates from local workspace, GitHub repos, or npm
  • Generate and consume registry.json manifests with integrity verification
  • Support "*" wildcard for including all available modules
  • Lock file (registry.lock.json) for reproducible builds with --frozen CI support
  • Circular dependency detection — throws on cycles with descriptive error messages
  • Template resolution — fetch store templates from GitHub or npm
  • Graceful handling of missing modules/templates with warnings
  • Retry with exponential backoff for transient network failures

Usage

Module Specifiers

Modules can be referenced in config.json using several formats:

{
  "modules": "*"
}

Or with explicit module references:

{
  "modules": [
    "products",
    "@86d-app/cart",
    "github:owner/repo/modules/custom-module",
    "github:owner/repo/modules/loyalty#v2.0",
    "npm:@acme/commerce-module",
    "npm:@acme/commerce-module@^1.0.0"
  ]
}

| Format | Source | Description | |---|---|---| | products | local/registry | Official module by short name | | @86d-app/products | local/registry | Official module by full package name | | github:owner/repo/path | GitHub | Module from a GitHub repository subpath | | github:owner/repo/path#ref | GitHub | GitHub module at a specific branch/tag | | npm:@scope/package | npm | Module from npm registry | | npm:@scope/package@version | npm | npm module with version constraint |

Resolving Modules

import { resolveModules, readStoreConfig } from "@86d-app/registry";

const config = readStoreConfig("templates/brisa/config.json");
const resolved = await resolveModules(config, {
  root: "/path/to/project",
});

for (const mod of resolved) {
  console.log(mod.specifier.name, mod.status, mod.localPath);
}

Building the Registry Manifest

import { buildManifest } from "@86d-app/registry";

const manifest = buildManifest("/path/to/project", {
  baseUrl: "https://github.com/86d-app/86d",
  defaultRef: "main",
});
// manifest.modules contains all discovered modules with metadata

Fetching Remote Modules

import { fetchModule, parseSpecifier } from "@86d-app/registry";

const spec = parseSpecifier("github:owner/repo/modules/loyalty");
const result = await fetchModule(spec, "/path/to/project");

if (result.success) {
  console.log(`Installed to: ${result.localPath}`);
}

CLI Integration

The registry integrates with the 86d CLI:

# Add a module from the registry (auto-installs required dependencies)
86d module add products

# Add from GitHub
86d module add github:owner/repo/modules/loyalty

# Add from npm
86d module add npm:@acme/commerce-module

# Check for module updates (compares local vs registry versions/integrity)
86d module update
86d module update cart

# Search the registry
86d module search shipping

# Generate registry manifest
86d generate registry

When adding a module, the CLI automatically resolves and installs any required dependencies (declared via the requires field in the registry manifest).

Config Format

The store's config.json supports these registry-related fields:

| Field | Type | Default | Description | |---|---|---|---| | modules | "*" \| string[] | "*" | Module specifiers or "*" for all | | template | string | — | Template specifier (local name, GitHub, or npm) | | registry | string | GitHub raw URL | Custom registry manifest URL | | moduleOptions | Record<string, object> | {} | Per-module configuration |

Resolving Templates

import { resolveTemplate, fetchTemplate } from "@86d-app/registry";

// Resolve from local, registry, GitHub, or npm
const result = resolveTemplate("brisa", "/path/to/project", manifest);

if (result.status === "missing") {
  const fetched = await fetchTemplate(result.specifier, "/path/to/project", manifest);
}

Template specifiers use the same formats as modules:

  • "brisa" — local template in templates/
  • "github:owner/repo/templates/custom" — from GitHub
  • "npm:@acme/store-template" — from npm

Registry Manifest

The registry.json file at the repo root indexes all available modules and templates:

{
  "version": 1,
  "baseUrl": "https://github.com/86d-app/86d",
  "defaultRef": "main",
  "modules": {
    "products": {
      "name": "@86d-app/products",
      "description": "Product catalog management",
      "version": "0.0.4",
      "category": "catalog",
      "path": "modules/products",
      "requires": [],
      "hasStoreComponents": true,
      "hasAdminComponents": true,
      "hasStorePages": true,
      "integrity": "sha256-..."
    }
  },
  "templates": {
    "brisa": {
      "name": "brisa",
      "description": "86d Starter Kit",
      "version": "0.0.1",
      "path": "templates/brisa"
    }
  }
}

Generate it with:

bun run generate:registry

API Reference

parseSpecifier(raw: string): ModuleSpecifier

Parse a module specifier string into a structured object with source type, name, and metadata.

resolveModules(config, options): Promise<ResolvedModule[]>

Resolve a store config's module list into concrete entries with status (found, missing, error).

fetchModule(spec, root, manifest?): Promise<FetchResult>

Download a module from its remote source (GitHub tarball or npm) and install it locally.

buildManifest(root, options?): RegistryManifest

Scan the modules/ directory and build a registry manifest with full metadata for each module.

readStoreConfig(path): StoreConfig

Read and parse a store's config.json file.

getModuleDependencies(name, manifest): string[]

Get the full transitive dependency list for a module, topologically sorted (dependencies before dependents). Throws if a circular dependency is detected.

detectCircularDependencies(manifest): string[]

Scan all modules in a manifest for circular dependencies. Returns an array of cycle descriptions (e.g., "a → b → c → a"). Returns empty array if no cycles exist.

generateLockfile(resolved, root): Lockfile

Generate a lock file from resolved modules, capturing source, version, integrity hash, and location.

writeLockfile(root, lockfile): void

Write the lock file to registry.lock.json at the project root.

readLockfile(root): Lockfile | undefined

Read the lock file from the project root. Returns undefined if not found or invalid.

verifyLockfile(lockfile, resolved): LockfileDiff

Compare a lock file against current resolved modules. Returns { added, removed, changed }.

isLockfileSatisfied(diff): boolean

Returns true if the diff has no added, removed, or changed modules.

getLocalModuleNames(root): string[]

Get sorted list of all locally available module names.

resolveTemplate(spec, root, manifest?): ResolvedTemplate

Resolve a template specifier to a local directory, checking local templates first then registry.

fetchTemplate(spec, root, manifest?): Promise<FetchResult>

Download a template from GitHub or npm and install it into templates/.

getLocalTemplateNames(root): string[]

Get sorted list of all locally available template names.

readTemplateConfig(path): Record<string, unknown> | undefined

Read a template's config.json contents.

computeIntegrity(modulePath): string | undefined

Compute SHA-256 integrity hash for a module's package.json.

Buildtime Integration

The registry is used at buildtime by scripts/generate-modules.ts:

  1. Reads config.json and resolves all module specifiers
  2. For missing modules (registry/GitHub/npm), fetches them automatically
  3. Generates the store's import files in apps/store/generated/

This means bun run generate:modules will pull any missing modules before generating code. Modules that fail to fetch are skipped with warnings.

Lock File

The registry.lock.json file captures the exact resolved state of all modules for reproducible builds. It is generated automatically by bun run generate:modules.

{
  "lockfileVersion": 1,
  "generatedAt": "2026-03-12T18:00:00.000Z",
  "modules": {
    "products": {
      "source": "local",
      "packageName": "@86d-app/products",
      "version": "0.0.4",
      "integrity": "sha256-...",
      "localPath": "modules/products"
    }
  }
}

Frozen Installs (CI)

Use --frozen to fail if the lock file is outdated:

bun run generate:modules -- --frozen

This ensures CI builds use the exact same module resolution as the developer who last generated the lock file.

Circular Dependency Detection

The registry detects circular dependencies in the module dependency graph and throws descriptive errors:

Circular dependency detected: cart → checkout → orders → cart

This runs automatically during generate:modules and will fail the build if cycles are found.

Notes

  • When modules is "*" or omitted, all local workspace modules are included
  • GitHub fetching uses the tarball API; tar must be available on the system
  • Set GITHUB_TOKEN environment variable for private repos or to avoid rate limits
  • npm modules are installed to node_modules/ via bun add (falls back to npm install)
  • The resolver always checks local workspace first before attempting remote sources