restix
v0.0.3
Published
Type-safe HTTP client builder for CLI tools and backend applications
Readme
restix
restix is a strict, type-safe HTTP client builder designed for CLI tools and backend applications.
It allows you to define your API once as a contract and interact with it safely without rewriting fetch logic, URL builders, or request payload handling.
Design your API → map it → call it safely
No runtime magic. No hidden abstractions. No guessing.
Why restix?
When building CLI tools or backend services, you often need to:
- Call many HTTP endpoints
- Inject URL params, query strings, headers, and body data
- Keep everything type-safe
- Avoid request boilerplate
restix solves this by:
- Enforcing exact input types per endpoint
- Preventing extra or missing fields at compile time
- Supporting multiple injection strategies
- Centralizing request logic
- Staying minimal and predictable
Core Concepts
1. API Contract (Type First)
Your API is defined as a TypeScript interface. Each key represents an endpoint, and its value represents the exact allowed input.
interface API_INTERFACE {
'GET /packages/cli/name/{name}': {
name: string
}
'POST /packages/cli/create': {
name: string
version: string
developer: string
}
}This interface is the single source of truth.
2. API Mapping
Each endpoint must declare how its data is injected.
Supported injection targets:
params→ URL parametersquery→ query stringbody→ request bodyheaders→ request headers
import { apiMap, type API_MAPS, type GET_API } from 'restix'
const api_maps: API_MAPS<API_INTERFACE> = {
'GET /packages/cli/name/{name}': {
map: apiMap<GET_API<API_INTERFACE, 'GET /packages/cli/name/{name}'>>({
params: ['name']
}),
res: 'json'
},
'POST /packages/cli/create': {
map: apiMap<GET_API<API_INTERFACE, 'POST /packages/cli/create'>>({
body: ['*']
}),
res: 'json',
status: {
safe: 201
}
}
}'*' means all fields
Explicit keys mean only those fields
3. Query Injection Strategies
A) Automatic Query Injection
map: apiMap({
query: ['q', 'v']
})api.request('GET /search', {
q: 'nex',
v: '1'
})➡️ ?q=nex&v=1
B) URL-Positioned Query Injection
'GET /packages/cli/search?selam={v}&VERSION={v}'api.request(
'GET /packages/cli/search?selam={v}&VERSION={v}',
{
q: 'nex',
v: 'sa'
}
)➡️ ?selam=sa&VERSION=sa
This is especially useful for:
- Legacy APIs
- Fixed query naming conventions
- Enterprise-style endpoints
4. Creating the Client
import { NexAPI } from 'restix'
const api = new NexAPI<API_INTERFACE>(
'http://localhost:5000',
api_maps
)With Defaults
const api = new NexAPI<API_INTERFACE>(
'http://localhost:5000',
api_maps,
{
headers: {
'User-Agent': 'restix-cli'
},
status: {
404: () => 'Global not found'
}
}
)Defaults are merged, not replaced.
5. Making Requests (Type-Safe)
await api.request('GET /packages/cli/name/{name}', {
name: 'xnex'
})await api.request('POST /packages/cli/create', {
name: 'xnex',
version: '0.0.1',
developer: 'Signor P'
})❌ Compile-time error (extra field):
api.request('GET /packages/cli/name/{name}', {
name: 'xnex',
extra: 'nope'
})❌ Compile-time error (missing field):
api.request('POST /packages/cli/create', {
name: 'xnex'
})Status Handling
Each endpoint can define status handlers:
status: {
safe: 200,
404: () => 'Not found',
400: () => 'Bad request'
}You can also define global status defaults when creating the client.
Key Features
- ✅ Exact object typing (no extra keys)
- ✅ Route-based type inference
- ✅ URL param injection
- ✅ Automatic & positional query injection
- ✅ Header & body extraction
- ✅ Global + local status handling
- ✅ CLI-friendly (Bun / Node)
- ✅ No runtime dependencies
- ✅ No decorators, no reflection
Designed For
- CLI tools
- Backend services
- Automation scripts
- Internal SDKs
- API clients
- Monorepo shared tooling
Not designed for heavy frontend frameworks.
Philosophy
restix follows a contract-first approach:
- Types are the contract
- Mapping defines behavior
- Requests are deterministic
- Errors are caught at compile time
If TypeScript allows it, restix allows it. If TypeScript rejects it, restix rejects it too.
Status
This project is actively evolving. The API is intentionally minimal and strict.
Ideas, issues, and contributions are welcome.
License
MIT
