import { describe, expectTypeOf, it } from 'vitest' import type { BaseKVStorage } from '../src/kv-storage/base-kv-storage.js' import { KVStorageInMemory } from '../src/kv-storage/kv-storage-in-memory.js' import { EventStorageKV } from '../src/event-storage/event-storage-kv.js' import type { StoredEvent } from '../src/event-storage/base-event-storage.js' import { DocumentStorageInMemory } from '../src/document-storage/document-storage-in-memory.js' import { EventSourcedDocumentStorage } from '../src/document-storage/event-sourced-document-storage.js' import type { DocChange } from '../src/utils/document-update.js' import type { FindResult } from '../src/utils/document-query.js' import type { Fields, Many } from '../src/utils/schema.js' type User = { username: string; age: number } type Post = { title: string; createdAt: string } type Schema = { children: { users: Many }> profile: { children: { [id: string]: { children: Fields } } } } } describe('KV types', () => { const db = new KVStorageInMemory() it('types reads at dynamic and named levels', () => { expectTypeOf(db.child('users').get('123')).toEqualTypeOf>() expectTypeOf(db.child('users').child('123').get()).toEqualTypeOf>() expectTypeOf(db.child('profile').child('9').get('age')).toEqualTypeOf>() expectTypeOf(db.child('users').child('123').child('posts')).toEqualTypeOf>>() // @ts-expect-error unknown child db.child('users').child('123').child('postz') // @ts-expect-error unknown field db.child('profile').child('9').get('agee') }) it('types writes', () => { db.child('users').set('1', { username: 'a', age: 1 }) db.child('users').child('1').set({ username: 'a', age: 1 }) // @ts-expect-error missing field db.child('users').set('1', { username: 'a' }) db.child('profile') .child('9') .setMany([ ['age', 3], // @ts-expect-error value doesn't match its key ['username', 3], ]) }) it('types listings', () => { expectTypeOf(db.child('profile').child('9').keys()).toEqualTypeOf>() expectTypeOf(db.child('users').entries()).toEqualTypeOf>() }) it('is untyped by default', () => { expectTypeOf(new KVStorageInMemory().child('a').child(1).get('b')).toEqualTypeOf>() }) }) describe('event and document types', () => { type OrderEvent = { type: 'created'; total: number } | { type: 'paid' } const orders = new EventStorageKV<{ children: { orders: Many } }>(new KVStorageInMemory()).child('orders') const users = new DocumentStorageInMemory<{ children: { users: Many }> } }>().child('users') it('types events', () => { orders.append('o1', [{ type: 'created', total: 1 }]) orders.child('o1').append([{ type: 'paid' }]) // @ts-expect-error not an OrderEvent orders.append('o1', [{ type: 'refunded' }]) expectTypeOf(orders.read('o1')).toEqualTypeOf>>() }) it('types documents', () => { expectTypeOf(users.get('1')).toEqualTypeOf>() expectTypeOf(users.update('1', { $inc: { age: 1 } })).toEqualTypeOf>() expectTypeOf(users.child('1').child('posts').get('p')).toEqualTypeOf>() expectTypeOf(users.find()).toEqualTypeOf>>() // @ts-expect-error missing field users.insert({ username: 'a' }) }) it('keeps event-sourced methods on children', () => { const docs = new EventSourcedDocumentStorage<{ children: { users: Many } }>( new EventStorageKV(new KVStorageInMemory()), new DocumentStorageInMemory(), ) expectTypeOf(docs.child('users').history('1')).toEqualTypeOf>>() expectTypeOf(docs.child('users').getAt('1', 'id')).toEqualTypeOf>() }) })