Reference

API Reference

Complete API reference for URPC packages including @unilab/urpc-core, @unilab/urpc-hono, @unilab/urpc, @unilab/urpc-next, @unilab/urpc, and @unilab/uniweb3.

@unilab/urpc-core

Core types and interfaces for the URPC framework.

Repository Operations Arguments

FindManyArgs

Arguments for finding multiple records with advanced query operators.

interface FindManyArgs<T extends Record<string, any>> {
  limit?: number;
  offset?: number;
  where?: WhereConditionWithOperators<T>;
  order_by?: Partial<Record<keyof T, "asc" | "desc">>;
  include?: {
    [key: string]: RelationCallbackMany<T, any>;
  };
}

type WhereCondition<T> = {
  [K in keyof T]?: T[K];
};

type WhereConditionWithOperators<T> = {
  [K in keyof T]?: T[K] | QueryOperators<T[K]>;
};

 type QueryOperators<T> = {
  $gt?: T;
  $gte?: T;
  $lt?: T;
  $lte?: T;
  $eq?: T;
  $ne?: T;
  $in?: T[];
  $nin?: T[];
};

export type RelationCallbackMany<
  T extends Record<string, any>,
  R extends Record<string, any>
> = (entities: T[]) => Promise<R[]>;

Properties:

  • limit - Maximum number of records to return
  • offset - Number of records to skip
  • where - Filter conditions with query operators support
  • order_by - Sort order specification
  • include - Include related entities using callback functions

Query Operators:

  • $gt - Greater than
  • $gte - Greater than or equal
  • $lt - Less than
  • $lte - Less than or equal
  • $eq - Equal to
  • $ne - Not equal to
  • $in - Value in array
  • $nin - Value not in array

FindOneArgs

Arguments for finding a single record.

interface FindOneArgs<T extends Record<string, any>> {
  where: WhereCondition<T>;
  include?: {
    [key: string]: RelationCallbackSingle<T, any>;
  };
}

export type RelationCallbackSingle<T extends Record<string, any>, R extends Record<string, any>> = (
  entity: T
) => Promise<R | null>;

Properties:

  • where - Filter conditions (required)
  • include - Include related entities using callback functions

CreationArgs

Arguments for creating a new record.

interface CreationArgs<T extends Record<string, any>> {
  data: Partial<T>;
}

Properties:

  • data - Data for the new record

UpdateArgs

Arguments for updating an existing record.

interface UpdateArgs<T extends Record<string, any>> {
  where: WhereCondition<T>;
  data: Partial<T>;
}

Properties:

  • where - Filter conditions to identify records to update
  • data - New data for the record

DeletionArgs

Arguments for deleting records.

interface DeletionArgs<T extends Record<string, any>> {
  where: WhereCondition<T>;
}

Properties:

  • where - Filter conditions to identify records to delete

DataSourceAdapter

Interface that all data source adapters must implement.

interface DataSourceAdapter<T extends Record<string, any>> {
  findMany(args?: FindManyArgs<T>): Promise<T[]>;
  findOne(args: FindOneArgs<T>): Promise<T | null>;
  create(args: CreationArgs<T>): Promise<T>;
  update(args: UpdateArgs<T>): Promise<T>;
  delete(args: DeletionArgs<T>): Promise<boolean>;
}

Repository

Repository class for interacting with data sources, includes built-in middleware support.

class Repository<T extends Record<string, any>> {
  constructor(adapter: DataSourceAdapter<T>);
  
  async findMany(args?: FindManyArgs<T>): Promise<T[]>;
  async findOne(args: FindOneArgs<T>): Promise<T | null>;
  async create(args: CreationArgs<T>): Promise<T>;
  async update(args: UpdateArgs<T>): Promise<T>;
  async delete(args: DeletionArgs<T>): Promise<boolean>;
}

Middleware System

Middleware Types

type Middleware<T extends Record<string, any>> = (
  context: MiddlewareContext<T>,
  next: MiddlewareNext<T>
) => Promise<any>;

