1import type * as runtime from "@cloudflare/workers-types";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import { Worker, WorkerEnvironment } from "../Workers/Worker.ts";
5import { type SearchIndexClient, SearchIndex } from "./SearchIndex.ts";
6import type { Index } from "./VectorizeIndex.ts";
7
8export const SearchIndexBinding = Layer.effect(
9 SearchIndex,
10 Effect.gen(function* () {
11 const env = yield* WorkerEnvironment;
12 const host = yield* Worker;
13
14 return Effect.fn(function* (index: Index) {
15 if (!globalThis.__ALCHEMY_RUNTIME__) {
16 yield* host.bind`${index}`({
17 bindings: [
18 {
19 type: "vectorize",
20 name: index.LogicalId,
21 indexName: index.indexName,
22 },
23 ],
24 });
25 }
26
27 const rawEff = Effect.sync(
28 () => (env as Record<string, runtime.Vectorize>)[index.LogicalId]!,
29 );
30
31 const withRuntime = <A>(fn: (raw: runtime.Vectorize) => Promise<A>) =>
32 Effect.flatMap(rawEff, (raw) => Effect.promise(() => fn(raw)));
33
34 return {
35 raw: rawEff,
36 describe: () => withRuntime((raw) => raw.describe()),
37 query: (vector, options) =>
38 withRuntime((raw) => raw.query(vector, options)),
39 queryById: (vectorId, options) =>
40 withRuntime((raw) => raw.queryById(vectorId, options)),
41 insert: (vectors) => withRuntime((raw) => raw.insert(vectors)),
42 upsert: (vectors) => withRuntime((raw) => raw.upsert(vectors)),
43 deleteByIds: (ids) => withRuntime((raw) => raw.deleteByIds(ids)),
44 getByIds: (ids) => withRuntime((raw) => raw.getByIds(ids)),
45 } satisfies SearchIndexClient;
46 });
47 }),
48);