npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

js-kt-api-client

v3.1.0

Published

Js-katana Api client

Readme

kt-client ⚔️

The Type-Safe bridge between your js-kt server and every JavaScript runtime.

kt-client gives you a drop-in HTTP + WebSocket client that speaks the js-kt runtime language. It pairs a CLI that downloads your server’s live contract and a runtime client that keeps the types in sync while you build.


✨ Why kt-client?

🎯 End-to-End Confidence

  • Server-Verified Types: Pull every route, channel, and event signature directly from your running js-kt server.
  • Autocomplete Everywhere: Rich IntelliSense in editors, plus inline docs that mirror your server annotations.
  • Zero Guesswork: Client method signatures stay locked to your server’s truth source.

Built for Real Projects

  • Unified Transport: HTTP and Socket.IO share the same type layer and configuration.
  • Scoped Access: Download only the APIs you are allowed to touch with per-scope filtering.
  • Production-Ready Storage: Opt-in caching, token management, and reconnection hooks included.

🧠 Developer Experience Deluxe

  • Commander-Powered CLI: Human-friendly commands with smart defaults and helpful prompts.
  • Plug & Play: Works with Bun, Node, TypeScript, or plain JavaScript bundles out of the box.
  • No Boilerplate: Create a fully configured client with a single function call.

🧱 Architecture at a Glance

kt-client is split into two tightly connected pieces:

| Piece | Path | What it does | | --- | --- | --- | | Types Loader CLI | src/client-api-types-loader/index.ts | Downloads live API metadata from your js-kt server and writes it to apiTypes.d.ts. | | Runtime Client Factory | src/api-client/index.tssrc/index.ts | Builds a typed HTTP + WebSocket client that uses the generated types for autocomplete and safety. |

The default export in src/index.ts is a pre-configured createApiClient that already understands the shapes produced by the loader.


🚀 Quick Start

1. Install

npm install js-kt-api-client
# or
bun add js-kt-api-client

2. (Optional) Configure your project

Default js-kt installations need zero setup—the loader assumes http://localhost:3000, /api, and no scope. If your server lives elsewhere, add an apiTypes section to your app’s package.json:

