{"_id":"sqlite.do","name":"sqlite.do","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"sqlite.do","version":"0.0.1","description":"High-level API and utilities for distributed SQLite on Cloudflare","type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","test":"vitest run","test:watch":"vitest"},"keywords":["sqlite","cloudflare","durable-objects"],"author":{"name":"Nathan Clevenger"},"license":"MIT","dependencies":{"@dotdo/sqlite-core":"0.0.1"},"devDependencies":{"typescript":"^5.3.3","vitest":"^2.0.0"},"_id":"sqlite.do@0.0.1","gitHead":"77fd4d165205fb7aae603a74d207c71b7b8a45c2","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-irjO7GoGY5ZbLcUvXI92nngjNVgKrT8GfBKBuEROyvdfFIaZAyQpvGi6oai17whHG2GJwZ1P1gvTNE6/DAr8lg==","shasum":"c43ae7b3e7665b84f23938727b0bcfee683cc85f","tarball":"https://registry.npmjs.org/sqlite.do/-/sqlite.do-0.0.1.tgz","fileCount":77,"unpackedSize":599608,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIC3USzt3dutzoak9rJTB/vbz0uWI0CWzFEBj0Sf9RzW1AiBhqFNdIxrAVQAM7dVBxtaMDoUz1NrycDOpeg9KWBHOcw=="}]},"_npmUser":{"name":"nathanclevenger","email":"nateclev@gmail.com"},"directories":{},"maintainers":[{"name":"nathanclevenger","email":"nateclev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sqlite.do_0.0.1_1769079774016_0.5114809768775483"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-22T11:02:53.960Z","0.0.1":"2026-01-22T11:02:54.169Z","modified":"2026-01-22T11:02:54.327Z"},"maintainers":[{"name":"nathanclevenger","email":"nateclev@gmail.com"}],"description":"High-level API and utilities for distributed SQLite on Cloudflare","keywords":["sqlite","cloudflare","durable-objects"],"author":{"name":"Nathan Clevenger"},"license":"MIT","readme":"# sqlite.do\n\n[![npm version](https://img.shields.io/npm/v/sqlite.do.svg)](https://www.npmjs.com/package/sqlite.do)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)\n\n**REST API and admin tools for edge SQLite.**\n\nYou need HTTP endpoints for your databases. You need admin tools to manage them. You need monitoring to keep them healthy.\n\n**Here's everything you need.**\n\n## The Problem\n\nYou've deployed your Durable Object databases. Now what? You need REST endpoints for external integrations. Admin APIs for management. Health checks for monitoring. Building all this from scratch is tedious.\n\n## The Solution\n\n`sqlite.do` provides a complete REST API layer and admin toolkit. Deploy once, manage everything.\n\n```bash\n# Query via REST\ncurl https://sqlite.do/api/my-database/query \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -d '{\"sql\": \"SELECT * FROM users LIMIT 10\"}'\n\n# Admin operations\ncurl https://sqlite.do/admin/my-database/stats\n```\n\nHTTP endpoints. Admin tools. Monitoring. All included.\n\n## Installation\n\n```bash\nnpm install sqlite.do\n```\n\n## REST API\n\n### Query Endpoint\n\nExecute SQL queries via HTTP:\n\n```bash\nPOST /api/{database}/query\nAuthorization: Bearer <token>\nContent-Type: application/json\n\n{\n  \"sql\": \"SELECT * FROM users WHERE active = ?\",\n  \"params\": [true]\n}\n```\n\nResponse:\n\n```json\n{\n  \"columns\": [\"id\", \"email\", \"active\", \"created_at\"],\n  \"rows\": [\n    { \"id\": 1, \"email\": \"alice@example.com\", \"active\": true, \"created_at\": \"2024-01-15\" }\n  ],\n  \"rowsAffected\": 0,\n  \"lastInsertRowid\": null,\n  \"timing\": { \"queryMs\": 2, \"totalMs\": 15 }\n}\n```\n\n### Execute Endpoint\n\nFor write operations:\n\n```bash\nPOST /api/{database}/execute\nAuthorization: Bearer <token>\nContent-Type: application/json\n\n{\n  \"sql\": \"INSERT INTO users (email, name) VALUES (?, ?)\",\n  \"params\": [\"bob@example.com\", \"Bob\"]\n}\n```\n\nResponse:\n\n```json\n{\n  \"rowsAffected\": 1,\n  \"lastInsertRowid\": 42,\n  \"timing\": { \"queryMs\": 5, \"totalMs\": 20 }\n}\n```\n\n### Batch Endpoint\n\nMultiple statements in one request:\n\n```bash\nPOST /api/{database}/batch\nAuthorization: Bearer <token>\nContent-Type: application/json\n\n{\n  \"statements\": [\n    { \"sql\": \"INSERT INTO logs (event) VALUES (?)\", \"params\": [\"user_created\"] },\n    { \"sql\": \"UPDATE stats SET count = count + 1 WHERE name = ?\", \"params\": [\"users\"] },\n    { \"sql\": \"SELECT count FROM stats WHERE name = ?\", \"params\": [\"users\"] }\n  ]\n}\n```\n\n### Transaction Endpoint\n\nACID transactions via REST:\n\n```bash\nPOST /api/{database}/transaction\nAuthorization: Bearer <token>\nContent-Type: application/json\n\n{\n  \"mode\": \"write\",\n  \"statements\": [\n    { \"sql\": \"INSERT INTO orders (user_id, total) VALUES (?, ?)\", \"params\": [1, 99.99] },\n    { \"sql\": \"UPDATE users SET order_count = order_count + 1 WHERE id = ?\", \"params\": [1] }\n  ]\n}\n```\n\n## Admin API\n\n### Database Management\n\n```bash\n# List all databases\nGET /admin/databases\nAuthorization: Bearer <admin-token>\n\n# Get database info\nGET /admin/{database}/info\n\n# Get database stats\nGET /admin/{database}/stats\n\n# Export database\nGET /admin/{database}/export\nAccept: application/x-sqlite3\n\n# Delete database\nDELETE /admin/{database}\n```\n\n### Schema Operations\n\n```bash\n# Get schema\nGET /admin/{database}/schema\n\n# Get table info\nGET /admin/{database}/tables/{table}\n\n# Get indexes\nGET /admin/{database}/indexes\n```\n\n### Health & Monitoring\n\n```bash\n# Health check\nGET /admin/{database}/health\n\n# Response:\n{\n  \"status\": \"healthy\",\n  \"database\": \"my-database\",\n  \"stats\": {\n    \"tables\": 5,\n    \"rows\": 12450,\n    \"sizeBytes\": 524288,\n    \"walSizeBytes\": 8192\n  },\n  \"sync\": {\n    \"localLsn\": 1234,\n    \"lastSyncTime\": \"2024-01-15T10:30:00Z\",\n    \"pendingFrames\": 0\n  }\n}\n```\n\n## Quick Start\n\n### Deploy the API\n\n```typescript\nimport { createSqliteDoApp } from 'sqlite.do'\n\nconst app = createSqliteDoApp({\n  // Authentication\n  authToken: env.AUTH_TOKEN,\n  adminToken: env.ADMIN_TOKEN,\n\n  // Rate limiting\n  rateLimit: {\n    queries: 1000,   // per minute\n    writes: 100      // per minute\n  },\n\n  // CORS\n  cors: {\n    origins: ['https://myapp.com'],\n    methods: ['GET', 'POST']\n  }\n})\n\nexport default app\n```\n\n### Wrangler Configuration\n\n```toml\n# wrangler.toml\nname = \"sqlite-api\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2024-01-01\"\n\n[durable_objects]\nbindings = [\n  { name = \"DATABASE\", class_name = \"DatabaseDO\" }\n]\n\n[vars]\nAUTH_TOKEN = \"your-auth-token\"\nADMIN_TOKEN = \"your-admin-token\"\n```\n\n### Client Usage\n\n```typescript\nimport { SqliteDoClient } from 'sqlite.do'\n\nconst client = new SqliteDoClient({\n  baseUrl: 'https://sqlite.do',\n  database: 'my-database',\n  authToken: process.env.AUTH_TOKEN\n})\n\n// Query\nconst users = await client.query('SELECT * FROM users WHERE active = ?', [true])\n\n// Execute\nconst result = await client.execute(\n  'INSERT INTO users (email) VALUES (?)',\n  ['new@example.com']\n)\n\n// Batch\nconst results = await client.batch([\n  { sql: 'INSERT INTO logs (msg) VALUES (?)', params: ['event1'] },\n  { sql: 'SELECT COUNT(*) FROM logs' }\n])\n\n// Transaction\nawait client.transaction([\n  { sql: 'UPDATE accounts SET balance = balance - ?', params: [100] },\n  { sql: 'INSERT INTO transfers (amount) VALUES (?)', params: [100] }\n])\n```\n\n## Authentication\n\n### Bearer Token\n\n```typescript\nconst app = createSqliteDoApp({\n  authToken: env.AUTH_TOKEN\n})\n\n// Requests must include:\n// Authorization: Bearer <token>\n```\n\n### Per-Database Tokens\n\n```typescript\nconst app = createSqliteDoApp({\n  authStrategy: 'per-database',\n  getToken: async (database: string) => {\n    return env[`TOKEN_${database.toUpperCase()}`]\n  }\n})\n```\n\n### Custom Authentication\n\n```typescript\nconst app = createSqliteDoApp({\n  authenticate: async (request: Request) => {\n    const token = request.headers.get('Authorization')?.replace('Bearer ', '')\n\n    // Your authentication logic\n    const user = await validateToken(token)\n\n    if (!user) {\n      return { authenticated: false, error: 'Invalid token' }\n    }\n\n    return {\n      authenticated: true,\n      user,\n      permissions: user.role === 'admin' ? ['read', 'write', 'admin'] : ['read']\n    }\n  }\n})\n```\n\n## Rate Limiting\n\n```typescript\nconst app = createSqliteDoApp({\n  rateLimit: {\n    // Queries per minute\n    queries: 1000,\n\n    // Writes per minute\n    writes: 100,\n\n    // By IP or token\n    keyBy: 'token',  // or 'ip'\n\n    // Custom key function\n    getKey: (request) => {\n      return request.headers.get('X-API-Key') || 'anonymous'\n    }\n  }\n})\n```\n\n## Monitoring & Observability\n\n### Request Logging\n\n```typescript\nconst app = createSqliteDoApp({\n  logging: {\n    enabled: true,\n    level: 'info',\n    includeQuery: true,      // Log SQL queries\n    includeTiming: true,     // Log execution times\n    destination: 'console'   // or 'logpush'\n  }\n})\n```\n\n### Metrics\n\n```typescript\nconst app = createSqliteDoApp({\n  metrics: {\n    enabled: true,\n    endpoint: '/metrics',    // Prometheus-compatible\n    include: ['queries', 'writes', 'errors', 'latency']\n  }\n})\n\n// GET /metrics\n// sqlite_queries_total{database=\"mydb\"} 12345\n// sqlite_query_latency_seconds{database=\"mydb\",quantile=\"0.99\"} 0.015\n```\n\n### Webhooks\n\n```typescript\nconst app = createSqliteDoApp({\n  webhooks: {\n    onError: 'https://myapp.com/webhooks/sqlite-error',\n    onSlowQuery: {\n      url: 'https://myapp.com/webhooks/slow-query',\n      thresholdMs: 100\n    }\n  }\n})\n```\n\n## API Reference\n\n### REST Endpoints\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `POST` | `/api/{db}/query` | Execute SELECT query |\n| `POST` | `/api/{db}/execute` | Execute write operation |\n| `POST` | `/api/{db}/batch` | Execute multiple statements |\n| `POST` | `/api/{db}/transaction` | Execute transaction |\n| `GET` | `/admin/databases` | List databases |\n| `GET` | `/admin/{db}/info` | Database info |\n| `GET` | `/admin/{db}/stats` | Database statistics |\n| `GET` | `/admin/{db}/schema` | Database schema |\n| `GET` | `/admin/{db}/health` | Health check |\n| `GET` | `/admin/{db}/export` | Export database |\n| `DELETE` | `/admin/{db}` | Delete database |\n\n### Error Responses\n\n```json\n{\n  \"error\": {\n    \"code\": \"SQLITE_CONSTRAINT_UNIQUE\",\n    \"message\": \"UNIQUE constraint failed: users.email\",\n    \"details\": {\n      \"table\": \"users\",\n      \"column\": \"email\"\n    }\n  }\n}\n```\n\n### Status Codes\n\n| Code | Meaning |\n|------|---------|\n| `200` | Success |\n| `400` | Bad request (invalid SQL, missing params) |\n| `401` | Unauthorized |\n| `403` | Forbidden (insufficient permissions) |\n| `404` | Database not found |\n| `429` | Rate limited |\n| `500` | Server error |\n\n## TypeScript SDK\n\nFull type safety for API responses:\n\n```typescript\nimport { SqliteDoClient, QueryResult, ExecuteResult } from 'sqlite.do'\n\ninterface User {\n  id: number\n  email: string\n  name: string\n}\n\nconst client = new SqliteDoClient({ ... })\n\n// Typed results\nconst result = await client.query<User>('SELECT * FROM users WHERE id = ?', [1])\nconst user: User = result.rows[0]\n\n// Type inference\nconst users = await client.query<User>('SELECT * FROM users')\nusers.rows.forEach(user => {\n  console.log(user.email)  // TypeScript knows this is string\n})\n```\n\n## Links\n\n- [GitHub Repository](https://github.com/dotdo-io/sqlite)\n- [API Documentation](https://sqlite.do/docs/api)\n- [Authentication Guide](https://sqlite.do/docs/auth)\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-0e71d9ffbfea15b3b6b251766768e167"}