1import * as Alchemy from "@/index.ts";
2import * as Cloudflare from "@/Cloudflare/index.ts";
3import * as Effect from "effect/Effect";
4import * as pathe from "pathe";
5import VectorizeEffectWorker from "./effect-worker.ts";
6import { ensureMetaIndex, TestIndex } from "./index-resource.ts";
7
8/**
9 * Async-style Worker: the shared Vectorize index is declared on `env`.
10 * `WorkerAsyncBindings` resolves it (via `isIndex`) into the native
11 * `vectorize` binding, so the plain `async fetch` handler in async-worker.ts
12 * gets `env.INDEX` as the runtime `Vectorize` binding.
13 */
14export const AsyncWorker = Cloudflare.Worker("VectorizeAsyncWorker", {
15 main: pathe.resolve(import.meta.dirname, "async-worker.ts"),
16 env: {
17 INDEX: TestIndex,
18 },
19});
20
21export type AsyncWorkerEnv = Cloudflare.InferEnv<typeof AsyncWorker>;
22
23/**
24 * One stack deploying BOTH binding styles against ONE shared index. The
25 * metadata index is declared at the stack level so it is created before either
26 * worker upserts (filtered queries require it to pre-exist the vectors).
27 */
28export default Alchemy.Stack(
29 "VectorizeBindingStack",
30 {
31 providers: Cloudflare.providers(),
32 state: Cloudflare.state(),
33 },
34 Effect.gen(function* () {
35 const index = yield* TestIndex;
36 yield* ensureMetaIndex(index);
37 const asyncWorker = yield* AsyncWorker;
38 const effectWorker = yield* VectorizeEffectWorker;
39
40 return {
41 indexName: index.indexName,
42 asyncWorkerUrl: asyncWorker.url.as<string>(),
43 effectWorkerUrl: effectWorker.url.as<string>(),
44 };
45 }),
46);