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

zikit-js

v1.0.1

Published

Data that blends in. A self-healing Express middleware that uses AI (Claude) to automatically repair malformed data and caches transformations for zero-latency future requests.

Readme

ZIKIT 🦎

Data that blends in.

A self-healing Express middleware that automatically repairs malformed data using AI (Claude) and caches transformations for zero-latency future requests.

Features

  • AI-Powered Repair - Uses Claude to intelligently fix data that doesn't match your Zod schema
  • Zero-Latency Caching - Caches repair patterns so repeated requests are instant
  • Strict Fields - Designate fields that must match exactly (no AI repair)
  • Configurable - Global config file + per-route overrides
  • Type-Safe - Full TypeScript support with Zod schemas
  • Express Ready - Drop-in middleware for Express.js

Installation

npm install zikit-js

Quick Start

1. Set up your API key

Create a zikit.config.json file in your project root:

{
  "apiKey": "your-anthropic-api-key-here",
  "strictFields": ["id", "userId"]
}

Or use environment variables:

export ANTHROPIC_API_KEY="your-key-here"

2. Use the middleware

import express from 'express';
import { zikit } from 'zikit-js';
import { z } from 'zod';

const app = express();
app.use(express.json());

// Define your schema
const UserSchema = z.object({
  id: z.string(),        // Strict field - must match exactly
  name: z.string(),      // Can be repaired
  age: z.number(),       // Can be repaired
  email: z.string().email(),
});

// Use zikit middleware
app.post('/users', zikit(UserSchema), (req, res) => {
  // req.body is now guaranteed to match UserSchema!
  // It was either already valid, or AI repaired it automatically
  res.json({ success: true, user: req.body });
});

How It Works

  1. Request arrives with potentially bad data: { name: "John", age: "30" }
  2. Check cache → If we've seen this structure before, use cached repair (instant!)
  3. Validate strict fields → If any strict field fails, reject immediately
  4. Call AI → Claude repairs the data: { name: "John", age: 30 }
  5. Cache the repair → Save for next time (same structure = instant response)
  6. Return clean datareq.body is now validated/repaired

Configuration

Config File (zikit.config.json)

{
  "apiKey": "your-anthropic-api-key",
  "model": "claude-sonnet-4-20250514",
  "maxTokens": 1024,
  "strictFields": ["id", "userId", "email"]
}

Per-Route Configuration

app.post('/users', zikit(UserSchema, {
  strictFields: ['id'],           // Override global strictFields
  adapter: {
    apiKey: 'custom-key',         // Override API key
    timeout: 60000,               // 60 second timeout
    retries: 2,                   // Retry twice on failure
    retryDelay: 2000,            // Wait 2s between retries
  },
  memory: {
    maxSize: 1000,               // Cache up to 1000 entries
    ttl: 3600000,                // 1 hour TTL
  },
}), handler);

Configuration Options

Global Config (zikit.config.json)

| Option | Type | Default | Description | |--------|------|---------|-------------| | apiKey | string | process.env.ANTHROPIC_API_KEY | Anthropic API key | | model | string | "claude-sonnet-4-20250514" | Claude model to use | | maxTokens | number | 1024 | Maximum tokens for AI response | | strictFields | string[] | [] | Fields that must match exactly |

Per-Route Config (zikit(schema, config))

| Option | Type | Description | |--------|------|-------------| | strictFields | string[] | Fields that must match exactly (overrides global) | | adapter.apiKey | string | API key (overrides global) | | adapter.model | string | Model name (overrides global) | | adapter.maxTokens | number | Max tokens (overrides global) | | adapter.timeout | number | Request timeout in ms (default: 30000) | | adapter.retries | number | Number of retry attempts (default: 0) | | adapter.retryDelay | number | Delay between retries in ms (default: 1000) | | memory.maxSize | number | Max cache entries (default: 500) | | memory.ttl | number | Cache TTL in ms (default: 3600000) | | schemaId | string | Custom schema identifier for caching | | maxInputSize | number | Max input size in bytes (default: 100000 = 100KB) |

Examples

Basic Usage

const UserSchema = z.object({
  name: z.string(),
  age: z.number(),
});

app.post('/users', zikit(UserSchema), (req, res) => {
  // req.body is validated/repaired
  res.json(req.body);
});

With Strict Fields

const UserSchema = z.object({
  id: z.string(),        // Must match exactly
  name: z.string(),      // Can be repaired
  age: z.number(),       // Can be repaired
});

