Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

@resourcexjs/server

ResourceX Registry Server - HTTP API server for hosting and serving ResourceX resources.

Installation

bun add @resourcexjs/server @resourcexjs/node-provider
# or
npm install @resourcexjs/server @resourcexjs/node-provider

Overview

This package provides three levels of abstraction for building a ResourceX registry server:

  1. Hono Server - Ready-to-use server with all endpoints configured
  2. Handlers - Framework-agnostic request handlers for custom integrations
  3. Protocol - Type definitions and constants for building clients

Quick Start

import { createRegistryServer } from "@resourcexjs/server";
import { FileSystemRXAStore, FileSystemRXMStore } from "@resourcexjs/node-provider";

const server = createRegistryServer({
  rxaStore: new FileSystemRXAStore("./data/blobs"),
  rxmStore: new FileSystemRXMStore("./data/manifests"),
});

// Bun
Bun.serve({ fetch: server.fetch, port: 3000 });

// Node.js (with @hono/node-server)
import { serve } from "@hono/node-server";
serve({ fetch: server.fetch, port: 3000 });

API

createRegistryServer(config)

Creates a Hono app with all registry endpoints configured.

import { createRegistryServer } from "@resourcexjs/server";
import { FileSystemRXAStore, FileSystemRXMStore } from "@resourcexjs/node-provider";

const server = createRegistryServer({
  rxaStore: new FileSystemRXAStore("./data/blobs"),
  rxmStore: new FileSystemRXMStore("./data/manifests"),
  basePath: "", // Optional: API route prefix (default: "")
  cors: true, // Optional: Enable CORS (default: true)
});

Config Interface

interface RegistryServerConfig {
  rxaStore: RXAStore; // Content-addressable blob storage
  rxmStore: RXMStore; // Manifest storage
  basePath?: string; // API route prefix (default: "")
  cors?: boolean; // Enable CORS (default: true)
}

Handlers

Framework-agnostic handlers for custom server integrations (Next.js, Express, etc.).

import {
  handlePublish,
  handleGetResource,
  handleHeadResource,
  handleDeleteResource,
  handleGetContent,
  handleSearch,
  CASRegistry,
} from "@resourcexjs/server";
import { FileSystemRXAStore, FileSystemRXMStore } from "@resourcexjs/node-provider";

const registry = new CASRegistry(
  new FileSystemRXAStore("./data/blobs"),
  new FileSystemRXMStore("./data/manifests")
);

// Next.js Route Handler example
export async function POST(request: Request) {
  return handlePublish(request, registry);
}

Handler Functions

Handler Description
handlePublish(request, registry) Process multipart form publish request
handleGetResource(locator, registry) Get resource manifest
handleHeadResource(locator, registry) Check resource existence
handleDeleteResource(locator, registry) Delete a resource
handleGetContent(locator, registry) Download resource archive
handleSearch(query, limit, offset, registry) Search resources

API Endpoints

All endpoints are prefixed with /api/v1.

GET /api/v1/health

Health check endpoint.

Response:

{ "status": "ok" }

POST /api/v1/publish

Publish a resource to the registry.

Content-Type: multipart/form-data

Fields:

  • locator (string) - Resource locator (e.g., hello:1.0.0)
  • manifest (file) - JSON manifest file
  • content (file) - Archive file (tar.gz)

Response (201):

{ "locator": "hello:1.0.0" }

GET /api/v1/resource/:locator

Get resource manifest.

Response (200):

{
  "name": "hello",
  "type": "text",
  "tag": "1.0.0",
  "path": "prompts"
}

HEAD /api/v1/resource/:locator

Check if resource exists.

Response: 200 if exists, 404 if not.

DELETE /api/v1/resource/:locator

Delete a resource.

Response: 204 on success.

GET /api/v1/content/:locator

Download resource archive.

Response: Binary application/gzip content.

GET /api/v1/search

Search for resources.

Query Parameters:

  • q (string, optional) - Search query
  • limit (number, default: 100) - Max results
  • offset (number, default: 0) - Pagination offset

Response (200):

{
  "results": [
    {
      "locator": "hello:1.0.0",
      "name": "hello",
      "type": "text",
      "tag": "1.0.0"
    }
  ],
  "total": 1
}

Protocol

Type definitions and constants for building clients.

import {
  API_VERSION, // "v1"
  API_PREFIX, // "/api/v1"
  ENDPOINTS, // { publish, resource, content, search, health }
  CONTENT_TYPES, // { json, binary, formData }
  ERROR_CODES, // Error code constants
  buildResourceUrl, // Build resource URL
  buildContentUrl, // Build content URL
  buildPublishUrl, // Build publish URL
  buildSearchUrl, // Build search URL with params
} from "@resourcexjs/server";

// Types
import type {
  ManifestData,
  SearchQuery,
  PublishResponse,
  GetResourceResponse,
  SearchResultItem,
  SearchResponse,
  ErrorResponse,
  ErrorCode,
} from "@resourcexjs/server";

URL Builders

import { buildResourceUrl, buildSearchUrl } from "@resourcexjs/server";

const url = buildResourceUrl("https://registry.example.com", "hello:1.0.0");
// "https://registry.example.com/api/v1/resource/hello%3A1.0.0"

const searchUrl = buildSearchUrl("https://registry.example.com", {
  q: "prompt",
  limit: 10,
});
// "https://registry.example.com/api/v1/search?q=prompt&limit=10"

Error Handling

All error responses follow a consistent format:

{
  "error": "Error message",
  "code": "ERROR_CODE"
}

Error Codes

Code Status Description
LOCATOR_REQUIRED 400 Missing locator field
MANIFEST_REQUIRED 400 Missing manifest file
CONTENT_REQUIRED 400 Missing content file
INVALID_MANIFEST 400 Invalid manifest format
INVALID_LOCATOR 400 Invalid locator format
RESOURCE_NOT_FOUND 404 Resource does not exist
INTERNAL_ERROR 500 Internal server error

Re-exports

For convenience, this package re-exports commonly used classes:

import { CASRegistry, FileSystemRXAStore, FileSystemRXMStore } from "@resourcexjs/server";

import type { RXAStore, RXMStore, Registry } from "@resourcexjs/server";

Storage Architecture

The server uses content-addressable storage (CAS) for efficient deduplication:

./data/
├── blobs/                        # Content-addressable blob storage
│   └── ab/
│       └── sha256:abcd1234...    # Archive data (tar.gz)
└── manifests/
    └── _local/                   # Resources stored on this server
        └── my-prompt/
            └── 1.0.0.json        # Manifest with digest reference

Note: The server stores resources without registry prefix. When a resource is published to registry.example.com/hello:1.0.0, it's stored as hello:1.0.0 on the server. The registry prefix is added by clients when they pull resources.

Related Packages

Package Description
resourcexjs Client SDK
@resourcexjs/core Core primitives and CASRegistry
@resourcexjs/node-provider Node.js/Bun storage providers

License

Apache-2.0