
Security News
Another Round of TEA Protocol Spam Floods npm, But It’s Not a Worm
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.
what-the-fetch
Advanced tools
Type-safe API client with schema validation using Standard Schema.
what-the-fetch is a type-safe API client library that integrates schema validation with fetch requests, leveraging the Standard Schema specification for maximum flexibility and type safety.
# Using npm
npm install what-the-fetch
# Using bun
bun add what-the-fetch
# Using JSR (recommended for Deno)
deno add jsr:@hckhanh/what-the-fetch
import { createFetch } from 'what-the-fetch';
import { z } from 'zod';
// Define your API schema
const api = {
'/users/:id': {
params: z.object({ id: z.number() }),
query: z.object({ fields: z.string().optional() }),
response: z.object({
id: z.number(),
name: z.string(),
email: z.string(),
}),
},
'/users': {
query: z.object({
limit: z.number().optional(),
offset: z.number().optional(),
}),
response: z.array(z.object({
id: z.number(),
name: z.string(),
})),
},
} as const;
// Create a typed fetch function
const apiFetch = createFetch(api, 'https://api.example.com');
// Make type-safe requests
const user = await apiFetch('/users/:id', {
params: { id: 123 },
query: { fields: 'name,email' },
});
// user is typed as { id: number; name: string; email: string }
const users = await apiFetch('/users', {
query: { limit: 10, offset: 0 },
});
// users is typed as Array<{ id: number; name: string }>
const api = {
'/users': {
body: z.object({
name: z.string(),
email: z.string().email(),
}),
response: z.object({
id: z.number(),
name: z.string(),
email: z.string(),
}),
},
} as const;
const apiFetch = createFetch(api, 'https://api.example.com');
const newUser = await apiFetch('/users', {
body: {
name: 'John Doe',
email: 'john@example.com',
},
});
what-the-fetch automatically infers HTTP methods: requests with a body use POST, and requests without a body use GET. You can also explicitly specify methods using the @method prefix for clarity or when you need other HTTP methods:
const api = {
// Automatic method inference (these are equivalent)
'/users/:id': { // Uses GET (no body)
params: z.object({ id: z.number() }),
response: z.object({ id: z.number(), name: z.string() }),
},
'@get/users/:id': { // Explicitly GET - same as above
params: z.object({ id: z.number() }),
response: z.object({ id: z.number(), name: z.string() }),
},
// POST is inferred when body is present
'/users': { // Uses POST (has body)
body: z.object({ name: z.string(), email: z.string().email() }),
response: z.object({ id: z.number(), name: z.string() }),
},
// Explicit methods for PUT, PATCH, DELETE
'@put/users/:id': {
params: z.object({ id: z.number() }),
body: z.object({ name: z.string(), email: z.string().email() }),
response: z.object({ id: z.number(), name: z.string() }),
},
'@delete/users/:id': {
params: z.object({ id: z.number() }),
response: z.object({ success: z.boolean() }),
},
} as const;
const apiFetch = createFetch(api, 'https://api.example.com');
// These are equivalent - both use GET
const user1 = await apiFetch('/users/:id', { params: { id: 123 } });
const user2 = await apiFetch('@get/users/:id', { params: { id: 123 } });
// POST (inferred from body)
const newUser = await apiFetch('/users', {
body: { name: 'John Doe', email: 'john@example.com' },
});
// Explicit methods for clarity
await apiFetch('@put/users/:id', {
params: { id: 123 },
body: { name: 'Jane Doe', email: 'jane@example.com' },
});
await apiFetch('@delete/users/:id', { params: { id: 123 } });
### With Shared Headers
You can provide shared headers when creating the fetch function:
```typescript
const apiFetch = createFetch(
api,
'https://api.example.com',
{
headers: {
'Authorization': 'Bearer token',
},
}
);
// All requests will include the Authorization header
const user = await apiFetch('/users/:id', { params: { id: 123 } });
You can also provide per-request headers that will be merged with shared headers:
const apiFetch = createFetch(api, 'https://api.example.com');
const user = await apiFetch(
'/users/:id',
{ params: { id: 123 } },
{
headers: {
'Authorization': 'Bearer token',
'X-Custom-Header': 'value',
},
}
);
createFetch(schema, baseUrl, sharedInit?)Creates a type-safe fetch function for your API.
Parameters:
schema: An object mapping API paths to their schema definitionsbaseUrl: The base URL for all API requestssharedInit (optional): Shared RequestInit options that will be merged with per-request optionsReturns: A typed fetch function that accepts:
path: The API path (must be a key from your schema)options (optional): Request options (params, query, body) based on the path's schemainit (optional): Per-request RequestInit to customize the fetch request (merged with sharedInit)Each path in your schema can have:
params: Schema for URL path parameters (e.g., :id) - Required for parameterized pathsquery: Schema for query string parametersbody: Schema for request body (automatically sets method to POST)response: Schema for response validationAll schemas must implement the Standard Schema specification.
Note: If your path contains parameters (e.g., /users/:id), you must define a params schema. The library will throw an error at runtime if you attempt to use a parameterized path without a params schema.
Building API clients manually is error-prone and lacks type safety:
// ❌ No type safety, manual validation
const response = await fetch(`${baseUrl}/users/${id}?fields=${fields}`);
const data = await response.json();
// What type is data? Who knows!
// ✅ Type-safe with validation
const user = await apiFetch('/users/:id', {
params: { id },
query: { fields },
});
// user is fully typed and validated!
what-the-fetch handles:
what-the-fetch works with any schema library that implements Standard Schema:
Contributions are welcome! Please feel free to submit a Pull Request.
MIT
FAQs
Type-safe API client with schema validation using Standard Schema
We found that what-the-fetch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.

Security News
PyPI adds Trusted Publishing support for GitLab Self-Managed as adoption reaches 25% of uploads

Research
/Security News
A malicious Chrome extension posing as an Ethereum wallet steals seed phrases by encoding them into Sui transactions, enabling full wallet takeover.