law4devs
v1.0.0
Published
Official TypeScript/JavaScript SDK for the Law4Devs EU Regulatory Compliance API
Maintainers
Readme
law4devs
Official TypeScript SDK for the Law4Devs API — structured EU regulatory compliance data for developers.
Features
- Full TypeScript types for all API resources
- Zero runtime dependencies (uses Node 18+ built-in
fetch) - Automatic pagination with
AsyncGenerator(iter()) - Automatic retry with exponential backoff on 429/5xx
- Dual CJS + ESM output
Installation
npm install law4devsQuick Start
import { Law4DevsClient } from 'law4devs';
const client = new Law4DevsClient();
// List all frameworks
const page = await client.frameworks.list();
console.log(page.data.map(f => f.slug));
// Get a specific framework
const gdpr = await client.frameworks.get('gdpr');
console.log(gdpr.name, gdpr.requirementCount);
// Iterate all articles in a framework (auto-pagination)
for await (const article of client.articles.iter('gdpr')) {
console.log(article.articleNumber, article.title);
}Authentication
No API key is required for public endpoints. To use an API key:
const client = new Law4DevsClient({ apiKey: 'your-key-here' });Configuration
const client = new Law4DevsClient({
baseUrl: 'https://api.law4devs.eu/v1', // default
apiKey: 'optional-key',
timeout: 30_000, // milliseconds, default 30s
maxRetries: 3, // default 3
});Resources
Frameworks
// List frameworks (paginated)
const page = await client.frameworks.list({ page: 1, perPage: 20 });
// Get framework detail
const fw = await client.frameworks.get('cra');
// Iterate all frameworks (auto-pagination)
for await (const fw of client.frameworks.iter()) {
console.log(fw.slug);
}Articles
// List articles in a framework
const page = await client.articles.list('gdpr', { page: 1, perPage: 20 });
// Get a specific article
const article = await client.articles.get('gdpr', 5);
// Get related articles
const related = await client.articles.related('gdpr', 5);
// Iterate all articles
for await (const article of client.articles.iter('gdpr')) {
console.log(article.articleNumber, article.title);
}Recitals
const page = await client.recitals.list('gdpr');
const recital = await client.recitals.get('gdpr', 1);
for await (const r of client.recitals.iter('gdpr')) { /* ... */ }Requirements
// All requirements
const page = await client.requirements.list();
// Filter by framework
const gdprReqs = await client.requirements.list({ frameworkSlug: 'gdpr' });
// Iterate
for await (const req of client.requirements.iter({ frameworkSlug: 'gdpr' })) {
console.log(req.requirementText);
}Tags
const page = await client.tags.list();
const tag = await client.tags.get('data-protection');
for await (const tag of client.tags.iter()) { /* ... */ }Compliance Deadlines
const page = await client.compliance.deadlines({ frameworkSlug: 'nis2' });
for await (const d of client.compliance.iterDeadlines({ frameworkSlug: 'nis2' })) {
console.log(d.deadlineDate, d.description);
}Annexes
const page = await client.annexes.list('cra');
const annex = await client.annexes.get('cra', 'I');
for await (const annex of client.annexes.iter('cra')) { /* ... */ }Search
const results = await client.search.query('data breach notification', {
framework: 'gdpr',
resultType: 'article',
});
for await (const result of client.search.iter('security requirements')) {
console.log(result.type, result.matchContext);
}Pagination
All list() methods return a Page<T> object:
const page = await client.frameworks.list({ page: 1, perPage: 10 });
console.log(page.meta.total); // total items
console.log(page.meta.pages); // total pages
console.log(page.links.next); // URL of next page, or null
console.log(page.data); // array of itemsFor automatic iteration, use iter():
for await (const item of client.frameworks.iter({ perPage: 50 })) {
// Automatically fetches next page when needed
}Error Handling
import { Law4DevsClient, NotFoundError, RateLimitError, ValidationError } from 'law4devs';
try {
const fw = await client.frameworks.get('unknown-slug');
} catch (err) {
if (err instanceof NotFoundError) {
console.error('Framework not found:', err.message);
} else if (err instanceof RateLimitError) {
console.error('Rate limited — will retry automatically');
} else if (err instanceof ValidationError) {
console.error('Bad request:', err.message, err.statusCode);
}
}Error classes: Law4DevsError (base), NotFoundError, ValidationError, RateLimitError, ServerError.
Available Frameworks
| Slug | Name | CELEX | Status |
|------|------|-------|--------|
| gdpr | General Data Protection Regulation | 32016R0679 | Active |
| nis2 | Network and Information Security Directive 2 | 32022L2555 | Active |
| cra | Cyber Resilience Act | 32024R2847 | Active |
| ai-act | Artificial Intelligence Act | 32024R1689 | Active |
| dora | Digital Operational Resilience Act | 32022R2554 | Active |
| dsa | Digital Services Act | 32022R2065 | Active |
| dma | Digital Markets Act | 32022R1925 | Active |
| eidas2 | eIDAS 2.0 | 32024R1183 | Active |
| data-act | Data Act | 32023R2854 | Active |
| data-governance-act | Data Governance Act | 32022R0868 | Active |
| eu-ai-liability | EU AI Liability Directive | — | Active |
| product-liability | Product Liability Directive | — | Active |
| eprivacy | ePrivacy Regulation | — | Active |
| psd3 | Payment Services Directive 3 | — | Active |
| micar | Markets in Crypto-Assets Regulation | 32023R1114 | Active |
| open-finance | Open Finance Framework | — | Active |
| fida | Financial Data Access | — | Active |
| nis1 | Network and Information Security Directive 1 | 32016L1148 | Superseded |
| csd-r | Cyber Security Delegated Regulation | — | Active |
License
MIT
