askill
data-client-rest-setup

data-client-rest-setupSafety 95Repository

Set up @data-client/rest for REST APIs. Creates custom RestEndpoint base class with common behaviors (auth, urlPrefix, error handling). Use after data-client-setup detects REST patterns.

2k stars
40.4k downloads
Updated 2/15/2026

Package Files

Loading files...
SKILL.md

REST Protocol Setup

This skill configures @data-client/rest for a project. It should be applied after skill "data-client-setup" detects REST API patterns.

First, apply the skill "data-client-rest" for accurate implementation patterns.

Installation

Install the REST package alongside the core package:

# npm
npm install @data-client/rest

# yarn
yarn add @data-client/rest

# pnpm
pnpm add @data-client/rest

Custom RestEndpoint Base Class

After installing, offer to create a custom RestEndpoint class for the project.

Detection Checklist

Scan the existing codebase for common REST patterns to include:

  1. Base URL / API prefix: Look for hardcoded URLs like https://api.example.com or env vars like process.env.API_URL
  2. Authentication: Look for Authorization headers, tokens in localStorage/cookies, auth interceptors
  3. Content-Type handling: Check if API uses JSON, form-data, or custom content types
  4. Error handling: Look for error response patterns, status code handling
  5. Request/Response transforms: Data transformations, date parsing, case conversion
  6. Query string format: Simple params vs nested objects (may need qs library)

Base Class Template

Create a file at src/api/BaseEndpoint.ts (or similar location based on project structure):

import { RestEndpoint, RestGenerics } from '@data-client/rest';

/**
 * Base RestEndpoint with project-specific defaults.
 * Extend this for all REST API endpoints.
 */
export class BaseEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
  // API base URL - adjust based on detected patterns
  urlPrefix = process.env.REACT_APP_API_URL ?? 'https://api.example.com';

  // Add authentication headers
  getHeaders(headers: HeadersInit): HeadersInit {
    const token = localStorage.getItem('authToken');
    return {
      ...headers,
      ...(token && { Authorization: `Bearer ${token}` }),
    };
  }
}

Common Lifecycle Overrides

Include these based on what's detected in the codebase. See RestEndpoint for full API documentation.

Authentication (async token refresh)

async getHeaders(headers: HeadersInit): Promise<HeadersInit> {
  const token = await getValidToken(); // handles refresh
  return {
    ...headers,
    Authorization: `Bearer ${token}`,
  };
}

Custom Request Init (CSRF, credentials)

getRequestInit(body?: RequestInit['body'] | Record<string, unknown>): RequestInit {
  return {
    ...super.getRequestInit(body),
    credentials: 'include', // for cookies
    headers: {
      'X-CSRF-Token': getCsrfToken(),
    },
  };
}

Custom Response Parsing (unwrap data envelope)

process(value: any, ...args: any[]) {
  // If API wraps responses in { data: ... }
  return value.data ?? value;
}

Custom Error Handling

async fetchResponse(input: RequestInfo, init: RequestInit): Promise<Response> {
  const response = await super.fetchResponse(input, init);
  
  // Handle specific status codes
  if (response.status === 401) {
    // Trigger logout or token refresh
    window.dispatchEvent(new CustomEvent('auth:expired'));
  }
  
  return response;
}

Custom Search Params (using qs library)

searchToString(searchParams: Record<string, any>): string {
  // For complex nested query params
  return qs.stringify(searchParams, { arrayFormat: 'brackets' });
}

Custom parseResponse (handle non-JSON)

async parseResponse(response: Response): Promise<any> {
  const contentType = response.headers.get('content-type');
  
  if (contentType?.includes('text/csv')) {
    return parseCSV(await response.text());
  }
  
  return super.parseResponse(response);
}

Full Example with Multiple Overrides

import { RestEndpoint, RestGenerics } from '@data-client/rest';
import qs from 'qs';

export class BaseEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
  urlPrefix = process.env.API_URL ?? 'http://localhost:3001/api';

  async getHeaders(headers: HeadersInit): Promise<HeadersInit> {
    const token = await getAuthToken();
    return {
      ...headers,
      'Content-Type': 'application/json',
      ...(token && { Authorization: `Bearer ${token}` }),
    };
  }

  getRequestInit(body?: RequestInit['body'] | Record<string, unknown>): RequestInit {
    return {
      ...super.getRequestInit(body),
      credentials: 'include',
    };
  }

  searchToString(searchParams: Record<string, any>): string {
    return qs.stringify(searchParams, { arrayFormat: 'brackets' });
  }

  process(value: any, ...args: any[]) {
    // Unwrap { data: ... } envelope if present
    return value?.data ?? value;
  }
}

// Helper function - implement based on project auth pattern
async function getAuthToken(): Promise<string | null> {
  // Check for valid token, refresh if needed
  return localStorage.getItem('token');
}

Usage After Setup

Once the base class is created, use it instead of RestEndpoint directly:

import { BaseEndpoint } from './BaseEndpoint';
import { Todo } from '../schemas/Todo';

export const getTodo = new BaseEndpoint({
  path: '/todos/:id',
  schema: Todo,
});

export const updateTodo = getTodo.extend({ method: 'PUT' });

Or with resource():

import { resource } from '@data-client/rest';
import { BaseEndpoint } from './BaseEndpoint';
import { Todo } from '../schemas/Todo';

export const TodoResource = resource({
  path: '/todos/:id',
  schema: Todo,
  Endpoint: BaseEndpoint,
});

Next Steps

  1. Apply skill "data-client-schema" to define Entity classes
  2. Apply skill "data-client-rest" for resource and endpoint patterns
  3. Apply skill "data-client-react" or "data-client-vue" for usage

References

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

87/100Analyzed 2/19/2026

High-quality skill for setting up @data-client/rest with comprehensive coverage of custom RestEndpoint patterns. Includes detection checklist, multiple lifecycle override examples (auth, CSRF, response parsing, error handling), and clear usage instructions. Slight penalty for .cursor path suggesting agent config, but content itself is well-structured and highly reusable across projects. Actionable and safe with good security practices shown.

95
85
80
85
90

Metadata

Licenseunknown
Version-
Updated2/15/2026
Publisherreactive

Tags

apisecurity