| 1 | import * as Cloudflare from "@/Cloudflare"; |
| 2 | import * as Alchemy from "@/index"; |
| 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as path from "pathe"; |
| 5 | import AiSearchEffectBindingsWorker from "./effect-bindings-worker.ts"; |
| 6 | |
| 7 | /** |
| 8 | * Deploys two Workers covering both AI Search binding flavors via both |
| 9 | * access styles: |
| 10 | * - The async worker takes the bindings through `env` (`SEARCH` is a |
| 11 | * single-instance `ai_search` binding; `NS` is an `ai_search_namespace` |
| 12 | * binding) and reads them as raw runtime objects. |
| 13 | * - The Effect worker attaches the same two binding flavors via |
| 14 | * `Cloudflare.AI.Search.Search(...)` / `Cloudflare.AI.SearchNamespace(...)` |
| 15 | * and reads them through the Effect-native client. |
| 16 | * |
| 17 | * The single-instance binding is sourced from the `AiSearch` construct (not |
| 18 | * the low-level `AiSearchInstance`), proving the construct's result is usable |
| 19 | * anywhere an `AiSearchInstance` is — here, passed straight to a Worker's |
| 20 | * `env`. The construct's `source` references the bucket and the worker's |
| 21 | * `env` references the search + namespace, so the engine orders the deploy |
| 22 | * bucket → instance/namespace → worker. |
| 23 | */ |
| 24 | export default Alchemy.Stack( |
| 25 | "AiSearchBindingsStack", |
| 26 | { |
| 27 | providers: Cloudflare.providers(), |
| 28 | state: Cloudflare.state(), |
| 29 | }, |
| 30 | Effect.gen(function* () { |
| 31 | const bucket = yield* Cloudflare.R2.Bucket("AiSearchBindingBucket", { |
| 32 | forceDestroy: true, |
| 33 | }); |
| 34 | const namespace = yield* Cloudflare.AI.SearchNamespace( |
| 35 | "AiSearchBindingNs", |
| 36 | {}, |
| 37 | ); |
| 38 | const search = yield* Cloudflare.AI.Search("AiSearchBindingInstance", { |
| 39 | source: bucket, |
| 40 | }); |
| 41 | const asyncWorker = yield* Cloudflare.Worker("AiSearchBindingsWorker", { |
| 42 | main: path.resolve(import.meta.dirname, "bindings-worker.ts"), |
| 43 | workersDev: true, |
| 44 | env: { SEARCH: search, NS: namespace }, |
| 45 | }); |
| 46 | const effectWorker = yield* AiSearchEffectBindingsWorker; |
| 47 | return { |
| 48 | url: asyncWorker.url.as<string>(), |
| 49 | effectUrl: effectWorker.url.as<string>(), |
| 50 | }; |
| 51 | }), |
| 52 | ); |