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

@resourcexjs/registry

v1.1.0

Published

ResourceX Registry - Resource storage and retrieval

Readme

@resourcexjs/registry

Resource registry for ResourceX - storage and retrieval of resources.

Installation

bun add @resourcexjs/registry

Overview

The @resourcexjs/registry package provides a Maven-style registry for storing and resolving resources locally.

Key Concepts

  • Registry: Interface for resource storage and retrieval
  • ARPRegistry: Implementation using ARP (Agent Resource Protocol) for I/O
  • Local-first: Resources cached locally at ~/.resourcex
  • Maven-style: Organized by domain/path/name.type@version

Usage

Create Registry

import { createRegistry } from "@resourcexjs/registry";

// Default configuration (~/.resourcex)
const registry = createRegistry();

// Custom path
const registry = createRegistry({
  path: "./my-registry",
});

// With extension types
import { promptType } from "@my-org/types";

const registry = createRegistry({
  types: [promptType],
});

Link Resource

Link a resource to local registry for development or caching:

import { loadResource } from "@resourcexjs/loader";
import { createRegistry } from "@resourcexjs/registry";

// Load resource from folder
const rxr = await loadResource("./my-prompt");

// Link to registry
const registry = createRegistry();
await registry.link(rxr);

// Now available at: ~/.resourcex/localhost/[email protected]/

Resolve Resource

Retrieve a resource by its locator:

const registry = createRegistry();

// Resolve by full locator
const rxr = await registry.resolve("localhost/[email protected]");

console.log(rxr.manifest.name); // "my-prompt"
console.log(await rxr.content.text()); // Content

Check Existence

const registry = createRegistry();

if (await registry.exists("localhost/[email protected]")) {
  console.log("Resource exists");
}

Delete Resource

const registry = createRegistry();

await registry.delete("localhost/[email protected]");

API Reference

createRegistry(config?)

Create a new registry instance.

Parameters:

  • config?: RegistryConfig
    • path?: string - Storage path (default: ~/.resourcex)
    • types?: ResourceType[] - Extension types to register globally

Returns: Registry

const registry = createRegistry({
  path: "./custom-registry",
  types: [promptType, toolType],
});

Registry Interface

link(resource: RXR): Promise<void>

Link a resource to local registry.

Parameters:

  • resource: RXR - Complete resource object
await registry.link(rxr);

resolve(locator: string): Promise<RXR>

Resolve a resource by locator.

Parameters:

  • locator: string - Full resource locator

Returns: Promise<RXR>

Throws: RegistryError if resource not found

const rxr = await registry.resolve("localhost/[email protected]");

exists(locator: string): Promise<boolean>

Check if resource exists in registry.

Parameters:

  • locator: string - Full resource locator

Returns: Promise<boolean>

if (await registry.exists("localhost/[email protected]")) {
  // Resource exists
}

delete(locator: string): Promise<void>

Delete resource from local registry.

Parameters:

  • locator: string - Full resource locator
await registry.delete("localhost/[email protected]");

publish(resource: RXR): Promise<void>

Publish resource to remote registry (TODO: not yet implemented).

search(query: string): Promise<RXL[]>

Search for resources (TODO: not yet implemented).

Storage Structure

Resources are stored in Maven-style structure:

~/.resourcex/
└── {domain}/
    └── {path}/
        └── {name}.{type}@{version}/
            ├── manifest.json    # RXM metadata
            └── content          # Serialized content

Example

For resource deepractice.ai/prompts/[email protected]:

~/.resourcex/
└── deepractice.ai/
    └── prompts/
        └── [email protected]/
            ├── manifest.json
            └── content

manifest.json:

{
  "domain": "deepractice.ai",
  "path": "prompts",
  "name": "assistant",
  "type": "prompt",
  "version": "1.0.0"
}

content: (serialized by type's serializer)

Extension Types

Register extension types globally when creating registry:

import { createRegistry } from "@resourcexjs/registry";
import type { ResourceType } from "@resourcexjs/type";

const promptType: ResourceType<string> = {
  name: "prompt",
  description: "AI Prompt template",
  serializer: {
    async serialize(rxr) {
      const text = await rxr.content.text();
      return Buffer.from(text, "utf-8");
    },
    async deserialize(data, manifest) {
      // ... implementation
    },
  },
  resolver: {
    async resolve(rxr) {
      return rxr.content.text();
    },
  },
};

// Register when creating registry
const registry = createRegistry({
  types: [promptType],
});

// Now can link/resolve prompt resources

Error Handling

import { RegistryError } from "@resourcexjs/registry";

try {
  const rxr = await registry.resolve("localhost/[email protected]");
} catch (error) {
  if (error instanceof RegistryError) {
    console.error("Registry error:", error.message);
    // "Resource not found: localhost/[email protected]"
  }
}

Common Errors

Resource not found:

RegistryError: Resource not found: localhost/[email protected]

Unsupported type:

RegistryError: Unsupported resource type 'unknown'

Examples

Complete Workflow

import { loadResource } from "@resourcexjs/loader";
import { createRegistry } from "@resourcexjs/registry";

// 1. Load resource from folder
const rxr = await loadResource("./my-prompts/assistant");

// 2. Create registry
const registry = createRegistry();

// 3. Link to local registry
await registry.link(rxr);

// 4. Resolve later
const resolved = await registry.resolve("localhost/[email protected]");

// 5. Use content
const text = await resolved.content.text();
console.log(text);

Versioning

const registry = createRegistry();

// Link multiple versions
await registry.link(promptV1); // v1.0.0
await registry.link(promptV2); // v2.0.0
await registry.link(promptV3); // v3.0.0

// Resolve specific version
const v1 = await registry.resolve("localhost/[email protected]");
const v2 = await registry.resolve("localhost/[email protected]");
const latest = await registry.resolve("localhost/[email protected]");

Custom Storage Path

// Project-local registry
const registry = createRegistry({
  path: "./project-registry",
});

await registry.link(rxr);
// Stored at: ./project-registry/localhost/...

With Custom Types

import { promptType, toolType, agentType } from "@my-org/ai-types";

const registry = createRegistry({
  types: [promptType, toolType, agentType],
});

// Now can handle these custom types
await registry.link(promptResource);
await registry.link(toolResource);
await registry.link(agentResource);

Resolution Strategy

  1. Check local registry (~/.resourcex or custom path)
  2. If not found: (TODO) Fetch from remote registry based on domain
  3. Cache locally after fetching
  4. Return resource

Currently only local resolution is implemented. Remote fetching is planned.

Architecture

┌─────────────────────────────────────┐
│          Registry Interface         │
└──────────────┬──────────────────────┘
               │
        ┌──────▼──────┐
        │ARPRegistry  │
        │(implements) │
        └──────┬──────┘
               │
     ┌─────────┴─────────┐
     │                   │
┌────▼────┐      ┌──────▼──────┐
│   ARP   │      │TypeHandler  │
│(I/O)    │      │Chain        │
└─────────┘      └─────────────┘

Type Safety

All operations are fully typed:

import type { RXR, Registry } from "@resourcexjs/registry";

const registry: Registry = createRegistry();
const rxr: RXR = await registry.resolve("localhost/[email protected]");

License

MIT