@vbyte/util
v2.0.0
Published
A collection of micro libraries, helper methods, and utilities.
Readme
@vbyte/util
A collection of TypeScript micro-libraries, helper methods, and utilities. Designed with modular exports so you can import only what you need.
Test Coverage: 97%+ | 549 tests | TypeScript 5.0+ | API Docs
Installation
npm install @vbyte/utilQuick Start
import { Assert, Schema, Fetch } from '@vbyte/util'
// Type-safe assertions
const data: unknown = await fetchData()
Assert.is_object(data) // Throws if not object, narrows type
// Schema validation (works with Zod, Valibot, or custom validators)
import { z } from 'zod'
const UserSchema = z.object({ id: z.number(), name: z.string() })
const user = Schema.parse(UserSchema, data) // Type-safe parsed result
// Typed fetch with Result pattern
const result = await Fetch.json('https://api.example.com/users')
if (result.ok) {
console.log(result.data) // Type-safe data access
} else {
console.error(result.error) // Error message
}Modules
Import the entire library or individual modules:
// Full library
import { Assert, Fetch, Schema } from '@vbyte/util'
// Individual modules (tree-shakeable)
import { Assert } from '@vbyte/util/assert'
import { Fetch } from '@vbyte/util/fetch'
import { Schema } from '@vbyte/util/schema'Available Modules
| Module | Import | Description |
|--------|--------|-------------|
| Assert | @vbyte/util/assert | Type assertion utilities with runtime validation |
| Schema | @vbyte/util/schema | Generic schema validation (Zod, Valibot compatible) |
| Fetch | @vbyte/util/fetch | HTTP fetch with Result pattern |
| Class | @vbyte/util/class | EventEmitter, Mutex, Queue classes |
| Flow | @vbyte/util/flow | Async flow control (retry, debounce, throttle) |
| Debug | @vbyte/util/debug | Lightweight debug logging |
| JSON | @vbyte/util/json | JSON utilities with special type support |
| Result | @vbyte/util/result | Result type wrapper for error handling |
| Arr | @vbyte/util/arr | Array utilities (chunk, unique, groupBy) |
| Obj | @vbyte/util/obj | Object utilities (pick, omit, sort) |
| Str | @vbyte/util/str | String utilities (truncate, dedent) |
| Rand | @vbyte/util/rand | Cryptographic random generation |
| Time | @vbyte/util/time | Time utilities (sleep, timeout) |
| Test | @vbyte/util/test | Test helper functions |
API Examples
Assert - Type Assertions
Runtime type checks that narrow TypeScript types:
import { Assert } from '@vbyte/util/assert'
function processData(input: unknown) {
// Throws if assertion fails, narrows type if passes
Assert.is_string(input) // input is now string
Assert.is_number(input) // input is now number
Assert.is_array(input) // input is now unknown[]
Assert.is_object(input) // input is now Record<string, unknown>
Assert.exists(input) // input is now NonNullable<T>
Assert.is_hex(input) // input is now hex string
Assert.is_hash(input) // input is now 64-char hex string
}Schema - Validation
Works with any validation library implementing a standard interface:
import { Schema } from '@vbyte/util/schema'
import { z } from 'zod'
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email()
})
// Parse with type inference
const user = Schema.parse(UserSchema, data) // throws on invalid
// Safe parse with error details
const result = Schema.safe(UserSchema, data)
if (result.ok) {
console.log(result.data)
} else {
console.log(result.errors) // Detailed error array
}
// Type assertion
Schema.assert(UserSchema, data) // throws, narrows typeFetch - HTTP Utilities
Type-safe fetch with discriminated union responses:
import { Fetch, Resolve } from '@vbyte/util/fetch'
// JSON request
const result = await Fetch.json('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'test' })
})
if (result.ok) {
// result.data is typed
console.log(result.data, result.status)
} else {
// result.error is string
console.error(result.error, result.status)
}
// Text request
const textResult = await Fetch.text('https://example.com/page')
// Create responses manually
const success = Resolve.data({ id: 1 }, 201)
const error = Resolve.error('Not found', 404)EventEmitter - Type-Safe Events
import { EventEmitter } from '@vbyte/util/class'
interface AppEvents {
'user:login': { userId: string; timestamp: number }
'user:logout': string // just the userId
'data:update': [string, number] // spread as args
}
const events = new EventEmitter<AppEvents>()
// Subscribe
events.on('user:login', (payload) => {
console.log(payload.userId) // Type-safe access
})
// One-time handler
events.once('user:logout', (userId) => {
console.log(`Goodbye ${userId}`)
})
// Auto-unsubscribe after timeout
events.within('data:update', (key, value) => {
console.log(key, value)
}, 5000)
// Emit (fire and forget)
events.emit('user:login', { userId: '123', timestamp: Date.now() })
// Emit and wait for async handlers
await events.emitAsync('user:login', { userId: '456', timestamp: Date.now() })
// Wildcard handler
events.on('*', (eventName, payload) => {
console.log(`Event: ${eventName}`, payload)
})Mutex - Concurrency Control
import { Mutex } from '@vbyte/util/class'
const mutex = new Mutex(30_000) // 30s timeout
// Method 1: Manual lock/release
const release = await mutex.lock()
try {
await criticalSection()
} finally {
release()
}
// Method 2: Automatic release
const result = await mutex.acquire(async () => {
await criticalSection()
return 'done'
})Queue - Batch Processing
import { Queue } from '@vbyte/util/class'
const queue = new Queue<string, Response>({
batchSize: 10, // Process 10 items at a time
interval: 1000, // Wait 1s between batches
process: async (items) => {
const responses = await Promise.all(
items.map(url => fetch(url))
)
return responses
}
})
// Add items - returns promise that resolves when processed
const result = await queue.add('https://api.example.com/1')Flow - Async Control
import { retry, debounce, throttle, parallel } from '@vbyte/util/flow'
// Retry with exponential backoff
const data = await retry(
() => fetchUnreliableApi(),
{ attempts: 3, delay: 1000, backoff: 2 }
)
// Debounce function calls
const debouncedSearch = debounce(search, 300)
// Throttle function calls
const throttledUpdate = throttle(updateUI, 100)
// Parallel execution with concurrency limit
const results = await parallel(
urls.map(url => () => fetch(url)),
{ concurrency: 5 }
)Debug - Logging
import { create_debugger } from '@vbyte/util/debug'
const debug = create_debugger('myapp:auth')
debug('user logged in: %s', username)
debug.error('login failed: %O', error)
debug.warn('rate limit approaching')
// Performance timing
const end = debug.time('database-query')
await query()
end() // logs: "database-query: 45.23ms"Enable debug output:
# Node.js
DEBUG=myapp:* node app.js
# Browser
window.DEBUG = 'myapp:*'Result - Error Handling
import { wrap_promise, wrap_func, return_ok, return_err } from '@vbyte/util/result'
// Wrap async operations
const result = await wrap_promise(riskyAsyncOperation())
if (result.ok) {
console.log(result.data)
} else {
console.error(result.err)
}
// With timeout
const result = await wrap_promise(slowOperation(), 5000)
// Wrap sync functions
const safeParse = wrap_func(JSON.parse)
const result = safeParse(jsonString)Environment Support
Runtime Requirements
| Environment | Minimum Version | Notes |
|-------------|-----------------|-------|
| Node.js | 19+ | Required for crypto.getRandomValues |
| Chrome | 43+ | Full support |
| Firefox | 36+ | Full support |
| Safari | 10.1+ | Full support |
| Edge | 12+ | Full support |
Feature Compatibility
| Feature | Node.js | Browser | Fallback |
|---------|---------|---------|----------|
| random_bytes | 19+ (crypto.getRandomValues) | All modern | Math.random (insecure, warns) |
| create_debugger | All | All | No-op in production |
| performance.now | 8.5+ | All modern | Date.now() |
| fetch | 18+ (native) | All modern | Requires polyfill |
Bundle Formats
| Format | File | Use Case |
|--------|------|----------|
| ESM | dist/module.mjs | Modern bundlers (Vite, Rollup, webpack 5+) |
| CommonJS | dist/main.cjs | Node.js, older bundlers |
| IIFE | dist/script.js | Direct browser <script> tag (minified) |
TypeScript
- Minimum TypeScript version: 5.0+
- Strict mode compatible
- Full type definitions included
License
MIT
