CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ky

Tiny and elegant HTTP client based on the Fetch API

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

instances.mddocs/

Instance Management

Create and extend ky instances with custom defaults for different API endpoints or configurations. This enables reusable configuration patterns and API-specific client creation.

Capabilities

Create Instance

Create a new ky instance with completely new defaults, independent of the parent instance.

/**
 * Create a new Ky instance with complete new defaults
 * @param defaultOptions - Default options for the new instance
 * @returns New KyInstance with the specified defaults
 */
function create(defaultOptions?: Options): KyInstance;

Usage Examples:

import ky from "ky";

// Create API-specific instance
const apiClient = ky.create({
  prefixUrl: "https://api.example.com",
  headers: {
    "Authorization": "Bearer token123",
    "Content-Type": "application/json"
  },
  timeout: 10000,
  retry: 3
});

// Use the configured instance
const users = await apiClient.get("users").json();
const user = await apiClient.post("users", {
  json: { name: "Alice", email: "alice@example.com" }
}).json();

// Create instance with custom retry logic
const robustClient = ky.create({
  retry: {
    limit: 5,
    methods: ["get", "post", "put"],
    statusCodes: [408, 413, 429, 500, 502, 503, 504],
    delay: (attemptCount) => Math.min(1000 * (2 ** attemptCount), 30000)
  },
  timeout: 30000
});

// Create instance with custom JSON handling
const customJsonClient = ky.create({
  parseJson: (text) => {
    // Custom JSON parsing logic
    return JSON.parse(text, (key, value) => {
      if (key.endsWith("_date")) {
        return new Date(value);
      }
      return value;
    });
  },
  stringifyJson: (data) => {
    // Custom JSON stringification
    return JSON.stringify(data, (key, value) => {
      if (value instanceof Date) {
        return value.toISOString();
      }
      return value;
    });
  }
});

Extend Instance

Create a new ky instance that inherits defaults from its parent and overrides or adds specific options.

/**
 * Create a new Ky instance with some defaults overridden with your own
 * Inherits defaults from its parent, unlike create() which starts fresh
 * @param defaultOptions - Options to override/add, or function receiving parent options
 * @returns New KyInstance extending the parent instance
 */
function extend(defaultOptions: Options | ((parentOptions: Options) => Options)): KyInstance;

Usage Examples:

import ky from "ky";

// Create base API client
const apiClient = ky.create({
  prefixUrl: "https://api.example.com",
  headers: { "Authorization": "Bearer token123" },
  timeout: 10000
});

// Extend with additional headers
const adminClient = apiClient.extend({
  headers: { "X-Admin-Access": "true" },
  timeout: 15000 // Override parent timeout
});

// Extend with function for dynamic configuration
const versionedClient = apiClient.extend((options) => ({
  prefixUrl: `${options.prefixUrl}/v2`,
  headers: {
    ...options.headers,
    "API-Version": "2.0"
  }
}));

// Create specialized clients from base
const usersClient = apiClient.extend({
  prefixUrl: "https://api.example.com/users",
  hooks: {
    beforeRequest: [
      (request) => {
        request.headers.set("X-Resource", "users");
      }
    ]
  }
});

const filesClient = apiClient.extend({
  prefixUrl: "https://api.example.com/files",
  timeout: 60000, // Longer timeout for file operations
  onUploadProgress: (progress) => {
    console.log(`Upload: ${Math.round(progress.percent * 100)}%`);
  }
});

// Chain extensions for complex inheritance
const devUsersClient = usersClient.extend({
  prefixUrl: "https://dev-api.example.com/users",
  headers: { "X-Environment": "development" }
});

Instance with Hooks

Create instances with pre-configured hooks for common patterns like authentication, logging, or error handling.

Usage Examples:

import ky from "ky";

// Instance with authentication refresh
const authClient = ky.create({
  prefixUrl: "https://api.example.com",
  hooks: {
    beforeRequest: [
      (request) => {
        const token = localStorage.getItem("token");
        if (token) {
          request.headers.set("Authorization", `Bearer ${token}`);
        }
      }
    ],
    beforeRetry: [
      async ({ request, options, error, retryCount }) => {
        if (error instanceof HTTPError && error.response.status === 401) {
          // Refresh token and retry
          const newToken = await refreshAuthToken();
          request.headers.set("Authorization", `Bearer ${newToken}`);
        }
      }
    ]
  }
});

// Instance with logging
const loggedClient = ky.create({
  hooks: {
    beforeRequest: [
      (request) => {
        console.log(`→ ${request.method} ${request.url}`);
      }
    ],
    afterResponse: [
      (request, options, response) => {
        console.log(`← ${response.status} ${request.method} ${request.url}`);
      }
    ]
  }
});

// Instance with error transformation
const errorClient = ky.create({
  hooks: {
    beforeError: [
      (error) => {
        if (error.response) {
          // Add custom error information
          error.name = "APIError";
          error.message = `API Error: ${error.response.status} ${error.response.statusText}`;
        }
        return error;
      }
    ]
  }
});

Environment-Specific Instances

Create instances optimized for different environments or API versions.

Usage Examples:

import ky from "ky";

// Development instance with verbose logging
const devClient = ky.create({
  prefixUrl: "https://dev-api.example.com",
  timeout: 30000,
  retry: { limit: 1 }, // Fail fast in development
  hooks: {
    beforeRequest: [(request) => console.log("DEV:", request.method, request.url)],
    beforeError: [(error) => { console.error("DEV ERROR:", error); return error; }]
  }
});

// Production instance with robust retry
const prodClient = ky.create({
  prefixUrl: "https://api.example.com",
  timeout: 10000,
  retry: {
    limit: 3,
    methods: ["get", "put", "head", "delete"],
    statusCodes: [408, 413, 429, 500, 502, 503, 504]
  },
  throwHttpErrors: true
});

// Testing instance with mocked responses
const testClient = ky.create({
  hooks: {
    beforeRequest: [
      (request) => {
        // Return mock response for testing
        if (request.url.includes("/users/123")) {
          return new Response(JSON.stringify({ id: 123, name: "Test User" }), {
            status: 200,
            headers: { "Content-Type": "application/json" }
          });
        }
      }
    ]
  }
});

Types

interface KyInstance {
  <T>(url: Input, options?: Options): ResponsePromise<T>;
  get: <T>(url: Input, options?: Options) => ResponsePromise<T>;
  post: <T>(url: Input, options?: Options) => ResponsePromise<T>;
  put: <T>(url: Input, options?: Options) => ResponsePromise<T>;
  patch: <T>(url: Input, options?: Options) => ResponsePromise<T>;
  delete: <T>(url: Input, options?: Options) => ResponsePromise<T>;
  head: (url: Input, options?: Options) => ResponsePromise;
  create: (defaultOptions?: Options) => KyInstance;
  extend: (defaultOptions: Options | ((parentOptions: Options) => Options)) => KyInstance;
  readonly stop: typeof stop;
}

type Input = string | URL | Request;

interface Options extends KyOptions, RequestInit {
  method?: LiteralUnion<HttpMethod, string>;
  headers?: KyHeadersInit;
}

docs

configuration.md

errors.md

hooks.md

http-methods.md

index.md

instances.md

responses.md

retry.md

tile.json