type MiddlewareContext<T extends Record<string, any>> = {
  operation: "findMany" | "findOne" | "create" | "update" | "delete";
  args: any;
  result?: any;
  metadata?: MiddlewareMetadata;
};

interface MiddlewareMetadata {
  entity: string;
  source?: string;
  context?: {
    lang?: string;
  };
}

type MiddlewareOptions = {
  position?: "before" | "after" | "around";
  priority?: number;
  name?: string;
  required?: {
    entities: string[];
  };
};

Entity Schema System

Decorators

Entity configuration using decorators for type-safe schema generation.

// Field decorators
const Fields = {
  string: (options?: { optional?: boolean; description?: string }) => PropertyDecorator;
  number: (options?: { optional?: boolean; description?: string }) => PropertyDecorator;
  boolean: (options?: { optional?: boolean; description?: string }) => PropertyDecorator;
  date: (options?: { optional?: boolean; description?: string }) => PropertyDecorator;
  array: (target: () => any, options?: { optional?: boolean; description?: string }) => PropertyDecorator;
  record: (target: () => any, options?: { optional?: boolean; description?: string }) => PropertyDecorator;
};

// Relation decorators
const Relations = {
  toOne: (target: () => any, options?: { optional?: boolean }) => PropertyDecorator;
  toMany: (target: () => any, options?: { optional?: boolean }) => PropertyDecorator;
};

Schema Generation

function generateSchema(entityClass: any): SchemaObject;
function generateSchemas(entityClasses: any[]): Record<string, SchemaObject>;

Plugin System

Plugin Interface

interface Plugin {
  entities?: Record<string, any>[];
  adapters?: AdapterRegistration[];
}

interface AdapterRegistration {
  source: string;
  entity: string;
  adapter: DataSourceAdapter<any>;
}

@unilab/urpc-hono

Server-side components for creating URPC API servers using Hono framework.

URPC

Main class for creating and configuring URPC servers with plugin support.

Static Methods

init

Initialize the URPC server with configuration including plugins and middleware.

static init(config: URPCConfig): Hono

Parameters:

  • config.app - Optional external Hono app instance
  • config.plugins - Array of plugins to register
  • config.middleware - Array of global middleware to apply

Returns: Hono app instance with all routes configured

Example:

import { URPC } from "@unilab/urpc-hono";
import { WalletPlugin } from "@unilab/uniweb3";
import { LoggingMiddleware } from "@unilab/urpc-core/middleware";

const app = URPC.init({
  plugins: [WalletPlugin],
  middlewares: [LoggingMiddleware]
});

repo

Get or create a repository for a specific data source.

static repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

getApp

Get the current Hono app instance.

static getApp(): Hono

getEntitySchemas

Get all registered entity schemas.

static getEntitySchemas(): Record<string, SchemaObject>

getEntitySources

Get mapping of entities to their available data sources.

static getEntitySources(): Record<string, string[]>

Configuration Interfaces

URPCConfig

Configuration options for initializing URPC server.

interface URPCConfig {
  app?: Hono;
  plugins?: Plugin[];
  middlewares?: Middleware<any>[];
}

Properties:

  • app - Optional external Hono app instance
  • plugins - Array of plugins containing entities and adapters
  • middlewares - Array of global middleware to apply

Automatic Route Generation

The URPC server automatically generates REST API endpoints based on registered plugins:

  • GET /{entity}/list - Find multiple records
  • GET /{entity}/find_one - Find single record
  • POST /{entity}/create - Create new record
  • PATCH /{entity}/update - Update existing record
  • DELETE /{entity}/delete - Delete records

All routes require a source query parameter to specify the data source.

@unilab/urpc

HTTP client library for consuming URPC APIs with relation support.

URPC Client

Main client class for interacting with URPC APIs with automatic relation loading.

Constructor

constructor(config: ClientConfig)

Parameters:

  • config - Client configuration options

Instance Methods

createRepositoryProxy

Create a repository proxy for a specific entity and data source.

