Skip to content

Initial Release v1.0.0

Choose a tag to compare

@grab-dev grab-dev released this 23 Jun 23:14
· 13 commits to main since this release
b6ee7d7

Grab.js v1.0.0 - Initial Release

Zero-dependency HTTP client built from real-world experience handling thousands of API requests in production environments.

Features

  • Smart retries with exponential backoff
  • Response caching with ETag support
  • Circuit breaker for fault tolerance
  • Request deduplication prevents duplicate requests
  • Auth-aware cache prevents user data leakage
  • Priority hints for modern browsers
  • HTTP/2 push hint processing
  • Interceptors for request, response, and error handling

Files

  • grab.min.js - Production minified version (16KB)
  • Grab.js - Development version with comments (36KB)
  • grab.d.ts - TypeScript definitions
  • Complete test suite covering real-world scenarios

Installation

CDN:

<script src="https://cdn.jsdelivr.net/gh/grab-dev/grab-js@1.0.0/dist/grab.min.js"></script>
<script>
    const api = new Grab({ baseUrl: 'https://api.example.com' });
    const response = await api.get('/users');
    console.log(response.data);
</script>

Direct Download:

curl -O https://github.com/grab-dev/grab-js/releases/download/v1.0.0/grab.min.js

ES Modules:

import { Grab } from './src/Grab.js';
const api = new Grab();

Use Cases

Constrained environments where you need reliability without complexity:

  • No npm/webpack required
  • Works in legacy systems
  • No external dependencies
  • Vanilla JavaScript (ES6+)

Enterprise patterns included:

  • Circuit breakers prevent cascade failures
  • ETags reduce bandwidth usage
  • Request deduplication improves performance
  • Auth-aware caching prevents security issues

Configuration

const api = new Grab({
    baseUrl: 'https://api.example.com',
    timeout: 30000,
    headers: { 'Authorization': 'Bearer token' },
cache: {
    enabled: true,
    ttl: 5 * 60 * 1000,  // 5 minutes
    maxSize: 100
},

retry: {
    attempts: 3,
    delay: (attempt) =&gt; Math.min(1000 * Math.pow(2, attempt - 1), 30000),
    condition: (error) =&gt; error.status &gt;= 500
},

circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 60000
}

});

// Add interceptors
api.use({
request: (config) => {
config.headers.Timestamp = Date.now();
return config;
},
error: (error) => {
if (error.status === 401) {
window.location.href = '/login';
}
throw error;
}
});