// Global strict fields from config file
app.post('/users', zikit(UserSchema), handler);

// Or override per-route
app.post('/admins', zikit(UserSchema, {
  strictFields: ['id', 'email']
}), handler);

Complex Nested Schemas

const OrderSchema = z.object({
  user: z.object({
    profile: z.object({
      name: z.string(),
      email: z.string().email(),
    }),
  }),
  items: z.array(z.object({
    productId: z.string(),
    quantity: z.number(),
    price: z.number(),
  })),
});

app.post('/orders', zikit(OrderSchema), (req, res) => {
  // All nested data is validated/repaired
  res.json(req.body);
});

Error Handling

app.post('/users', zikit(UserSchema), (req, res, next) => {
  // If strict field validation fails, error is passed to Express error handler
  res.json(req.body);
});

// Express error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  if (err.message.includes('Strict field validation failed')) {
    res.status(400).json({ error: err.message });
  } else if (err.message.includes('AI repair failed')) {
    res.status(500).json({ error: 'Data repair service unavailable' });
  } else {
    res.status(500).json({ error: 'Internal server error' });
  }
});

How Caching Works

ZIKIT uses two-tier caching for optimal performance:

Tier 1: Exact Match Cache (Structure + Values)

// Request 1: { name: "John", age: "30" }
// → AI repairs: { name: "John", age: 30 }
// → Cached with key: structure + values + schema

// Request 2: { name: "John", age: "30" }  (exact same!)
// → Exact cache HIT! Instant response, no AI call
// → Returns: { name: "John", age: 30 }

Tier 2: Pattern Cache (Structure Only)

// Request 3: { name: "Jane", age: "25" }  (different values, same structure!)
// → Exact cache MISS
// → Pattern cache HIT! Applies transformation pattern
// → Transforms "25" → 25 (learned from Request 1)
// → Returns: { name: "Jane", age: 25 } - INSTANT, no AI call!

How it works:

  1. Exact match: If structure + values match exactly → instant return
  2. Pattern match: If structure matches but values differ → apply learned transformation pattern
  3. Cache miss: If neither matches → call AI, then cache both exact + pattern

Benefits:

  • Accuracy: Exact matches are always correct
  • Performance: Pattern cache handles similar requests without AI calls
  • Cost savings: Pattern cache dramatically reduces AI calls for high-volume APIs

Cost Optimization Tips

ZIKIT's two-tier caching automatically optimizes for high-volume scenarios:

  1. Pattern cache reduces AI calls - Same structure problems share transformation patterns:

    // First: { age: "30" } → AI call → caches pattern
    // Then: { age: "25" } → Pattern cache hit → NO AI call!
  2. Increase cache size - Store more patterns:

    zikit(UserSchema, {
      memory: { maxSize: 10000 } // Store 10k entries (5k exact + 5k patterns)
    })
  3. Use strict fields - Reject invalid data early (no AI cost):

    zikit(UserSchema, {
      strictFields: ['id', 'userId'] // Reject if these fail - no AI call
    })
  4. Monitor cache performance:

    const stats = memory.getStats();
    console.log(`Cache hit rate: ${stats.hitRate}%`);
    console.log(`Total entries: ${stats.size} (exact + patterns)`);
  5. Set appropriate TTL - Balance freshness vs. cache hits:

    zikit(UserSchema, {
      memory: { ttl: 24 * 60 * 60 * 1000 } // 24 hours
    })

API Reference

zikit<T>(schema: ZodType<T>, config?: ZikitConfig): ZikitMiddleware

Creates an Express middleware function for the given Zod schema.

Parameters:

  • schema - Zod schema to validate/repair against
  • config - Optional configuration (see Configuration Options)

Returns: Express middleware function

Types

interface ZikitConfig {
  adapter?: AdapterConfig;
  memory?: MemoryConfig;
  schemaId?: string;
  strictFields?: string[];
  maxInputSize?: number; // Maximum input size in bytes (default: 100000 = 100KB)
}

interface AdapterConfig {
  apiKey?: string;
  model?: string;
  maxTokens?: number;
  timeout?: number;
  retries?: number;
  retryDelay?: number;
}

interface MemoryConfig {
  maxSize?: number;
  ttl?: number;
}

Advanced Usage

Custom Schema IDs

app.post('/users', zikit(UserSchema, {
  schemaId: 'UserSchemaV2'  // Custom cache key
}), handler);

Accessing Cache Statistics

import { ZikitMemory } from 'zikit-js';