createRepositoryProxy<T extends Record<string, any>>(
  entity: string,
  source: string
): Repository<T>

Parameters:

  • entity - Name of the entity
  • source - Data source identifier

Returns: Repository instance with client-side relation loading support

Static Methods

init

Initialize the global client instance.

static init(config: ClientConfig): void

Parameters:

  • config - Client configuration options

Example:

import { URPC } from "@unilab/urpc";

URPC.init({
  baseUrl: "http://localhost:3000",
  timeout: 10000,
  headers: {
    Authorization: "Bearer token",
  },
});

repo

Create a repository instance using the global client.

interface RepoOptions {
  entity: string;
  source: string;
}

static repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

Example:

import { URPC } from "@unilab/urpc";
import { WalletEntity } from "@unilab/uniweb3/entities";

const walletRepo = URPC.repo<WalletEntity>({
  entity: "wallet",
  source: "evm",
});

joinRepo

Create a repository with relation mapping support.

type JoinRepoOptions<
  F extends Record<string, any> = Record<string, any>,
  L extends Record<string, any> = Record<string, any>
> = RepoOptions & RelationMapping<F, L>

static joinRepo<F extends Record<string, any>, L extends Record<string, any>>(
  options: JoinRepoOptions<F, L>
): Repository<F>

Configuration Interfaces

ClientConfig

Configuration options for the URPC client.

interface ClientConfig {
  baseUrl: string;
  timeout?: number;
  headers?: Record<string, string>;
}

Properties:

  • baseUrl - Base URL of the URPC server (required)
  • timeout - Request timeout in milliseconds (default: 5000)
  • headers - Default headers to include with requests

RelationMapping

Interface for defining entity relationships.

interface RelationMapping<
  T extends Record<string, any>,
  F extends Record<string, any>
> {
  localField: keyof F;
  foreignField: keyof T;
}

HttpRequestOptions

Internal interface for HTTP request configuration.

interface HttpRequestOptions {
  method: "GET" | "POST" | "PATCH" | "DELETE";
  url: string;
  params?: Record<string, any>;
  data?: any;
  headers?: Record<string, string>;
}

ApiResponse

Interface for API response structure.

interface ApiResponse<T = any> {
  data: T;
  success: boolean;
  message?: string;
}

Utility Functions

repo

Global convenience function for creating repository instances.

function repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

joinRepo

Global convenience function for creating repository instances with relation mapping.

function joinRepo<
  F extends Record<string, any> = Record<string, any>,
  L extends Record<string, any> = Record<string, any>
>(
  options: JoinRepoOptions<F, L>
): Repository<F>

Example:

import { repo, URPC } from "@unilab/urpc";
import { WalletEntity } from "@unilab/uniweb3/entities";

// Initialize client first
URPC.init({ baseUrl: "http://localhost:3000" });

// Use the convenience function
const walletRepo = repo<WalletEntity>({
  entity: "wallet",
  source: "solana",
});
const wallet = await walletRepo.findOne({
  where: { address: "11111111111111111111111111111112" }
});

Client-Side Relations

The client automatically handles relation loading by executing callback functions on the client side after fetching the main entity data. This allows for flexible relation definitions without server-side configuration.

@unilab/urpc-next

Next.js integration for URPC with support for both App Router and Pages Router.

URPC

App Router integration (Next.js 13+).

Static Methods

init

Initialize the URPC API handlers for App Router.

static init(config: URPCConfig): URPCAPI

Parameters:

  • config.plugins - Array of plugins to register
  • config.middleware - Array of global middleware to apply

Returns: API handlers object with GET, POST, PATCH, DELETE methods

Example:

// app/api/[...urpc]/route.ts
import { URPC } from "@unilab/urpc-next";
import { WalletPlugin } from "@unilab/uniweb3";

const api = URPC.init({
  plugins: [WalletPlugin]
});

export const { GET, POST, PATCH, DELETE } = api;

repo

Get or create a repository for a specific data source.

static repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

URPC

Pages Router integration (Next.js 12+).

