diff options
| author | Mohamed Bassem <me@mbassem.com> | 2025-11-08 14:50:00 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-08 14:50:00 +0000 |
| commit | 99413db0e79a156a1b87eacd3c6a7b83e9df946e (patch) | |
| tree | 73f0a5fceb507f75f662a109b00beeb3fa6b16fb /packages/plugins-search-meilisearch/src | |
| parent | 737b03172c2e063ba311c23d6552418bd2ab1955 (diff) | |
| download | karakeep-99413db0e79a156a1b87eacd3c6a7b83e9df946e.tar.zst | |
refactor: consolidate multiple karakeep plugins into one package (#2101)
* refactor: consolidate plugin packages into single plugins directory
- Create new `packages/plugins` directory with consolidated package.json
- Move queue-liteque, queue-restate, and search-meilisearch to subdirectories
- Update imports in packages/shared-server/src/plugins.ts
- Remove individual plugin package directories
- Update shared-server dependency to use @karakeep/plugins
This reduces overhead of maintaining multiple separate packages for plugins.
* refactor: consolidate plugin config files to root level
- Move .oxlintrc.json to packages/plugins root
- Move vitest.config.ts to packages/plugins root
- Update vitest config paths to work from root
- Remove individual config files from plugin subdirectories
This reduces configuration duplication across plugin subdirectories.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Diffstat (limited to 'packages/plugins-search-meilisearch/src')
| -rw-r--r-- | packages/plugins-search-meilisearch/src/env.ts | 8 | ||||
| -rw-r--r-- | packages/plugins-search-meilisearch/src/index.ts | 159 |
2 files changed, 0 insertions, 167 deletions
diff --git a/packages/plugins-search-meilisearch/src/env.ts b/packages/plugins-search-meilisearch/src/env.ts deleted file mode 100644 index c06fdd55..00000000 --- a/packages/plugins-search-meilisearch/src/env.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { z } from "zod"; - -export const envConfig = z - .object({ - MEILI_ADDR: z.string().optional(), - MEILI_MASTER_KEY: z.string().default(""), - }) - .parse(process.env); diff --git a/packages/plugins-search-meilisearch/src/index.ts b/packages/plugins-search-meilisearch/src/index.ts deleted file mode 100644 index 30da4a64..00000000 --- a/packages/plugins-search-meilisearch/src/index.ts +++ /dev/null @@ -1,159 +0,0 @@ -import type { Index } from "meilisearch"; -import { MeiliSearch } from "meilisearch"; - -import type { - BookmarkSearchDocument, - FilterQuery, - SearchIndexClient, - SearchOptions, - SearchResponse, -} from "@karakeep/shared/search"; -import serverConfig from "@karakeep/shared/config"; -import { PluginProvider } from "@karakeep/shared/plugins"; - -import { envConfig } from "./env"; - -function filterToMeiliSearchFilter(filter: FilterQuery): string { - switch (filter.type) { - case "eq": - return `${filter.field} = "${filter.value}"`; - case "in": - return `${filter.field} IN [${filter.values.join(",")}]`; - default: { - const exhaustiveCheck: never = filter; - throw new Error(`Unhandled color case: ${exhaustiveCheck}`); - } - } -} - -class MeiliSearchIndexClient implements SearchIndexClient { - constructor(private index: Index<BookmarkSearchDocument>) {} - - async addDocuments(documents: BookmarkSearchDocument[]): Promise<void> { - const task = await this.index.addDocuments(documents, { - primaryKey: "id", - }); - await this.ensureTaskSuccess(task.taskUid); - } - - async deleteDocuments(ids: string[]): Promise<void> { - const task = await this.index.deleteDocuments(ids); - await this.ensureTaskSuccess(task.taskUid); - } - - async search(options: SearchOptions): Promise<SearchResponse> { - const result = await this.index.search(options.query, { - filter: options.filter?.map((f) => filterToMeiliSearchFilter(f)), - limit: options.limit, - offset: options.offset, - sort: options.sort?.map((s) => `${s.field}:${s.order}`), - attributesToRetrieve: ["id"], - showRankingScore: true, - }); - - return { - hits: result.hits.map((hit) => ({ - id: hit.id, - score: hit._rankingScore, - })), - totalHits: result.estimatedTotalHits ?? 0, - processingTimeMs: result.processingTimeMs, - }; - } - - async clearIndex(): Promise<void> { - const task = await this.index.deleteAllDocuments(); - await this.ensureTaskSuccess(task.taskUid); - } - - private async ensureTaskSuccess(taskUid: number): Promise<void> { - const task = await this.index.waitForTask(taskUid, { - intervalMs: 200, - timeOutMs: serverConfig.search.jobTimeoutSec * 1000 * 0.9, - }); - if (task.error) { - throw new Error(`Search task failed: ${task.error.message}`); - } - } -} - -export class MeiliSearchProvider implements PluginProvider<SearchIndexClient> { - private client: MeiliSearch | undefined; - private indexClient: SearchIndexClient | undefined; - private readonly indexName = "bookmarks"; - - constructor() { - if (MeiliSearchProvider.isConfigured()) { - this.client = new MeiliSearch({ - host: envConfig.MEILI_ADDR!, - apiKey: envConfig.MEILI_MASTER_KEY, - }); - } - } - - static isConfigured(): boolean { - return !!envConfig.MEILI_ADDR; - } - - async getClient(): Promise<SearchIndexClient | null> { - if (this.indexClient) { - return this.indexClient; - } - - if (!this.client) { - return null; - } - - const indices = await this.client.getIndexes(); - let indexFound = indices.results.find((i) => i.uid === this.indexName); - - if (!indexFound) { - const idx = await this.client.createIndex(this.indexName, { - primaryKey: "id", - }); - await this.client.waitForTask(idx.taskUid); - indexFound = await this.client.getIndex<BookmarkSearchDocument>( - this.indexName, - ); - } - - await this.configureIndex(indexFound); - this.indexClient = new MeiliSearchIndexClient(indexFound); - return this.indexClient; - } - - private async configureIndex( - index: Index<BookmarkSearchDocument>, - ): Promise<void> { - const desiredFilterableAttributes = ["id", "userId"].sort(); - const desiredSortableAttributes = ["createdAt"].sort(); - - const settings = await index.getSettings(); - - if ( - JSON.stringify(settings.filterableAttributes?.sort()) !== - JSON.stringify(desiredFilterableAttributes) - ) { - console.log( - `[meilisearch] Updating desired filterable attributes to ${desiredFilterableAttributes} from ${settings.filterableAttributes}`, - ); - const taskId = await index.updateFilterableAttributes( - desiredFilterableAttributes, - ); - await this.client!.waitForTask(taskId.taskUid); - } - - if ( - JSON.stringify(settings.sortableAttributes?.sort()) !== - JSON.stringify(desiredSortableAttributes) - ) { - console.log( - `[meilisearch] Updating desired sortable attributes to ${desiredSortableAttributes} from ${settings.sortableAttributes}`, - ); - const taskId = await index.updateSortableAttributes( - desiredSortableAttributes, - ); - await this.client!.waitForTask(taskId.taskUid); - } - } -} |
