ai-database 0.1.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -0
- package/CHANGELOG.md +9 -0
- package/README.md +381 -68
- package/TESTING.md +410 -0
- package/TEST_SUMMARY.md +250 -0
- package/TODO.md +128 -0
- package/dist/ai-promise-db.d.ts +370 -0
- package/dist/ai-promise-db.d.ts.map +1 -0
- package/dist/ai-promise-db.js +839 -0
- package/dist/ai-promise-db.js.map +1 -0
- package/dist/authorization.d.ts +531 -0
- package/dist/authorization.d.ts.map +1 -0
- package/dist/authorization.js +632 -0
- package/dist/authorization.js.map +1 -0
- package/dist/durable-clickhouse.d.ts +193 -0
- package/dist/durable-clickhouse.d.ts.map +1 -0
- package/dist/durable-clickhouse.js +422 -0
- package/dist/durable-clickhouse.js.map +1 -0
- package/dist/durable-promise.d.ts +182 -0
- package/dist/durable-promise.d.ts.map +1 -0
- package/dist/durable-promise.js +409 -0
- package/dist/durable-promise.js.map +1 -0
- package/dist/execution-queue.d.ts +239 -0
- package/dist/execution-queue.d.ts.map +1 -0
- package/dist/execution-queue.js +400 -0
- package/dist/execution-queue.js.map +1 -0
- package/dist/index.d.ts +50 -191
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -462
- package/dist/index.js.map +1 -0
- package/dist/linguistic.d.ts +115 -0
- package/dist/linguistic.d.ts.map +1 -0
- package/dist/linguistic.js +379 -0
- package/dist/linguistic.js.map +1 -0
- package/dist/memory-provider.d.ts +304 -0
- package/dist/memory-provider.d.ts.map +1 -0
- package/dist/memory-provider.js +785 -0
- package/dist/memory-provider.js.map +1 -0
- package/dist/schema.d.ts +899 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +1165 -0
- package/dist/schema.js.map +1 -0
- package/dist/tests.d.ts +107 -0
- package/dist/tests.d.ts.map +1 -0
- package/dist/tests.js +568 -0
- package/dist/tests.js.map +1 -0
- package/dist/types.d.ts +972 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +126 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -37
- package/src/ai-promise-db.ts +1243 -0
- package/src/authorization.ts +1102 -0
- package/src/durable-clickhouse.ts +596 -0
- package/src/durable-promise.ts +582 -0
- package/src/execution-queue.ts +608 -0
- package/src/index.test.ts +868 -0
- package/src/index.ts +337 -0
- package/src/linguistic.ts +404 -0
- package/src/memory-provider.test.ts +1036 -0
- package/src/memory-provider.ts +1119 -0
- package/src/schema.test.ts +1254 -0
- package/src/schema.ts +2296 -0
- package/src/tests.ts +725 -0
- package/src/types.ts +1177 -0
- package/test/README.md +153 -0
- package/test/edge-cases.test.ts +646 -0
- package/test/provider-resolution.test.ts +402 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +19 -0
- package/dist/index.d.mts +0 -195
- package/dist/index.mjs +0 -430
package/TESTING.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# Testing Guide for ai-database
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Run all tests
|
|
7
|
+
pnpm test
|
|
8
|
+
|
|
9
|
+
# Run once (non-watch mode)
|
|
10
|
+
pnpm test run
|
|
11
|
+
|
|
12
|
+
# Run specific test file
|
|
13
|
+
pnpm test src/schema.test.ts
|
|
14
|
+
|
|
15
|
+
# Build and test together
|
|
16
|
+
pnpm build && pnpm test run
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Test Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
ai-database/
|
|
23
|
+
├── src/
|
|
24
|
+
│ ├── index.test.ts # Integration tests (31 tests)
|
|
25
|
+
│ ├── memory-provider.test.ts # Provider tests (40 tests)
|
|
26
|
+
│ └── schema.test.ts # Schema parsing (22 tests)
|
|
27
|
+
├── test/
|
|
28
|
+
│ ├── edge-cases.test.ts # Edge cases (43 tests)
|
|
29
|
+
│ ├── provider-resolution.test.ts # URL parsing (38 tests)
|
|
30
|
+
│ └── README.md # Test documentation
|
|
31
|
+
├── vitest.config.ts # Test configuration
|
|
32
|
+
├── TEST_SUMMARY.md # Comprehensive summary
|
|
33
|
+
└── TESTING.md # This file
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Total**: 174 tests across 5 files, ~2,600 lines of test code
|
|
37
|
+
|
|
38
|
+
## Test Categories
|
|
39
|
+
|
|
40
|
+
### Unit Tests
|
|
41
|
+
- `src/schema.test.ts` - Schema parsing and validation
|
|
42
|
+
- `src/memory-provider.test.ts` - Provider implementation
|
|
43
|
+
|
|
44
|
+
### Integration Tests
|
|
45
|
+
- `src/index.test.ts` - Full DB API with typed operations
|
|
46
|
+
|
|
47
|
+
### System Tests
|
|
48
|
+
- `test/provider-resolution.test.ts` - DATABASE_URL parsing
|
|
49
|
+
- `test/edge-cases.test.ts` - Boundary conditions and errors
|
|
50
|
+
|
|
51
|
+
## Writing New Tests
|
|
52
|
+
|
|
53
|
+
### Basic Test Pattern
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
57
|
+
import { DB, setProvider, createMemoryProvider } from '../src/index.js'
|
|
58
|
+
|
|
59
|
+
describe('feature name', () => {
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
// Reset state for each test
|
|
62
|
+
setProvider(createMemoryProvider())
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('does something', async () => {
|
|
66
|
+
const schema = {
|
|
67
|
+
User: { name: 'string' },
|
|
68
|
+
} as const
|
|
69
|
+
|
|
70
|
+
const db = DB(schema)
|
|
71
|
+
|
|
72
|
+
const user = await db.User.create('id', { name: 'Test' })
|
|
73
|
+
|
|
74
|
+
expect(user.name).toBe('Test')
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Testing Schemas
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { parseSchema } from '../src/schema.js'
|
|
83
|
+
import type { DatabaseSchema } from '../src/schema.js'
|
|
84
|
+
|
|
85
|
+
it('parses schema correctly', () => {
|
|
86
|
+
const schema: DatabaseSchema = {
|
|
87
|
+
Post: {
|
|
88
|
+
title: 'string',
|
|
89
|
+
author: 'Author.posts',
|
|
90
|
+
},
|
|
91
|
+
Author: {
|
|
92
|
+
name: 'string',
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const parsed = parseSchema(schema)
|
|
97
|
+
|
|
98
|
+
expect(parsed.entities.size).toBe(2)
|
|
99
|
+
|
|
100
|
+
const author = parsed.entities.get('Author')
|
|
101
|
+
expect(author!.fields.has('posts')).toBe(true) // Auto-created backref
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Testing CRUD Operations
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
it('creates and retrieves entity', async () => {
|
|
109
|
+
const db = DB(schema)
|
|
110
|
+
|
|
111
|
+
// Create
|
|
112
|
+
const created = await db.User.create('john', {
|
|
113
|
+
name: 'John',
|
|
114
|
+
email: 'john@example.com',
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
expect(created.$id).toBe('john')
|
|
118
|
+
|
|
119
|
+
// Get
|
|
120
|
+
const retrieved = await db.User.get('john')
|
|
121
|
+
|
|
122
|
+
expect(retrieved?.name).toBe('John')
|
|
123
|
+
|
|
124
|
+
// Update
|
|
125
|
+
const updated = await db.User.update('john', {
|
|
126
|
+
name: 'Jane',
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
expect(updated.name).toBe('Jane')
|
|
130
|
+
expect(updated.email).toBe('john@example.com') // Preserved
|
|
131
|
+
|
|
132
|
+
// Delete
|
|
133
|
+
const deleted = await db.User.delete('john')
|
|
134
|
+
|
|
135
|
+
expect(deleted).toBe(true)
|
|
136
|
+
expect(await db.User.get('john')).toBeNull()
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Testing Relationships
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
it('manages relationships', async () => {
|
|
144
|
+
const db = DB(schema)
|
|
145
|
+
const provider = createMemoryProvider()
|
|
146
|
+
setProvider(provider)
|
|
147
|
+
|
|
148
|
+
await db.User.create('user1', { name: 'User 1' })
|
|
149
|
+
await db.Post.create('post1', { title: 'Post 1' })
|
|
150
|
+
|
|
151
|
+
// Create relation
|
|
152
|
+
await provider.relate('User', 'user1', 'posts', 'Post', 'post1')
|
|
153
|
+
|
|
154
|
+
// Query related
|
|
155
|
+
const posts = await provider.related('User', 'user1', 'posts')
|
|
156
|
+
|
|
157
|
+
expect(posts).toHaveLength(1)
|
|
158
|
+
expect(posts[0]?.$id).toBe('post1')
|
|
159
|
+
|
|
160
|
+
// Remove relation
|
|
161
|
+
await provider.unrelate('User', 'user1', 'posts', 'Post', 'post1')
|
|
162
|
+
|
|
163
|
+
const afterUnrelate = await provider.related('User', 'user1', 'posts')
|
|
164
|
+
expect(afterUnrelate).toHaveLength(0)
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Testing Search
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
it('searches entities', async () => {
|
|
172
|
+
const db = DB(schema)
|
|
173
|
+
|
|
174
|
+
await db.Post.create('post1', {
|
|
175
|
+
title: 'TypeScript Guide',
|
|
176
|
+
content: 'Learn TypeScript',
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
await db.Post.create('post2', {
|
|
180
|
+
title: 'JavaScript Patterns',
|
|
181
|
+
content: 'Learn JavaScript',
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// Search by keyword
|
|
185
|
+
const results = await db.Post.search('TypeScript')
|
|
186
|
+
|
|
187
|
+
expect(results).toHaveLength(1)
|
|
188
|
+
expect(results[0]?.title).toContain('TypeScript')
|
|
189
|
+
|
|
190
|
+
// Search with options
|
|
191
|
+
const filtered = await db.Post.search('TypeScript', {
|
|
192
|
+
fields: ['title'],
|
|
193
|
+
minScore: 0.5,
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
expect(filtered.length).toBeGreaterThan(0)
|
|
197
|
+
})
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Best Practices
|
|
201
|
+
|
|
202
|
+
### ✅ DO
|
|
203
|
+
|
|
204
|
+
- **Use `beforeEach`** to reset state between tests
|
|
205
|
+
- **Test one thing** per test case
|
|
206
|
+
- **Use descriptive names** like "creates entity with auto-generated ID"
|
|
207
|
+
- **Test both success and failure** cases
|
|
208
|
+
- **Use type assertions** with `as const` for schemas
|
|
209
|
+
- **Clean up** after tests that modify global state
|
|
210
|
+
|
|
211
|
+
### ❌ DON'T
|
|
212
|
+
|
|
213
|
+
- **Share state** between tests
|
|
214
|
+
- **Use hard-coded delays** (use await instead)
|
|
215
|
+
- **Test implementation details** (test behavior)
|
|
216
|
+
- **Skip cleanup** in `beforeEach`/`afterEach`
|
|
217
|
+
- **Use real databases** in unit tests
|
|
218
|
+
- **Write flaky tests** that randomly fail
|
|
219
|
+
|
|
220
|
+
## Common Patterns
|
|
221
|
+
|
|
222
|
+
### Testing Optional Fields
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
it('handles optional fields', async () => {
|
|
226
|
+
const schema = {
|
|
227
|
+
User: {
|
|
228
|
+
name: 'string',
|
|
229
|
+
bio: 'string?',
|
|
230
|
+
},
|
|
231
|
+
} as const
|
|
232
|
+
|
|
233
|
+
const db = DB(schema)
|
|
234
|
+
|
|
235
|
+
// Create without optional field
|
|
236
|
+
const user1 = await db.User.create('user1', {
|
|
237
|
+
name: 'John',
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
expect(user1.bio).toBeUndefined()
|
|
241
|
+
|
|
242
|
+
// Create with optional field
|
|
243
|
+
const user2 = await db.User.create('user2', {
|
|
244
|
+
name: 'Jane',
|
|
245
|
+
bio: 'Developer',
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
expect(user2.bio).toBe('Developer')
|
|
249
|
+
})
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Testing Error Cases
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
it('throws error when entity exists', async () => {
|
|
256
|
+
const db = DB(schema)
|
|
257
|
+
const provider = createMemoryProvider()
|
|
258
|
+
setProvider(provider)
|
|
259
|
+
|
|
260
|
+
await provider.create('User', 'john', { name: 'John' })
|
|
261
|
+
|
|
262
|
+
await expect(
|
|
263
|
+
provider.create('User', 'john', { name: 'Jane' })
|
|
264
|
+
).rejects.toThrow('Entity already exists')
|
|
265
|
+
})
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Testing Edge Cases
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
it('handles empty results', async () => {
|
|
272
|
+
const db = DB(schema)
|
|
273
|
+
|
|
274
|
+
const results = await db.User.list({ where: { age: 999 } })
|
|
275
|
+
|
|
276
|
+
expect(results).toEqual([])
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
it('handles large data', async () => {
|
|
280
|
+
const db = DB(schema)
|
|
281
|
+
|
|
282
|
+
const largeString = 'x'.repeat(100000)
|
|
283
|
+
const doc = await db.Document.create('doc1', {
|
|
284
|
+
content: largeString,
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
expect(doc.content.length).toBe(100000)
|
|
288
|
+
})
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Debugging Tests
|
|
292
|
+
|
|
293
|
+
### Run Single Test
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# By file
|
|
297
|
+
pnpm test src/schema.test.ts
|
|
298
|
+
|
|
299
|
+
# By pattern
|
|
300
|
+
pnpm test -t "creates entity"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Watch Mode
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
pnpm test
|
|
307
|
+
# Tests will re-run on file changes
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Verbose Output
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
pnpm test --reporter=verbose
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Debug in VS Code
|
|
317
|
+
|
|
318
|
+
Add to `.vscode/launch.json`:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"type": "node",
|
|
323
|
+
"request": "launch",
|
|
324
|
+
"name": "Debug Tests",
|
|
325
|
+
"runtimeExecutable": "pnpm",
|
|
326
|
+
"runtimeArgs": ["test", "--run", "--no-coverage"],
|
|
327
|
+
"console": "integratedTerminal"
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Test Coverage
|
|
332
|
+
|
|
333
|
+
Currently not configured, but can be added:
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Add to package.json scripts
|
|
337
|
+
"test:coverage": "vitest run --coverage"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Continuous Integration
|
|
341
|
+
|
|
342
|
+
Tests should be run in CI on:
|
|
343
|
+
- Pull requests
|
|
344
|
+
- Commits to main
|
|
345
|
+
- Before releases
|
|
346
|
+
|
|
347
|
+
Example GitHub Actions:
|
|
348
|
+
|
|
349
|
+
```yaml
|
|
350
|
+
name: Test
|
|
351
|
+
on: [push, pull_request]
|
|
352
|
+
jobs:
|
|
353
|
+
test:
|
|
354
|
+
runs-on: ubuntu-latest
|
|
355
|
+
steps:
|
|
356
|
+
- uses: actions/checkout@v3
|
|
357
|
+
- uses: pnpm/action-setup@v2
|
|
358
|
+
- uses: actions/setup-node@v3
|
|
359
|
+
with:
|
|
360
|
+
node-version: '20'
|
|
361
|
+
cache: 'pnpm'
|
|
362
|
+
- run: pnpm install
|
|
363
|
+
- run: pnpm build
|
|
364
|
+
- run: pnpm test run
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Troubleshooting
|
|
368
|
+
|
|
369
|
+
### Tests Hang
|
|
370
|
+
|
|
371
|
+
- Check for missing `await` keywords
|
|
372
|
+
- Ensure async operations complete
|
|
373
|
+
- Add `timeout` to slow tests
|
|
374
|
+
|
|
375
|
+
### Flaky Tests
|
|
376
|
+
|
|
377
|
+
- Add `beforeEach` to reset state
|
|
378
|
+
- Don't rely on execution order
|
|
379
|
+
- Use deterministic test data
|
|
380
|
+
|
|
381
|
+
### Import Errors
|
|
382
|
+
|
|
383
|
+
- Check file paths are correct
|
|
384
|
+
- Use `.js` extensions for imports
|
|
385
|
+
- Verify `vitest.config.ts` is correct
|
|
386
|
+
|
|
387
|
+
### Type Errors
|
|
388
|
+
|
|
389
|
+
- Use `as const` for schema definitions
|
|
390
|
+
- Add proper type assertions
|
|
391
|
+
- Check TypeScript version compatibility
|
|
392
|
+
|
|
393
|
+
## Resources
|
|
394
|
+
|
|
395
|
+
- [Vitest Documentation](https://vitest.dev/)
|
|
396
|
+
- [Testing Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
|
|
397
|
+
- [Test Coverage Guide](https://istanbul.js.org/)
|
|
398
|
+
|
|
399
|
+
## Summary
|
|
400
|
+
|
|
401
|
+
The ai-database test suite provides:
|
|
402
|
+
|
|
403
|
+
✅ **174 comprehensive tests**
|
|
404
|
+
✅ **100% passing rate**
|
|
405
|
+
✅ **Fast execution** (~215ms total)
|
|
406
|
+
✅ **Good coverage** of all features
|
|
407
|
+
✅ **Clear patterns** for new tests
|
|
408
|
+
✅ **Excellent documentation**
|
|
409
|
+
|
|
410
|
+
All tests follow consistent patterns and best practices, making it easy to add new tests as features are developed.
|
package/TEST_SUMMARY.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# ai-database Test Suite Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Comprehensive test suite for the ai-database package with **174 tests** across **5 test files**, all passing.
|
|
6
|
+
|
|
7
|
+
## Test Files
|
|
8
|
+
|
|
9
|
+
### 1. `src/schema.test.ts` (22 tests)
|
|
10
|
+
**Purpose**: Schema parsing and bi-directional relationship validation
|
|
11
|
+
|
|
12
|
+
**Coverage**:
|
|
13
|
+
- Primitive field types (string, number, boolean, date, datetime, json, markdown, url)
|
|
14
|
+
- Optional fields with `?` modifier
|
|
15
|
+
- Array fields with `[]` and `[type]` syntax
|
|
16
|
+
- Simple relations and bi-directional relationships
|
|
17
|
+
- Automatic backref generation (e.g., `Post.author: 'Author.posts'` auto-creates `Author.posts`)
|
|
18
|
+
- Complex multi-entity schemas
|
|
19
|
+
- Self-referential relations
|
|
20
|
+
- Edge cases (empty schemas, missing entities, etc.)
|
|
21
|
+
- TypeScript type inference validation
|
|
22
|
+
|
|
23
|
+
**Key Tests**:
|
|
24
|
+
- ✅ Parses all primitive types correctly
|
|
25
|
+
- ✅ Handles optional and array modifiers
|
|
26
|
+
- ✅ Creates automatic backrefs for one-to-many relations
|
|
27
|
+
- ✅ Creates automatic backrefs for many-to-many relations
|
|
28
|
+
- ✅ Validates DB factory creates typed database
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
### 2. `src/memory-provider.test.ts` (40 tests)
|
|
33
|
+
**Purpose**: In-memory database provider implementation
|
|
34
|
+
|
|
35
|
+
**Coverage**:
|
|
36
|
+
- **CRUD Operations**: Create, get, update, delete
|
|
37
|
+
- **Querying**: List with filtering, sorting, pagination
|
|
38
|
+
- **Search**: Full-text search with scoring and field filtering
|
|
39
|
+
- **Relationships**: Create, query, and remove relations between entities
|
|
40
|
+
- **Utility Methods**: `clear()` and `stats()`
|
|
41
|
+
- **Concurrency**: Multiple simultaneous operations
|
|
42
|
+
- **Special Cases**: UUID generation, timestamp tracking, error handling
|
|
43
|
+
|
|
44
|
+
**Key Tests**:
|
|
45
|
+
- ✅ Creates entities with auto-generated or explicit IDs
|
|
46
|
+
- ✅ Lists with where clauses, ordering, limits, and offsets
|
|
47
|
+
- ✅ Searches with relevance scoring and min score filtering
|
|
48
|
+
- ✅ Creates and queries many-to-many relationships
|
|
49
|
+
- ✅ Cleans up relations when entities are deleted
|
|
50
|
+
- ✅ Tracks entity and relation counts
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### 3. `src/index.test.ts` (31 tests)
|
|
55
|
+
**Purpose**: Integration tests for the full DB API
|
|
56
|
+
|
|
57
|
+
**Coverage**:
|
|
58
|
+
- **DB Factory**: Creating typed database instances from schemas
|
|
59
|
+
- **Entity Operations**: All CRUD methods on typed entities
|
|
60
|
+
- **List & Query**: Filtering, sorting, pagination
|
|
61
|
+
- **Search**: Entity-specific and global search
|
|
62
|
+
- **Relationships**: Managing relations through both DB API and provider
|
|
63
|
+
- **Global Methods**: `db.get()` by URL, `db.search()` across all types
|
|
64
|
+
- **Type Safety**: Verifying TypeScript inference works correctly
|
|
65
|
+
- **Complex Scenarios**: Multi-entity operations, self-referential relations
|
|
66
|
+
|
|
67
|
+
**Key Tests**:
|
|
68
|
+
- ✅ Creates, reads, updates, deletes entities via typed API
|
|
69
|
+
- ✅ Upserts work for both create and update scenarios
|
|
70
|
+
- ✅ Lists with various query options and pagination
|
|
71
|
+
- ✅ Searches within entity type and globally
|
|
72
|
+
- ✅ Iterates over entities with `forEach()`
|
|
73
|
+
- ✅ Gets entities by URL (multiple formats supported)
|
|
74
|
+
- ✅ Handles complex multi-entity schemas
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### 4. `test/provider-resolution.test.ts` (38 tests)
|
|
79
|
+
**Purpose**: DATABASE_URL parsing and provider resolution
|
|
80
|
+
|
|
81
|
+
**Coverage**:
|
|
82
|
+
- **URL Format Detection**: All supported DATABASE_URL formats
|
|
83
|
+
- `:memory:` → In-memory provider
|
|
84
|
+
- `./content` → Filesystem provider
|
|
85
|
+
- `sqlite://./content` → Local SQLite provider
|
|
86
|
+
- `libsql://db.turso.io` → Remote Turso provider
|
|
87
|
+
- `chdb://./content` → Local ClickHouse (chDB)
|
|
88
|
+
- `clickhouse://host:8123` → Remote ClickHouse
|
|
89
|
+
- **Provider Selection**: Environment variable handling
|
|
90
|
+
- **URL Parsing**: Extracting provider type, paths, and remote URLs
|
|
91
|
+
- **Provider Initialization**: Memory provider setup and isolation
|
|
92
|
+
- **Interface Compliance**: Ensuring all providers implement required methods
|
|
93
|
+
- **Documentation Examples**: Verifying all README examples work
|
|
94
|
+
|
|
95
|
+
**Key Tests**:
|
|
96
|
+
- ✅ Detects all provider types from URL format
|
|
97
|
+
- ✅ Generates correct .db folder paths for local providers
|
|
98
|
+
- ✅ Handles query parameters and database names in URLs
|
|
99
|
+
- ✅ Memory provider implements all required methods
|
|
100
|
+
- ✅ Provider instances are properly isolated
|
|
101
|
+
- ✅ All README URL examples are valid
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### 5. `test/edge-cases.test.ts` (43 tests)
|
|
106
|
+
**Purpose**: Edge cases, boundary conditions, and error scenarios
|
|
107
|
+
|
|
108
|
+
**Coverage**:
|
|
109
|
+
- **Empty/Minimal Schemas**: Handling edge case configurations
|
|
110
|
+
- **Special Characters**: IDs and data with unicode, symbols, paths
|
|
111
|
+
- **Large Data**: 100KB strings, 1000+ entities, bulk operations
|
|
112
|
+
- **Concurrent Operations**: Parallel creates, updates, queries
|
|
113
|
+
- **Optional Fields**: Missing, undefined, and null values
|
|
114
|
+
- **Array Fields**: Empty arrays, array mutations
|
|
115
|
+
- **URL Parsing**: Various URL formats, query params, hashes
|
|
116
|
+
- **Search Edge Cases**: Empty queries, special regex chars, extreme scores
|
|
117
|
+
- **Pagination**: Out-of-bounds offsets, zero/negative limits
|
|
118
|
+
- **Type Coercion**: Handling different value types
|
|
119
|
+
|
|
120
|
+
**Key Tests**:
|
|
121
|
+
- ✅ Handles empty schemas and entities with no fields
|
|
122
|
+
- ✅ Supports IDs with hyphens, underscores, dots, slashes, UUIDs
|
|
123
|
+
- ✅ Stores unicode characters and emojis correctly
|
|
124
|
+
- ✅ Handles 100KB strings and 1000+ entities
|
|
125
|
+
- ✅ Concurrent operations don't interfere with each other
|
|
126
|
+
- ✅ Optional fields can be set, unset, and omitted
|
|
127
|
+
- ✅ Parses full HTTPS URLs, HTTP URLs, and type/id paths
|
|
128
|
+
- ✅ Search handles empty strings and special regex characters
|
|
129
|
+
- ✅ Pagination handles out-of-bounds offsets gracefully
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Test Execution
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Run all tests
|
|
137
|
+
pnpm test
|
|
138
|
+
|
|
139
|
+
# Run tests once (non-watch mode)
|
|
140
|
+
pnpm test run
|
|
141
|
+
|
|
142
|
+
# Run specific test file
|
|
143
|
+
pnpm test src/schema.test.ts
|
|
144
|
+
|
|
145
|
+
# Build package (verifies no TypeScript errors)
|
|
146
|
+
pnpm build
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Test Results
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
✓ src/index.test.ts (31 tests) 7ms
|
|
153
|
+
✓ test/edge-cases.test.ts (43 tests) 6ms
|
|
154
|
+
✓ src/memory-provider.test.ts (40 tests) 14ms
|
|
155
|
+
✓ src/schema.test.ts (22 tests) 2ms
|
|
156
|
+
✓ test/provider-resolution.test.ts (38 tests) 2ms
|
|
157
|
+
|
|
158
|
+
Test Files 5 passed (5)
|
|
159
|
+
Tests 174 passed (174)
|
|
160
|
+
Duration 215ms
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Coverage Areas
|
|
164
|
+
|
|
165
|
+
| Area | Test File | Tests | Status |
|
|
166
|
+
|------|-----------|-------|--------|
|
|
167
|
+
| Schema Parsing | `src/schema.test.ts` | 22 | ✅ 100% |
|
|
168
|
+
| Memory Provider | `src/memory-provider.test.ts` | 40 | ✅ 100% |
|
|
169
|
+
| Integration | `src/index.test.ts` | 31 | ✅ 100% |
|
|
170
|
+
| Provider Resolution | `test/provider-resolution.test.ts` | 38 | ✅ 100% |
|
|
171
|
+
| Edge Cases | `test/edge-cases.test.ts` | 43 | ✅ 100% |
|
|
172
|
+
| **TOTAL** | | **174** | **✅ 100%** |
|
|
173
|
+
|
|
174
|
+
## Key Features Tested
|
|
175
|
+
|
|
176
|
+
### ✅ Schema-First Design
|
|
177
|
+
- Declarative schema definitions
|
|
178
|
+
- Automatic bi-directional relationships
|
|
179
|
+
- TypeScript type inference from schema
|
|
180
|
+
- Support for all primitive types
|
|
181
|
+
|
|
182
|
+
### ✅ CRUD Operations
|
|
183
|
+
- Create with auto-generated or explicit IDs
|
|
184
|
+
- Get by ID with null for not-found
|
|
185
|
+
- Update with partial data merging
|
|
186
|
+
- Upsert for create-or-update semantics
|
|
187
|
+
- Delete with cascade cleanup of relations
|
|
188
|
+
|
|
189
|
+
### ✅ Querying & Search
|
|
190
|
+
- List with where clauses
|
|
191
|
+
- Sorting (ascending/descending)
|
|
192
|
+
- Pagination (limit/offset)
|
|
193
|
+
- Full-text search with scoring
|
|
194
|
+
- Field-specific search
|
|
195
|
+
- Global search across all entity types
|
|
196
|
+
|
|
197
|
+
### ✅ Relationships
|
|
198
|
+
- One-to-many with automatic backrefs
|
|
199
|
+
- Many-to-many with array syntax
|
|
200
|
+
- Self-referential relations
|
|
201
|
+
- Lazy-loaded relation traversal
|
|
202
|
+
- Relation cleanup on entity deletion
|
|
203
|
+
|
|
204
|
+
### ✅ Provider System
|
|
205
|
+
- In-memory provider (fully implemented)
|
|
206
|
+
- Pluggable provider interface
|
|
207
|
+
- DATABASE_URL parsing for all provider types
|
|
208
|
+
- Graceful fallback to memory provider
|
|
209
|
+
- Provider isolation for testing
|
|
210
|
+
|
|
211
|
+
### ✅ Type Safety
|
|
212
|
+
- Full TypeScript inference
|
|
213
|
+
- Typed entity operations
|
|
214
|
+
- Type-safe query results
|
|
215
|
+
- Compile-time schema validation
|
|
216
|
+
|
|
217
|
+
## Implementation Notes
|
|
218
|
+
|
|
219
|
+
1. **In-Memory Provider**: Fully functional with all operations implemented
|
|
220
|
+
2. **Dynamic Imports**: Other providers (`@mdxdb/fs`, `@mdxdb/sqlite`, `@mdxdb/clickhouse`) are dynamically imported with graceful fallback
|
|
221
|
+
3. **Test Isolation**: Each test suite uses fresh provider instances via `beforeEach`
|
|
222
|
+
4. **TypeScript**: All code compiles without errors, strict mode enabled
|
|
223
|
+
5. **Vitest**: Using vitest as test runner with fork pool for isolation
|
|
224
|
+
|
|
225
|
+
## Future Test Additions
|
|
226
|
+
|
|
227
|
+
Potential areas for expansion once additional providers are implemented:
|
|
228
|
+
|
|
229
|
+
1. **Filesystem Provider Tests**: When `@mdxdb/fs` is implemented
|
|
230
|
+
2. **SQLite Provider Tests**: When `@mdxdb/sqlite` is implemented
|
|
231
|
+
3. **ClickHouse Provider Tests**: When `@mdxdb/clickhouse` is implemented
|
|
232
|
+
4. **Cross-Provider Tests**: Verifying behavior consistency
|
|
233
|
+
5. **Performance Benchmarks**: Large dataset tests with timing
|
|
234
|
+
6. **Migration Tests**: Schema evolution and data migration
|
|
235
|
+
7. **Transaction Tests**: If/when transaction support is added
|
|
236
|
+
8. **Validation Tests**: Runtime schema validation
|
|
237
|
+
9. **Index Tests**: Query optimization with indexes
|
|
238
|
+
|
|
239
|
+
## Conclusion
|
|
240
|
+
|
|
241
|
+
The ai-database package has **comprehensive test coverage** with **174 passing tests** covering:
|
|
242
|
+
- ✅ All core functionality
|
|
243
|
+
- ✅ Schema parsing and validation
|
|
244
|
+
- ✅ Complete CRUD operations
|
|
245
|
+
- ✅ Advanced querying and search
|
|
246
|
+
- ✅ Relationship management
|
|
247
|
+
- ✅ Provider resolution and initialization
|
|
248
|
+
- ✅ Edge cases and error scenarios
|
|
249
|
+
|
|
250
|
+
The test suite provides a **solid foundation** for the package and ensures reliability as new providers and features are added.
|