import type { CollectionApi, IndexDefinition, IndexRange, StoreOptions } from './types.js'; import type { SqlJsStore } from './sqljs-store.js'; import type { SyncEngine } from './sync-engine.js'; export class Collection implements CollectionApi { private readonly storeName: string; private readonly indexes: IndexDefinition[]; private indexesBuilt = false; constructor(options: StoreOptions, private store: SqlJsStore, private sync: SyncEngine) { this.storeName = options.name; this.indexes = options.indexes ?? []; this.sync.registerIndexes(this.storeName, this.indexes as IndexDefinition[]); } private async ensureIndexes(): Promise { if (this.indexesBuilt || this.indexes.length === 0) return; await this.store.rebuildIndexes(this.storeName, this.indexes as IndexDefinition[]); this.indexesBuilt = true; } async get(id: string): Promise { const rec = await this.store.getDoc(this.storeName, id); return rec ? (rec.data as T) : undefined; } async put(doc: T): Promise { await this.ensureIndexes(); const existing = await this.store.getRawDoc(this.storeName, doc.id); await this.sync.writeDoc(this.storeName, doc.id, doc, Date.now(), (existing?.rev ?? 0) + 1); } async delete(id: string): Promise { await this.ensureIndexes(); const existing = await this.store.getRawDoc(this.storeName, id); if (!existing || existing.deleted) return; await this.sync.deleteDocEvent(this.storeName, id, Date.now(), existing.rev + 1); } async all(): Promise { return (await this.store.getAllDocs(this.storeName)).map((d) => d.data as T); } async findByIndex(indexName: string, value: unknown): Promise { await this.ensureIndexes(); const ids = await this.store.findByIndex(this.storeName, indexName, value); return this.fetchByIds(ids); } async queryByIndex(indexName: string, range: IndexRange): Promise { await this.ensureIndexes(); const ids = await this.store.queryByIndex(this.storeName, indexName, range); return this.fetchByIds(ids); } private async fetchByIds(ids: string[]): Promise { const results: T[] = []; for (const id of ids) { const doc = await this.store.getDoc(this.storeName, id); if (doc) results.push(doc.data as T); } return results; } }