1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4
5/**
6 * Shared HTTP scaffolding for the geo-places runtime bindings.
7 *
8 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
9 * thin `Layer.effect(Cap, makeGeoPlacesHttpBinding({ … }))` over the builder
10 * below. Everything except the operation and the IAM action is boilerplate.
11 *
12 * geo-places is a standalone, pay-per-call Amazon Location API with no
13 * resource to manage: every action authorizes account-wide through the
14 * singleton `provider/default`, so the builder always grants on
15 * `Resource: ["*"]` and the capability takes no arguments.
16 */
17export const makeGeoPlacesHttpBinding = <I extends object, A, E, R>(options: {
18 /**
19 * Short capability name used in the binding sid and runtime span, e.g.
20 * `"Geocode"`.
21 */
22 capability: string;
23 /** IAM actions granted on `Resource: ["*"]`. */
24 iamActions: readonly string[];
25 /** The distilled operation implementing the capability. */
26 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
27}) =>
28 Effect.gen(function* () {
29 const op = yield* options.operation;
30
31 return Effect.fn(function* () {
32 if (!globalThis.__ALCHEMY_RUNTIME__) {
33 const host = yield* Binding.Host;
34 if (isBindingHost(host)) {
35 yield* host.bind`Allow(${host}, AWS.GeoPlaces.${options.capability}())`(
36 {
37 policyStatements: [
38 {
39 Effect: "Allow",
40 Action: [...options.iamActions],
41 // geo-places is a standalone, account-wide pay-per-call API
42 // scoped through the singleton `provider/default`; the
43 // operations have no per-resource ARN.
44 Resource: ["*"],
45 },
46 ],
47 },
48 );
49 }
50 }
51 return Effect.fn(`AWS.GeoPlaces.${options.capability}`)(function* (
52 request: I,
53 ) {
54 return yield* op(request);
55 });
56 });
57 });