🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

@nestjs-rpc/client

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nestjs-rpc/client

latest
npmnpm
Version
2.1.7
Version published
Maintainers
1
Created
Source

@nestjs-rpc/client

Type-safe RPC client for calling NestJS methods from any frontend. Full TypeScript inference, zero configuration.

npm version npm downloads License: MIT TypeScript

InstallationQuick StartExamples

📖 📚 Full Documentation → 📖

Complete guides, API reference, and advanced examples

🎯 Why @nestjs-rpc/client?

Stop writing API client wrappers manually. This package gives you:

  • 🔒 End-to-End Type Safety - Import your server's manifest type for complete type inference
  • 🎯 Zero Boilerplate - No manual API wrappers or type definitions
  • 📤 Built-in File Uploads - Upload files with simple { file } or { files: [] } options
  • Proxy-Based API - Call methods like rpc.user.getUserById('123') - feels like local functions
  • 🎨 Framework Agnostic - Works with React, Vue, Angular, Svelte, or vanilla JS
  • 🔧 Fully Customizable - Built on Axios with full configuration support

The Traditional Way (Without NestRPC)

// ❌ Manual API client with no type safety
const response = await fetch('/api/user/getUserById', {
  method: 'POST',
  body: JSON.stringify({ id: '123' }),
});
const user = await response.json(); // 😱 No types!

The NestRPC Way

// ✅ Type-safe, feels like a local function
const { data: user } = await rpc.user.getUserById('123');
//    ^? { id: string; name: string; email: string }
// Full autocomplete and type checking! 🎉

📦 Installation

npm install @nestjs-rpc/client axios
# or
pnpm add @nestjs-rpc/client axios
# or
yarn add @nestjs-rpc/client axios

Peer Dependencies:

  • axios - Used as the default HTTP client (you can provide your own)

🚀 Quick Start

1. Import Your Server's Manifest Type

First, make sure your server exports the manifest type:

// server/src/nest-rpc.config.ts
export const manifest = defineManifest({ /* ... */ });
export type Manifest = typeof manifest; // 👈 Export this!

2. Create the Client

// client/src/rpc-client.ts
import { RpcClient } from '@nestjs-rpc/client';
import type { Manifest } from '../../server/src/nest-rpc.config';

export const rpcClient = new RpcClient<Manifest>({
  baseUrl: 'http://localhost:3000',
  apiPrefix: 'nestjs-rpc', // Optional, defaults to 'nestjs-rpc'
});

export const rpc = rpcClient.routers();

3. Use with Full Type Safety!

// Now you have full type safety and autocomplete!
const { data: user } = await rpc.user.getUserById('123');
//    ^? { id: string; name: string; email: string }

await rpc.user.createUser({ 
  name: 'Jane Doe', 
  email: 'jane@example.com' 
});

const { data: users } = await rpc.user.listUsers();
//    ^? Array<{ id: string; name: string; email: string }>

That's it! You get:

  • ✅ Full TypeScript autocomplete
  • ✅ Compile-time type checking
  • ✅ Runtime type safety
  • ✅ Zero boilerplate

📤 File Uploads

NestRPC client has built-in support for file uploads. No FormData handling needed!

Single File Upload

const fileInput = document.querySelector<HTMLInputElement>('input[type="file"]');

const { data } = await rpc.user.uploadAvatar(
  { userId: '123' },
  { file: fileInput.files[0] }
);

Multiple File Upload

const fileInput = document.querySelector<HTMLInputElement>('input[type="file"]');

const { data } = await rpc.files.uploadDocuments(
  { category: 'invoices' },
  { files: Array.from(fileInput.files) }
);

With React Example

function FileUpload() {
  const [file, setFile] = useState<File | null>(null);

  const handleUpload = async () => {
    if (!file) return;
    
    const { data } = await rpc.user.uploadAvatar(
      { userId: '123' },
      { file }
    );
    
    console.log('Uploaded:', data);
  };

  return (
    <div>
      <input 
        type="file" 
        onChange={(e) => setFile(e.target.files?.[0] || null)} 
      />
      <button onClick={handleUpload}>Upload</button>
    </div>
  );
}

🔧 Configuration

Basic Configuration

const rpcClient = new RpcClient<Manifest>({
  baseUrl: 'http://localhost:3000',
  apiPrefix: 'nestjs-rpc', // Optional
});

