1import * as Effect from "effect/Effect";
2import * as Layer from "effect/Layer";
3import type * as HttpClient from "effect/http/HttpClient";
4import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
5import type { Credentials } from "../Credentials.ts";
6import { QuerySearchNamespace } from "./QuerySearchNamespace.ts";
7import {
8 makeLocalSearchNamespaceClient,
9 type SearchAuth,
10} from "./SearchHttpClient.ts";
11import type { SearchNamespace } from "./SearchNamespace.ts";
12
13/**
14 * Local implementation of the {@link QuerySearchNamespace} binding — queries an
15 * AI Search namespace over the Cloudflare HTTP API using the **current
16 * credentials** instead of a native Worker binding
17 * (`QuerySearchNamespaceBinding`).
18 *
19 * Provide it on an {@link Action} (or any deploy-time Effect) to `list`
20 * instances, run a multi-instance `search`, or `.get(instanceName)` a
21 * single-instance client — the same client you'd use inside a Worker. The
22 * namespace name is resolved at apply time through the ambient RuntimeContext.
23 *
24 * `raw` (the native `AiSearchNamespace` runtime handle) is unavailable outside a
25 * deployed Worker and dies if forced.
26 *
27 * @example List a namespace's instances from an Action
28 * ```typescript
29 * const Probe = Alchemy.Action(
30 * "Probe",
31 * Effect.gen(function* () {
32 * const ns = yield* Cloudflare.AI.QuerySearchNamespace(namespace);
33 * return Effect.fn(function* () {
34 * const { result } = yield* ns.list();
35 * return result.map((i) => i.id);
36 * });
37 * }).pipe(Effect.provide(Cloudflare.AI.QuerySearchNamespaceLocal)),
38 * );
39 * ```
40 */
41export const QuerySearchNamespaceLocal = Layer.effect(
42 QuerySearchNamespace,
43 Effect.gen(function* () {
44 const { accountId } = yield* yield* CloudflareEnvironment;
45 const context = yield* Effect.context<
46 Credentials | HttpClient.HttpClient
47 >();
48
49 const auth: SearchAuth = {
50 authorize: (eff) => eff.pipe(Effect.provideContext(context)),
51 accountId,
52 };
53
54 return Effect.fn(function* (namespace: SearchNamespace) {
55 // Deferred accessor — resolved against the tracker at apply time.
56 const name = yield* namespace.name;
57 return makeLocalSearchNamespaceClient(auth, name);
58 });
59 }),
60);