const memory = new ZikitMemory();
const stats = memory.getStats();

console.log({
  hits: stats.hits,        // Cache hits
  misses: stats.misses,    // Cache misses
  hitRate: stats.hitRate,  // Hit rate percentage
  size: stats.size,        // Current cache size
});

Error Handling

ZIKIT handles errors gracefully:

  • Strict field validation fails → 400 error passed to Express
  • AI repair fails → Error passed to Express error handler
  • Network timeout → Configurable timeout with retries
  • Invalid JSON from AI → Error with details

Security

ZIKIT includes comprehensive prompt injection protection to prevent malicious users from manipulating the AI's behavior.

Prompt Injection Protection

ZIKIT implements multiple layers of security to prevent prompt injection attacks:

1. Input Sanitization

  • Automatically filters dangerous patterns like "ignore previous instructions", "system:", etc.
  • Removes code blocks that might contain malicious instructions
  • Escapes special characters through JSON serialization

2. System/User Message Separation

  • Uses Anthropic's system message for core instructions (harder to override)
  • Isolates user data in user message with explicit delimiters
  • System instructions are protected from user input manipulation

3. Input Size Limits

  • Default 100KB limit on request payloads (configurable)
  • 10KB limit on data section in AI prompts
  • Prevents prompt flooding attacks
app.post('/users', zikit(UserSchema, {
  maxInputSize: 50000, // Limit to 50KB (default: 100KB)
}), handler);

4. Explicit Security Instructions

  • Multiple security warnings in system prompt
  • Clear instructions to ignore any commands in user data
  • Visual delimiters to separate data from instructions

5. Output Validation

  • All AI responses are validated against Zod schema
  • Even if AI is manipulated, output must match expected structure
  • Invalid responses are rejected and errors are thrown

Security Best Practices

  1. Use Strict Fields - Protect critical fields from AI repair:

    zikit(UserSchema, {
      strictFields: ['id', 'userId', 'email'] // Reject if invalid, no AI call
    })
  2. Set Input Size Limits - Prevent large payload attacks:

    zikit(UserSchema, {
      maxInputSize: 50000 // 50KB limit
    })
  3. Monitor for Suspicious Patterns - Log and monitor:

    // In your Express error handler
    app.use((err, req, res, next) => {
      if (err.message.includes('Input size exceeds')) {
        // Log suspicious large payloads
        console.warn('Large payload detected:', req.body);
      }
    });
  4. Rate Limiting - Combine with rate limiting middleware:

    import rateLimit from 'express-rate-limit';
       
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100 // limit each IP to 100 requests per windowMs
    });
       
    app.use('/api', limiter);
    app.post('/users', zikit(UserSchema), handler);

What ZIKIT Protects Against

Prompt Injection - Malicious instructions in user data
Instruction Override - Attempts to change AI behavior
Prompt Flooding - Large payloads designed to overwhelm
Code Injection - Malicious code blocks in data
System Prompt Leakage - Attempts to extract system instructions

Security Considerations

  • Always validate output - ZIKIT validates all AI responses, but you should also validate in your business logic
  • Use strict fields - Critical fields should bypass AI repair entirely
  • Monitor costs - Unusual spikes might indicate abuse
  • Rate limiting - Combine with rate limiting for additional protection
  • Keep dependencies updated - Regularly update ZIKIT and other dependencies

Performance

  • Cache hit: ~0-10ms (instant, no AI call)
  • Cache miss: ~500-2000ms (AI call time, depends on Claude API)
  • Memory usage: Configurable (default: 500 entries)
  • Cost: Only pays for AI calls on cache misses

Cost Considerations

  • Exact cache hit: $0 (no API call, instant)
  • Pattern cache hit: $0 (no API call, applies learned transformation)
  • Cache miss: ~$0.003-0.015 per request (depends on Claude pricing)

Example with 10,000 requests/day:

  • 3,000 exact matches → $0 (exact cache)
  • 5,000 pattern matches → $0 (pattern cache)
  • 2,000 AI calls → ~$6-30/day

Best case: With 80%+ cache hit rate (exact + pattern), you pay for only 20% of requests!

Tip: Pattern cache automatically learns transformation patterns, so similar structure problems share the same repair logic without additional AI calls.

Requirements

  • Node.js 18+
  • Express.js 4.x or 5.x
  • Anthropic API key

License

MIT

Contributing

Contributions welcome! Please open an issue or submit a PR.

Support


Made with love ❤️ by 🦎 ZIKIT