restql-client-next
v1.0.2
Published
A structured RestQL client adapter for Next.js Server Components.
Downloads
299
Maintainers
Readme
restql-client-next
A robust, type-safe client adapter for building complex RestQL queries in Next.js applications, optimized for Server Components and Server Actions.
🛠️ 2. Setup (Initializing the Client)
The restql-client-next package uses a factory pattern (createRestqlClient) which requires you to provide your specific API fetch logic. This is essential for handling authentication, base URLs, and error handling in your environment.
2.1. Define the Custom Fetch Function
This function wraps the native fetch API, adding necessary logic like setting the base URL, attaching authentication tokens, and handling detailed API errors.
// lib/api/services/api.ts (Example Fetch Wrapper)
'use server';
import { getAuthTokenServer } from '../auth/auth-helpers'; // Assuming an auth helper
const BASE_URL = process.env.ADMIN_API_URL || 'http://localhost:3000/api';
export async function fetchApi<T>(
endpoint: string,
options: RequestInit = {},
): Promise<T> {
const url = `${BASE_URL}${endpoint}`;
const token = await getAuthTokenServer();
const headers: Record<string, string> = {
...(options.headers as Record<string, string>),
};
if (!(options.body instanceof FormData)) {
headers['Content-Type'] = 'application/json';
}
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch(url, { ...options, headers });
if (!response.ok) {
// Detailed error handling...
let errorDetail = `HTTP error! Status: ${response.status}`;
try {
const errorBody = await response.json();
errorDetail = errorBody.message || errorDetail;
} catch {
errorDetail = response.statusText;
}
throw new Error(errorDetail);
}
if (response.status === 204) {
return {} as T;
}
return response.json() as Promise<T>;
}2.2. Instantiate the RestQL Client
Use the factory function to create a ready-to-use client instance and export a wrapper function for consumption in your application.
// lib/api/restql.ts
'use server';
import { createRestqlClient } from 'restql-client-next';
import { fetchApi } from './services/api';
// 1. Instantiate the client with your custom fetch function
const restqlClient = createRestqlClient(fetchApi);
/**
* Public export function for consuming the RestQL client.
* @param queryName The resource path (e.g., "collection", "users")
* @param params The structured RestQL parameters
*/
export async function findWithRestQL<T = any>(queryName: string, params?: any): Promise<T> {
return restqlClient.findWithRestql(queryName, params);
}Usage example
The client accepts a structured object for fields, filters, and includes, which it automatically serializes into the correct RestQL query string before sending the request via fetchApi.
const collections: ICollection[] = await findWithRestQL("collection", {
fields: [
{field: 'id'},
{field: 'name'},
{field: 'goal'},
{field: 'description'},
{field: 'image'},
{field: 'status', filters: [{ op: "==", type: "string", value: { OR: ["Completed", "Active"]}}]}
],
includes: [
{relation: "collected", fields: [
{field: "totalUah"}
]},
{relation: "category", fields: [
{field: "name"},
{field: "color"}
]}
]
})