{
    "apiTypes": {
        "baseUrl": "http://localhost:3000",
        "apiPrefix": "/api",
        "scope": "dashboard"
    }
}
  • baseUrl – js-kt server origin (defaults to http://localhost:3000)
  • apiPrefix – HTTP prefix exposed by your server (defaults to /api)
  • scope – optional path prefix to filter routes, channels, and events

3. Pull the latest types

npx kt-client load-types
# or short
npx kt-client l

The CLI will:

  • discover your project root
  • hit the server’s __describe-json endpoint
  • generate a fresh apiTypes.d.ts alongside the package

Need auth? Export DESCRIPTION_SECRET before running the command and the loader will include it automatically.

4. Bootstrap the client

import createClient from "kt-client";

const client = createClient({
    baseUrl: "http://localhost:3000",
    // adapter defaults to "fetch" for ~2.3× faster raw HTTP calls; pass "axios" to opt in to Axios helpers
    // httpPrefix and channellingPrefix default to "/api" and "/channel" respectively
});

Autocomplete is now powered by the types you just generated. You can still override prefixes, scopes, or transport preferences at any time.


🔄 Keeping Types Fresh

  • Manual refresh: run npx kt-client load-types whenever the server contract changes.
  • Automation idea: add a post-deploy or postinstall script:
    {
        "scripts": {
            "refresh:types": "kt-client load-types",
            "postinstall": "kt-client load-types"
        }
    }
  • Scoped Projects: use --scope, --baseUrl, or --apiPrefix flags to override package.json options per run.

🕹️ Runtime Client Overview

The client factory returned by createApiClient gives you three pillars:

1. api – pluggable HTTP adapter

  • Choose between the built-in fetch adapter (default, ~2.3× faster HTTP throughput in our benchmarks) or opt into "axios" if you need its interceptors, transformers, or plugins.
  • Both adapters expose the same typed get, post, put, delete helpers plus caching controls.
  • With the Axios adapter you still get the underlying axios utilities (api._get, interceptors, etc.) without rewriting your calls.
  • Accepts requestVia hints (["http"], ["socket"], or both) to force a transport.
  • Respects caching toggles with noCaching, httpOnly, and storage options.

2. socket – Socket.IO power-up

  • asyncEmit(event, body, options) returns typed promises with optional timeouts.
  • on(event, callback) & off mirror the event signatures generated by the loader.
  • Handles autoReconnect, scoped namespaces, and before reconnect hooks.

3. Lifecycle helpers

  • reloadConfig(updatedProps) to swap runtime configuration without rebuilding.
  • close() to tear down socket connections and clear storage when you need the process to exit (ideal for scripts, CLIs, background jobs).
  • createWebStorage() utility for browser-friendly persistence.

🧊 Smart Caching with Web Storage

kt-client ships with a plug-and-play storage helper. Cache responses transparently and choose when to reuse them.

import createClient, { createWebStorage } from "kt-client";

const client = createClient({
    baseUrl: "http://localhost:3000",
    adapter: "fetch", // default; switch to "axios" to use Axios-specific features
    storage: createWebStorage(),
    noCaching: () => false // enable caching
});

// Prime the cache (uses socket transport automatically when the socket is connected)
await client.api.get("reports/daily", {
    params: { plan: "pro" },
    sinceMins: 15 // reuse the cached payload for 15 minutes
});

// Later within 15 minutes, the same request resolves from cache instantly
const cached = await client.api.get("reports/daily", {
    params: { plan: "pro" },
    sinceMins: 15
});

// Force a fresh fetch even inside the cache window
const fresh = await client.api.get("reports/daily", {
    params: { plan: "pro" },
    sinceMins: 15,
    now: true
});
  • sinceMins checks storage first; if a response is younger than the window, it’s returned immediately.
  • now: true bypasses the cache for that call and updates the stored response for future requests.

🧪 Example: One Client, Two Transports

Channelling is enabled by default, so the client will opportunistically reuse the socket transport without additional configuration.

import createClient from "kt-client";

const kt = createClient({
    baseUrl: "http://localhost:3000",
    getToken: () => window.localStorage.getItem("token") ?? undefined
});

// Typed HTTP call via socket if available
const user = await kt.api.get("users/profile", {
    params: { includeStats: true }
});

// Typed socket emit that automatically waits for a typed response
const ack = await kt.socket.asyncEmit("chat/message", {
    roomId: "general",
    message: "Hello from kt-client!"
});

// Force a request over HTTP even when the socket is connected
const dailyReport = await kt.api.get("reports/daily", {
    params: { includeMeta: true },
    requestVia: ["http"]
});

// Listen to server-side pushes with full type safety
const stop = await kt.socket.on("chat/receive", (payload, respond) => {
    console.log(payload.sender, payload.message);
    respond?.({ deliveredAt: Date.now() });
});

// Later: unsubscribe & clean up (only required in scripts/services)
await stop();
kt.close();

Every string literal route, channel, and event above is validated against the generated types. Autocomplete suggests only valid keys, and payload shapes are inferred automatically. By default, eligible API requests are dispatched over the socket when the server exposes the handler via sockets; if a route is configured with serveVia: ["http"] (or the socket connection is unavailable), kt-client falls back to plain HTTP automatically. Use requestVia: ["http"] to explicitly pin an individual request to HTTP even when the socket is ready.


🧬 Parameter-Aware Routes

The loader inspects your server files and generates literal types that understand dynamic segments. Routes such as users/[id].router.ts are transformed into template-literal safe keys:

const userId = crypto.randomUUID();

const res = await client.api.get(`users/${userId}`, {
    params: { verbose: true }
});

When you hover over the key, you’ll see it constrained to the shape users/${string}. Editors will even remind you of the expected params, body, headers, and response types automatically.


⚡ Socket-Accelerated HTTP

Channelling is enabled by default, so kt-client routes eligible HTTP requests through your socket connection, cutting latency by avoiding repeat network handshakes.

  • Requests fall back to HTTP automatically when sockets are unavailable or when you:
    • set httpOnly: () => true on the client to enforce HTTP for every request,
    • set channelling.useChannelling to false (which disables sockets over all), or
    • pass { requestVia: ["http"] } per request/config.
  • Combine with caching for blazing-fast UI refreshes while maintaining type guarantees.

If Socket.IO reconnects, kt-client replays pending emits and rehydrates subscriptions without manual work.


🔐 Authentication & Secrets

  • Tokens: Provide a getToken callback; the client injects the token into both HTTP headers and socket auth payloads.
  • App headers: Set appHeader to send a custom header along every request.
  • Private docs: Export DESCRIPTION_SECRET when running the loader if your server protects the describe endpoint.
DESCRIPTION_SECRET="super-secret" npx kt-client load-types

🧰 Configuration Reference

type ApiProps = {
    baseUrl: string;
    httpPrefix?: string;
    scope?: string;
    httpRequestTimeout?: number;
    httpOnly?: () => boolean;
    noCaching?: () => boolean;
    getToken?: () => string | undefined;
    appHeader?: string;
    storage?: Storage;
    onUnauthorized?: () => void | Promise<void>;
    adapter?: "fetch" | "axios";
    channelling?: {
        useChannelling: boolean;
        channellingPrefix?: string;
        autoConnect?: boolean;
        autoReconnect?: boolean;
        channellingRequestTimeout?: number;
        beforeReconnect?: (options: Partial<ManagerOptions & SocketOptions>) => void | boolean | Promise<void | boolean>;
        query?: any;
        transports?: string[];
    };
};
  • storage: Inject createWebStorage() for browser environments or bring your own.
  • onUnauthorized: Handle 401s globally (log out, refresh tokens, etc.).
  • adapter: Stay on the default fetch adapter for best raw HTTP performance, or pass "axios" when you need Axios niceties (transformers, interceptors, cancellation). Switching adapters does not change your typed API surface.
  • modifyRequest: Use axios interceptors exposed on client.api for custom logic.

🧭 Tips & Best Practices

  • Pin your server URL: Use environment variables and feed them to both the loader and the runtime client for consistency.
  • Version your types: Regenerate immediately after backend schema changes so reviews catch contract shifts.
  • Fail fast in CI: Run kt-client load-types during continuous integration to detect breaking API changes early.
  • Wrapper ready: Compose kt-client inside your own API service layer—types propagate automatically.

📡 Troubleshooting

| Symptom | Possible Cause | Fix | | --- | --- | --- | | No package.json file found | Running CLI outside your project root | Invoke from the app root or pass --baseUrl manually. | | Secret required | Server has DESCRIPTION_SECRET enforced | Export DESCRIPTION_SECRET before running the loader. | | Missing autocomplete | Types not referenced by your TS config | Include "./apiTypes.d.ts" in the include array or add /// <reference path="./apiTypes.d.ts" /> to your entry file. | | Socket stuck reconnecting | TTL expired or scope mismatch | Verify scope, channellingPrefix, and requestVia options. |


🙋 Need Help?

  • Check the server companion docs at https://github.com/almoatamed/js-katana for js-kt server features.
  • Open an issue or share feedback—kt-client evolves with your workflows.

Happy hacking, and may your types always line up! ⚔️