enrich.sh
v0.0.2
Published
Send JSON, get Parquet. Zero-dependency SDK for Enrich.sh — the serverless data ingestion pipeline.
Maintainers
Readme
enrich.sh
┌─────────────────────────────────────────────────┐
│ │
│ ███████╗███╗ ██╗██████╗ ██╗ ██████╗██╗ ██╗ │
│ ██╔════╝████╗ ██║██╔══██╗██║██╔════╝██║ ██║ │
│ █████╗ ██╔██╗ ██║██████╔╝██║██║ ███████║ │
│ ██╔══╝ ██║╚██╗██║██╔══██╗██║██║ ██╔══██║ │
│ ███████╗██║ ╚████║██║ ██║██║╚██████╗██║ ██║ │
│ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝ │
│ │
│ Serverless Data Ingestion Pipeline │
│ Your events → Parquet on R2 → DuckDB │
│ │
└─────────────────────────────────────────────────┘Official JavaScript SDK for Enrich.sh
Install
npm install enrich.shWorks in Node.js 18+, browsers, and edge runtimes (Deno, Bun, Workers).
Quick Start
┌──────────┐ track() ┌──────────┐ flush ┌──────────┐
│ Your │ ─────────────► │ SDK │ ──────────► │ Enrich │
│ App │ (buffered) │ Buffer │ (batched) │ API │
└──────────┘ └──────────┘ └────┬─────┘
│
┌────▼─────┐
│ R2 │
│ Parquet │
└────┬─────┘
│
┌────▼─────┐
│ DuckDB │
│ Query │
└──────────┘1 · Initialize
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_your_api_key')
// Create a stream
await enrich.createStream('clicks', { schema_mode: 'evolve' })
// Send events
enrich.track('clicks', { url: '/pricing', user_id: 'usr_42' })
// Query your data as Parquet
const urls = await enrich.query('clicks', { days: 7 })API
new Enrich(apiKey, options?)
| Option | Default | Description |
|-----------|---------------------|------------------------------|
| baseUrl | https://enrich.sh | API endpoint (custom domain) |
Ingestion
// Buffer events — SDK batches and flushes automatically
enrich.track('clicks', { url: '/home', user_id: 'usr_42' })
// Send immediately (bypasses buffer)
await enrich.ingest('clicks', [
{ url: '/home', user_id: 'usr_42' },
{ url: '/pricing', user_id: 'usr_77' },
])
// Flush before tab close (survives page unload)
enrich.beacon()
// Force flush buffered events
await enrich.flush()
// Cleanup on shutdown
await enrich.destroy()Streams
// List all streams
const streams = await enrich.listStreams()
// Create a stream
await enrich.createStream('purchases', {
schema_mode: 'strict',
fields: {
amount: { type: 'float64' },
currency: { type: 'string' },
},
})
// Get stream details
const stream = await enrich.getStream('purchases')
// Update stream config
await enrich.updateStream('purchases', { schema_mode: 'evolve' })
// Delete a stream
await enrich.deleteStream('old-stream')Query
// Get signed Parquet URLs → pass to DuckDB
const urls = await enrich.query('clicks', { days: 30 })
await conn.query(`SELECT * FROM read_parquet(${JSON.stringify(urls)})`)
// Get URLs + file metadata
const detailed = await enrich.queryDetailed('clicks', { days: 7 })
console.log(`${detailed.file_count} files, expires ${detailed.expires_at}`)Monitoring
// Usage stats
const stats = await enrich.usage({ start: '2026-02-01' })
// Recent errors
const errs = await enrich.errors({ limit: 20 })
// Dead Letter Queue
const rejected = await enrich.dlq('purchases', { days: 7 })
// Schema change history
const changes = await enrich.schemaEvents('purchases')
// Available enrichment templates
const templates = await enrich.templates()Connect
// Get S3 credentials for direct warehouse access
const creds = await enrich.connect()
// → { endpoint, bucket, access_key_id, secret_access_key, sql }Examples
Browser — Clickstream
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_xxx')
document.addEventListener('click', (e) => {
enrich.track('clicks', {
tag: e.target.tagName,
id: e.target.id,
path: location.pathname,
})
})
window.addEventListener('beforeunload', () => enrich.beacon())Node.js — Express Middleware
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_xxx')
app.use((req, res, next) => {
const start = Date.now()
res.on('finish', () => {
enrich.track('api_logs', {
method: req.method,
path: req.path,
status: res.statusCode,
duration_ms: Date.now() - start,
})
})
next()
})
process.on('SIGTERM', () => enrich.destroy())DuckDB — Analytics
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_xxx')
const urls = await enrich.query('clicks', { days: 30 })
const result = await conn.query(`
SELECT path, COUNT(*) as hits
FROM read_parquet(${JSON.stringify(urls)})
GROUP BY path
ORDER BY hits DESC
`)Specs
| Spec | Value |
|------|-------|
| Package size | < 4 KB |
| Dependencies | 0 |
| Runtime | Node 18+, Browsers, Edge |
| Transport | HTTPS |
| Auth | Bearer token (sk_live_* / sk_test_*) |
| Output format | Apache Parquet |
| Max request size | 1 MB |
License
MIT — Enrich.sh