Static Methods

init

Initialize the URPC API handler for Pages Router.

static init(config: URPCConfig): (req: NextApiRequest, res: NextApiResponse) => Promise<void>

Example:

// pages/api/[...urpc].ts
import { URPC } from "@unilab/urpc-next";
import { WalletPlugin } from "@unilab/uniweb3";

export default URPC.init({
  plugins: [WalletPlugin]
});

Configuration Interfaces

URPC API

Interface for App Router API handlers.

interface URPCAPI {
  GET: RouteHandler;
  POST: RouteHandler;
  PATCH: RouteHandler;
  DELETE: RouteHandler;
}

URPCConfig

Configuration options for Next.js integration.

interface URPCConfig {
  plugins?: Plugin[];
  middlewares?: Middleware<any>[];
}

@unilab/urpc

Lightweight browser-only client library for URPC without HTTP functionality.

URPC

Browser-optimized client for local data sources.

Static Methods

repo

Create a repository instance for browser environments.

static repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

joinRepo

Create a repository with relation mapping for browser environments.

static joinRepo<F extends Record<string, any>, L extends Record<string, any>>(
  options: JoinRepoOptions<F, L>
): Repository<F>

Utility Functions

repo

Global convenience function for browser repository creation.

function repo<T extends Record<string, any>>(
  options: RepoOptions
): Repository<T>

joinRepo

Global convenience function for browser repository with relations.

function joinRepo<F extends Record<string, any>, L extends Record<string, any>>(
  options: JoinRepoOptions<F, L>
): Repository<F>

@unilab/uniweb3

Unified blockchain data adapters and entities for Web3 integration.

Entities

WalletEntity

Entity for blockchain wallet data.

import { Fields } from "@unilab/urpc-core";

class TokenEntity {
  @Fields.string()
  symbol = "";

  @Fields.number()
  decimals = 0;
}

export class WalletEntity {
  @Fields.string()
  address = "";

  @Fields.string()
  balance = "";

  @Fields.string()
  network = "";

  @Fields.record(() => TokenEntity, {
    optional: true,
  })
  token?: TokenEntity = new TokenEntity();
}

Adapters

EVMAdapter

Ethereum Virtual Machine adapter for EVM-compatible chains.

class EVMAdapter extends BaseAdapter<WalletEntity> {
  // Implements all DataSourceAdapter methods for EVM chains
}

SolanaAdapter

Solana blockchain adapter.

class SolanaAdapter extends BaseAdapter<WalletEntity> {
  // Implements all DataSourceAdapter methods for Solana
}

Plugins

WalletPlugin

Complete plugin configuration for wallet functionality.

const WalletPlugin: Plugin = {
  entities: [WalletEntity],
  adapters: [
    { source: "evm", entity: "wallet", adapter: new EVMAdapter() },
    { source: "solana", entity: "wallet", adapter: new SolanaAdapter() }
  ]
};

API Routes

The URPC server automatically generates the following REST API endpoints when adapters are registered:

GET /{entity}/list

Find multiple records with advanced filtering.

Query Parameters:

  • source (required) - Data source identifier
  • limit - Maximum number of records to return
  • offset - Number of records to skip
  • where - JSON filter conditions with query operators
  • order_by - JSON sort specification

Example:

GET /wallet/list?source=evm&limit=10&where={"balance":{"$gt":"1000000000000000000"}}

GET /{entity}/find_one

Find a single record.

Query Parameters:

  • source (required) - Data source identifier
  • where (required) - JSON filter conditions

Example:

GET /wallet/find_one?source=solana&where={"address":"11111111111111111111111111111112"}

POST /{entity}/create

Create a new record.

Query Parameters:

  • source (required) - Data source identifier

Request Body:

{
  "data": {
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
    "balance": "5000000000",
    "network": "bitcoin"
  }
}

PATCH /{entity}/update

Update an existing record.

Query Parameters:

  • source (required) - Data source identifier

Request Body:

{
  "where": {
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
  },
  "data": {
    "balance": "6000000000"
  }
}

