improved contracts

This commit is contained in:
Morten Olsen
2025-09-09 18:43:14 +02:00
parent c59c9487e6
commit d5b6a8269b
3 changed files with 39 additions and 19 deletions

View File

@@ -89,6 +89,13 @@ const documentSearchOptionsSchema = z.object({
type DocumentSearchOptions = z.infer<typeof documentSearchOptionsSchema>;
const documentSearchResultSchema = z.object({
documents: z.array(documentSchema),
more: z.boolean(),
});
type DocumentSearchResult = z.infer<typeof documentSearchResultSchema>;
const documentUpsertEventSchema = z.object({
action: z.union([z.literal('insert'), z.literal('update'), z.literal('delete')]),
document: documentSchema,
@@ -96,12 +103,21 @@ const documentUpsertEventSchema = z.object({
type DocumentUpsertEvent = z.infer<typeof documentUpsertEventSchema>;
export type { Document, DocumentUpsert, MetaFilter, MetaCondition, DocumentSearchOptions, DocumentUpsertEvent };
export type {
Document,
DocumentUpsert,
MetaFilter,
MetaCondition,
DocumentSearchOptions,
DocumentSearchResult,
DocumentUpsertEvent,
};
export {
documentSchema,
documentUpsertSchema,
metaFilterSchema,
metaConditionSchema,
documentSearchOptionsSchema,
documentSearchResultSchema,
documentUpsertEventSchema,
};

View File

@@ -7,6 +7,7 @@ import {
documentUpsertEventSchema,
type Document,
type DocumentSearchOptions,
type DocumentSearchResult,
type DocumentUpsert,
type DocumentUpsertEvent,
} from './documents.schemas.ts';
@@ -26,7 +27,7 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
this.#services = services;
}
public get = async (uri: string, type: string) => {
public get = async (uri: string, type: string): Promise<Document | undefined> => {
const db = await this.#services.get(DatabaseService).getDb();
const [document] = await db<TableRow['document']>(tableNames.documents)
.where({
@@ -37,7 +38,7 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
return document;
};
public delete = async (uri: string, type: string) => {
public delete = async (uri: string, type: string): Promise<DocumentUpsertEvent | undefined> => {
const db = await this.#services.get(DatabaseService).getDb();
const [document] = await db<TableRow['document']>(tableNames.documents)
.where({
@@ -53,10 +54,12 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
deletedAt: new Date().toISOString(),
};
await db(tableNames.documents).where({ uri, type }).update(toDelete);
this.emit('upsert', { action: 'delete', document: toDelete });
const event: DocumentUpsertEvent = { action: 'delete', document: toDelete };
this.emit('upsert', event);
return event;
};
public upsert = async (document: DocumentUpsert) => {
public upsert = async (document: DocumentUpsert): Promise<DocumentUpsertEvent | undefined> => {
const db = await this.#services.get(DatabaseService).getDb();
const [current] = await db<TableRow['document']>(tableNames.documents)
.where({
@@ -80,7 +83,9 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
uri: document.uri,
type: document.type,
});
this.emit('upsert', { action: 'update', document: toInsert });
const event: DocumentUpsertEvent = { action: 'update', document: toInsert };
this.emit('upsert', event);
return event;
} else {
const toInsert: Document = {
...document,
@@ -88,12 +93,14 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
updatedAt: new Date().toISOString(),
};
await db(tableNames.documents).insert(toInsert);
this.emit('upsert', { action: 'insert', document: toInsert });
const event: DocumentUpsertEvent = { action: 'insert', document: toInsert };
this.emit('upsert', event);
return event;
}
};
public search = async (options: DocumentSearchOptions) => {
const { uris, types, meta, limit, offset } = options;
public search = async (options: DocumentSearchOptions): Promise<DocumentSearchResult> => {
const { uris, types, meta, limit = 10, offset = 0 } = options;
const db = await this.#services.get(DatabaseService).getDb();
let query = db<TableRow['document']>(tableNames.documents);
if (uris) {
@@ -102,18 +109,15 @@ class DocumentsService extends EventEmitter<DocumentEvents> {
if (types) {
query = query.whereIn('type', types);
}
if (limit) {
query = query.limit(limit);
}
if (meta) {
query = query.where((builder) => {
buildMetaCondition(builder, meta);
});
}
if (offset) {
query = query.offset(offset);
}
return query;
query = query.limit(limit + 1).offset(offset);
const documents = await query;
const more = documents.length > limit;
return { documents: documents.slice(0, limit), more };
};
}