kotadb-client
Version:
TypeScript/JavaScript client for KotaDB - PostgreSQL-level ease of use for document database
450 lines (368 loc) • 10.7 kB
Markdown
# KotaDB TypeScript/JavaScript Client
A simple, PostgreSQL-level easy-to-use TypeScript/JavaScript client for KotaDB with built-in type safety and validation.
## Features
- **Type Safety**: Validated types prevent common errors before they reach the server
- **Security**: Protection against path injection and other client-side attacks
- **Builder Patterns**: Fluent APIs with IntelliSense-friendly construction
- **Consistency**: Same patterns as Python client for consistent developer experience
- **Backward Compatible**: All existing code continues to work unchanged
## Installation
```bash
npm install kotadb-client
```
## Quick Start
### Basic Usage (TypeScript)
```typescript
import { KotaDB } from 'kotadb-client';
// Connect to KotaDB
const db = new KotaDB({ url: 'http://localhost:8080' });
// Insert a document
const docId = await db.insert({
path: '/notes/meeting.md',
title: 'Team Meeting Notes',
content: 'Discussed project roadmap and next steps...',
tags: ['work', 'meeting', 'planning']
});
// Search for documents
const results = await db.query('project roadmap');
for (const result of results.results) {
console.log(`Found: ${result.document.title} (score: ${result.score})`);
}
// Get a specific document
const doc = await db.get(docId);
console.log(`Document: ${doc.title}`);
// Update a document
const updatedDoc = await db.update(docId, {
content: 'Updated meeting notes with action items...'
});
// Delete a document
await db.delete(docId);
```
### Type-Safe Usage with Builders (Recommended)
```typescript
import {
KotaDB,
DocumentBuilder,
QueryBuilder,
ValidatedPath,
ValidatedTitle
} from 'kotadb-client';
const db = new KotaDB({ url: 'http://localhost:8080' });
// Create document with type safety and validation
const docId = await db.insertWithBuilder(
new DocumentBuilder()
.path("/notes/meeting.md") // Validates path safety
.title("Team Meeting Notes") // Ensures non-empty
.content("Safe content") // Validates content
.addTag("work") // Validates tag format
.addTag("meeting")
.addMetadata("priority", "high")
);
// Type-safe search queries
const results = await db.queryWithBuilder(
new QueryBuilder()
.text("project roadmap")
.limit(10)
.tagFilter("work")
.pathFilter("/notes/*")
);
// Semantic search with validation
const semanticResults = await db.semanticSearchWithBuilder(
new QueryBuilder()
.text("machine learning concepts")
.limit(5)
.semanticWeight(0.7) // Validates 0.0-1.0 range
);
```
### JavaScript (CommonJS)
```javascript
const { KotaDB } = require('kotadb-client');
// Connect to KotaDB
const db = new KotaDB({ url: 'http://localhost:8080' });
// Use with async/await or promises
db.query('search term')
.then(results => {
console.log(`Found ${results.total_count} results`);
})
.catch(error => {
console.error('Search failed:', error);
});
```
### JavaScript (ES Modules)
```javascript
import { KotaDB } from 'kotadb-client';
const db = new KotaDB({ url: 'http://localhost:8080' });
const results = await db.query('search term');
```
## Type Safety and Validation
### Validated Types
The client provides validated types that ensure data integrity and security:
```typescript
import {
ValidatedPath,
ValidatedDocumentId,
ValidatedTitle,
ValidationError
} from 'kotadb-client';
// Safe path validation
try {
const path = new ValidatedPath("/notes/meeting.md");
console.log(path.asStr()); // "/notes/meeting.md"
} catch (error) {
if (error instanceof ValidationError) {
console.error("Invalid path:", error.message);
}
}
// Prevents directory traversal attacks
try {
new ValidatedPath("../../../etc/passwd"); // Throws ValidationError
} catch (error) {
console.log("Security threat blocked!");
}
// Document ID validation
const docId = ValidatedDocumentId.new(); // Generates valid UUID
const existingId = ValidatedDocumentId.parse("123e4567-e89b-12d3-a456-426614174000");
// Title validation
const title = new ValidatedTitle("My Document"); // Ensures non-empty, length limits
```
### Builder Patterns
Use builders for fluent, validated construction:
```typescript
import { DocumentBuilder, QueryBuilder, UpdateBuilder } from 'kotadb-client';
// Document builder with validation at each step
const document = new DocumentBuilder()
.path("/documents/report.md") // Validates path security
.title("Quarterly Report") // Validates non-empty title
.content("Report content here...") // Accepts string or byte array
.addTag("business") // Validates tag format
.addTag("quarterly")
.addMetadata("author", "jane.doe")
.addMetadata("department", "finance")
.autoId() // Generates secure UUID
.build();
// Query builder with parameter validation
const searchParams = new QueryBuilder()
.text("quarterly business") // Validates search query
.limit(25) // Validates positive numbers
.offset(50) // Validates non-negative
.semanticWeight(0.8) // Validates 0.0-1.0 range
.tagFilter("business") // Validates tag format
.pathFilter("/documents/*") // Path pattern filter
.build();
// Update builder for safe document modifications
const updates = new UpdateBuilder()
.title("Updated Quarterly Report") // Validates title
.addTag("updated") // Validates and merges tags
.removeTag("draft") // Safe tag removal
.addMetadata("revised_by", "john.doe") // Metadata updates
.build();
```
### Security Features
Built-in protection against common attacks:
```typescript
// Path traversal protection
try {
new DocumentBuilder().path("../../../etc/passwd"); // Blocked
} catch (error) {
console.log("Directory traversal blocked");
}
// Null byte injection protection
try {
new DocumentBuilder().path("/file\x00.txt"); // Blocked
} catch (error) {
console.log("Null byte injection blocked");
}
// Reserved name protection (Windows compatibility)
try {
new DocumentBuilder().path("CON.txt"); // Blocked
} catch (error) {
console.log("Reserved filename blocked");
}
// Input validation
try {
new QueryBuilder().limit(-1); // Blocked
new QueryBuilder().semanticWeight(1.5); // Blocked
new DocumentBuilder().addTag("invalid@tag"); // Blocked
} catch (error) {
console.log("Invalid input blocked");
}
```
## Connection Options
### Environment Variable
```bash
export KOTADB_URL="http://localhost:8080"
```
```typescript
// Will use KOTADB_URL automatically
const db = new KotaDB();
```
### Connection String
```typescript
// PostgreSQL-style connection string
const db = new KotaDB({ url: 'kotadb://localhost:8080/myapp' });
// Direct HTTP URL
const db = new KotaDB({ url: 'http://localhost:8080' });
```
### Advanced Configuration
```typescript
const db = new KotaDB({
url: 'http://localhost:8080',
timeout: 30000, // 30 second timeout
retries: 3, // 3 retry attempts
headers: { // Custom headers
'Authorization': 'Bearer token',
'X-Custom-Header': 'value'
}
});
```
## Search Options
### Text Search
```typescript
const results = await db.query('rust programming patterns', {
limit: 10,
offset: 0
});
```
### Semantic Search
```typescript
const results = await db.semanticSearch('machine learning concepts', {
limit: 5,
model: 'all-MiniLM-L6-v2'
});
```
### Hybrid Search
```typescript
const results = await db.hybridSearch('database optimization', {
limit: 10,
semantic_weight: 0.7 // 70% semantic, 30% text
});
```
## Document Operations
### Create Document
```typescript
const docId = await db.insert({
path: '/docs/guide.md',
title: 'User Guide',
content: 'How to use the system...',
tags: ['documentation', 'guide'],
metadata: { author: 'jane@example.com' }
});
```
### List Documents
```typescript
// Get all documents
const allDocs = await db.listAll();
// With pagination
const docs = await db.listAll({ limit: 50, offset: 100 });
```
### Database Health
```typescript
// Check health
const health = await db.health();
console.log(`Status: ${health.status}`);
// Get statistics
const stats = await db.stats();
console.log(`Document count: ${stats.document_count}`);
```
## Error Handling
```typescript
import {
KotaDBError,
NotFoundError,
ConnectionError,
ValidationError
} from 'kotadb-client';
try {
const doc = await db.get('non-existent-id');
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation failed: ${error.message}`);
} else if (error instanceof NotFoundError) {
console.log('Document not found');
} else if (error instanceof ConnectionError) {
console.log('Failed to connect to database');
} else if (error instanceof KotaDBError) {
console.log(`Database error: ${error.message}`);
} else {
console.log(`Unexpected error: ${error}`);
}
}
// Builder validation errors
try {
const builder = new DocumentBuilder()
.path("../../../etc/passwd") // Invalid path
.title("") // Empty title
.build();
} catch (error) {
if (error instanceof ValidationError) {
console.log("Input validation failed:", error.message);
// Handle validation error appropriately
}
}
```
## Type Definitions
### Document
```typescript
interface Document {
id: string;
path: string;
title: string;
content: string;
tags: string[];
created_at: string;
updated_at: string;
size: number;
metadata?: Record<string, any>;
}
```
### SearchResult
```typescript
interface SearchResult {
document: Document;
score: number;
content_preview: string;
}
```
### QueryResult
```typescript
interface QueryResult {
results: SearchResult[];
total_count: number;
query_time_ms: number;
}
```
## Browser Support
This client works in both Node.js and modern browsers. For browser usage:
```html
<!-- Using a CDN (once published) -->
<script src="https://unpkg.com/kotadb-client@latest/dist/index.js"></script>
<script>
const db = new KotaDB.default({ url: 'http://localhost:8080' });
// Use the client...
</script>
```
## Development
### Building
```bash
npm run build
```
### Testing
```bash
npm test
```
### Linting
```bash
npm run lint
npm run lint:fix
```
### Formatting
```bash
npm run format
```
## License
MIT License - see LICENSE file for details.
## Contributing
See CONTRIBUTING.md for contribution guidelines.
## Support
- GitHub Issues: https://github.com/jayminwest/kota-db/issues
- Documentation: https://github.com/jayminwest/kota-db/docs