aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared/search.ts
blob: d23ab29f377fcfbea01ded9df85a629cfb4744a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { z } from "zod";

import { PluginManager, PluginType } from "./plugins";

export const zBookmarkSearchDocument = z.object({
  id: z.string(),
  userId: z.string(),
  url: z.string().nullish(),
  title: z.string().nullish(),
  linkTitle: z.string().nullish(),
  description: z.string().nullish(),
  content: z.string().nullish(),
  metadata: z.string().nullish(),
  fileName: z.string().nullish(),
  createdAt: z.string().nullish(),
  note: z.string().nullish(),
  summary: z.string().nullish(),
  tags: z.array(z.string()).default([]),
  publisher: z.string().nullish(),
  author: z.string().nullish(),
  datePublished: z.date().nullish(),
  dateModified: z.date().nullish(),
});

export type BookmarkSearchDocument = z.infer<typeof zBookmarkSearchDocument>;

export type SortOrder = "asc" | "desc";
export type SortableAttributes = "createdAt";

export type FilterableAttributes = "userId" | "id";
export type FilterQuery =
  | {
      type: "eq";
      field: FilterableAttributes;
      value: string;
    }
  | {
      type: "in";
      field: FilterableAttributes;
      values: string[];
    };

export interface SearchResult {
  id: string;
  score?: number;
}

export interface SearchOptions {
  query: string;
  // Diffeernt filters are ANDed together
  filter?: FilterQuery[];
  limit?: number;
  offset?: number;
  sort?: { field: SortableAttributes; order: SortOrder }[];
}

export interface SearchResponse {
  hits: SearchResult[];
  totalHits: number;
  processingTimeMs: number;
}

export interface SearchIndexClient {
  addDocuments(documents: BookmarkSearchDocument[]): Promise<void>;
  deleteDocuments(ids: string[]): Promise<void>;
  search(options: SearchOptions): Promise<SearchResponse>;
  clearIndex(): Promise<void>;
}

export async function getSearchClient(): Promise<SearchIndexClient | null> {
  return PluginManager.getClient(PluginType.Search);
}