Documentation Index
Fetch the complete documentation index at: https://docs.law4devs.eu/llms.txt
Use this file to discover all available pages before exploring further.
Exception hierarchy
All errors thrown by the SDK extend Law4DevsError, which itself extends the built-in Error. Use instanceof checks to handle specific error types.
Law4DevsError
├── NotFoundError (HTTP 404)
├── ValidationError (HTTP 422)
├── RateLimitError (HTTP 429)
└── ServerError (HTTP 5xx)
Every error class exposes a statusCode property with the underlying HTTP status code.
import {
Law4DevsError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError,
} from 'law4devs';
Basic try/catch
try {
const article = await client.articles.get('gdpr', 999);
console.log(article.title);
} catch (err) {
if (err instanceof NotFoundError) {
console.error(`Not found (${err.statusCode}): ${err.message}`);
} else if (err instanceof ValidationError) {
console.error(`Invalid request (${err.statusCode}): ${err.message}`);
} else if (err instanceof RateLimitError) {
console.error(`Rate limited (${err.statusCode}) — all retries exhausted`);
} else if (err instanceof ServerError) {
console.error(`Server error (${err.statusCode}) — all retries exhausted`);
} else if (err instanceof Law4DevsError) {
console.error(`API error (${err.statusCode}): ${err.message}`);
} else {
throw err; // network error or unexpected — re-throw
}
}
Auto-retry behaviour
The SDK automatically retries on RateLimitError (429) and ServerError (5xx) using exponential backoff with jitter. Only after all retries are exhausted is the error thrown to your code.
// Configure retry behaviour at construction time
const client = new Law4DevsClient({
maxRetries: 3, // default: 3 — set to 0 to disable retries
timeout: 30000, // ms — each individual attempt has this timeout
});
Timeouts are enforced via AbortController, so they apply per-attempt (not across all retries combined).
NotFoundError and ValidationError are never retried — they indicate client-side issues that will not resolve on retry.
TypeScript narrowing with a typed helper
Define a safeGet helper to return a typed result or a structured error without propagating exceptions:
import { Law4DevsClient, NotFoundError, Law4DevsError, Article } from 'law4devs';
type Result<T> =
| { ok: true; value: T }
| { ok: false; error: Law4DevsError };
async function safeGet<T>(fn: () => Promise<T>): Promise<Result<T>> {
try {
return { ok: true, value: await fn() };
} catch (err) {
if (err instanceof Law4DevsError) {
return { ok: false, error: err };
}
throw err; // unexpected — re-throw
}
}
// Usage
const result = await safeGet(() => client.articles.get('gdpr', 5));
if (result.ok) {
console.log(result.value.title); // TypeScript knows result.value is Article
} else {
if (result.error instanceof NotFoundError) {
console.log('Article does not exist');
} else {
console.error(`Unexpected error: ${result.error.message}`);
}
}
Handling errors inside for await
Errors thrown during iter() or iterDeadlines() are propagated out of the for await loop. Wrap the loop in try/catch to handle them:
try {
for await (const article of client.articles.iter('gdpr')) {
console.log(article.title);
}
} catch (err) {
if (err instanceof RateLimitError) {
console.error('Rate limit hit during iteration — consider reducing perPage or adding delays');
} else {
throw err;
}
}
Error reference
| Class | HTTP Status | When thrown | Retried? |
|---|
NotFoundError | 404 | Requested resource does not exist | No |
ValidationError | 422 | Invalid parameters or query | No |
RateLimitError | 429 | Too many requests | Yes |
ServerError | 5xx | Server-side error | Yes |
Law4DevsError | any | Base class — catch-all | Depends |
After all retries are exhausted, RateLimitError and ServerError are thrown normally. Always include these in your catch blocks for production code.