DELETE /{entity}/delete

Delete records.

Query Parameters:

  • source (required) - Data source identifier
  • where (required) - JSON filter conditions

Example:

DELETE /wallet/delete?source=evm&where={"balance":"0"}

Usage Examples

Hono Server Setup

import { URPC } from "@unilab/urpc-hono";
import { WalletPlugin } from "@unilab/uniweb3";
import { LoggingMiddleware } from "@unilab/urpc-core/middleware";

const app = URPC.init({
  plugins: [WalletPlugin],
  middlewares: [LoggingMiddleware]
});

export default {
  port: 3000,
  fetch: app.fetch,
};

Next.js App Router Setup

// app/api/[...urpc]/route.ts
import { URPC } from "@unilab/urpc-next";
import { WalletPlugin } from "@unilab/uniweb3";

const api = URPC.init({
  plugins: [WalletPlugin]
});

export const { GET, POST, PATCH, DELETE } = api;

Client Usage with Relations

import { URPC, repo } from "@unilab/urpc";
import { WalletEntity } from "@unilab/uniweb3/entities";

// Initialize client
URPC.init({
  baseUrl: "http://localhost:3000",
  timeout: 10000,
});

// Query with relations
const wallets = await repo<WalletEntity>({
  entity: "wallet",
  source: "solana",
}).findMany({
  where: { 
    balance: { $gt: "1000000000000000000" } 
  },
  include: {
    transactions: async (wallets) => {
      // Load related transactions
      return await repo("transaction", "solana").findMany({
        where: { wallet_address: { $in: wallets.map(w => w.address) } }
      });
    }
  }
});

Custom Entity and Adapter

import { Fields, Relations, DataSourceAdapter } from "@unilab/urpc-core";

// Define entity with decorators
class UserEntity {
  @Fields.string()
  id = "";

  @Fields.string()
  name = "";

  @Fields.string({ optional: true })
  email = "";

  @Relations.toMany(() => PostEntity)
  posts?: PostEntity[];
}

// Implement custom adapter
class DatabaseAdapter extends BaseAdapter<UserEntity> {
  async findMany(args?: FindManyArgs<UserEntity>): Promise<UserEntity[]> {
    // Database query implementation
    return [];
  }

  async findOne(args: FindOneArgs<UserEntity>): Promise<UserEntity | null> {
    // Database query implementation
    return null;
  }
}

// Create plugin
const UserPlugin: Plugin = {
  entities: [UserEntity],
  adapters: [
    { source: "database", entity: "user", adapter: new DatabaseAdapter() }
  ]
};

Browser-Only Usage

import { repo } from "@unilab/urpc";
import { LocalStorageAdapter } from "./local-storage-adapter";

// Browser-only repository without HTTP
const localRepo = repo("todos", new LocalStorageAdapter());

const todos = await localRepo.findMany({
  where: { completed: false },
  order_by: { created_at: "desc" }
});

Middleware Usage

import { useGlobalMiddleware } from "@unilab/urpc-core";

// Add logging middleware
useGlobalMiddleware(async (context, next) => {
  console.log(`${context.operation} started:`, context.args);
  const result = await next();
  console.log(`${context.operation} completed:`, result);
  return result;
}, {
  name: "logger",
  position: "around",
  priority: 1
});

// Add caching middleware
useGlobalMiddleware(async (context, next) => {
  if (context.operation === "findMany") {
    const cacheKey = JSON.stringify(context.args);
    const cached = cache.get(cacheKey);
    if (cached) return cached;
    
    const result = await next();
    cache.set(cacheKey, result);
    return result;
  }
  return next();
}, {
  name: "cache",
  position: "around",
  priority: 2
});

Error Handling

All endpoints return consistent error responses:

{
  "error": "Error message describing what went wrong"
}

Common HTTP status codes:

  • 400 - Bad Request (missing required parameters, invalid JSON)
  • 404 - Not Found (unknown entity or source)
  • 500 - Internal Server Error (adapter errors, database errors)