Advanced Configuration

import axios from 'axios';

// Create custom Axios instance
const axiosInstance = axios.create({
  timeout: 10000,
  headers: {
    'X-Custom-Header': 'value',
  },
});

const rpcClient = new RpcClient<Manifest>({
  baseUrl: 'http://localhost:3000',
  apiPrefix: 'nestjs-rpc',
  axiosInstance, // Use custom instance
  requestOptions: {
    // Default options for all requests
    headers: {
      Authorization: 'Bearer token',
    },
  },
});

Per-Call Options

Override options for individual calls:

// Add custom headers for this call
const { data } = await rpc.user.getUserById('123', {
  requestOptions: {
    headers: {
      Authorization: 'Bearer custom-token',
      'X-Custom-Header': 'value',
    },
  },
});

// Use different Axios instance for this call
const { data } = await rpc.user.getUserById('123', {
  axiosInstance: customAxiosInstance,
});

Dynamic Configuration

Update configuration at runtime:

// Update base URL
rpcClient.$setConfigProperty('baseUrl', 'https://api.production.com');

// Or update entire config
rpcClient.$setConfig({
  baseUrl: 'https://api.production.com',
  requestOptions: {
    headers: {
      Authorization: `Bearer ${newToken}`,
    },
  },
});

// Read current config
const config = rpcClient.$config;
console.log(config.baseUrl);

🎨 Framework Examples

React

import { useState, useEffect } from 'react';
import { rpc } from './rpc-client';

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    rpc.user.listUsers().then(({ data }) => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Vue 3

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { rpc } from './rpc-client';

const users = ref([]);

onMounted(async () => {
  const { data } = await rpc.user.listUsers();
  users.value = data;
});
</script>

Angular

import { Component, OnInit } from '@angular/core';
import { rpc } from './rpc-client';

@Component({
  selector: 'app-user-list',
  template: `
    <ul>
      <li *ngFor="let user of users">{{ user.name }}</li>
    </ul>
  `,
})
export class UserListComponent implements OnInit {
  users: any[] = [];

  async ngOnInit() {
    const { data } = await rpc.user.listUsers();
    this.users = data;
  }
}

Vanilla TypeScript

import { rpc } from './rpc-client';

async function loadUsers() {
  const { data: users } = await rpc.user.listUsers();
  console.log('Users:', users);
}

loadUsers();

🔒 Type Safety

The client automatically infers types from your server's manifest:

// Server method signature:
@Route()
async getUserById(id: string): Promise<User> {
  return { id, name: 'John', email: 'john@example.com' };
}

// Client automatically gets:
const { data } = await rpc.user.getUserById('123');
//    ^? { data: User }
//    ^? id parameter is typed as string
//    ^? Full autocomplete for User properties

If your server types change, your client code will show TypeScript errors immediately!

📖 API Reference

RpcClient<Manifest>

Main client class.

const client = new RpcClient<Manifest>(config);

Config:

  • baseUrl: string - Base URL of your server
  • apiPrefix?: string - API prefix (default: 'nestjs-rpc')
  • axiosInstance?: AxiosInstance - Custom Axios instance
  • requestOptions?: AxiosRequestConfig - Default request options

client.routers()

Get the router proxy for making RPC calls.

const rpc = client.routers();
// Use rpc.user.getUserById(), etc.

client.$setConfig(config)

Update the entire configuration.

client.$setConfigProperty(key, value)

Update a single configuration property.

client.$config

Read-only access to current configuration.

🎯 Best Practices

  • Export manifest type - Make sure your server exports export type Manifest = typeof manifest
  • Centralize client - Create one client instance and export it
  • Use environment variables - Use different base URLs for dev/prod
  • Handle errors - Wrap calls in try-catch or use error boundaries
  • Type your responses - Use const { data } destructuring for better types

💡 Examples

Check out the example directory for a complete working example with React.

📚 Need More Help?

📖 Full Documentation →

Complete guides, API reference, advanced patterns, and troubleshooting

🤝 Contributing

Contributions welcome! See the main README for details.

📄 License

MIT

Made with ❤️ for the NestJS community

⭐ Star us on GitHub📖 Documentation💬 Discussions

Keywords

nestjs

FAQs

Package last updated on 25 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts