1import { Credentials } from "@distilled.cloud/gcp/Credentials";
2import * as Effect from "effect/Effect";
3import * as HttpClient from "effect/http/HttpClient";
4import type { Collector } from "./Collector.ts";
5import { bindGcpHost } from "../Host.ts";
6import { type BindingIam, grantFor } from "../HttpBinding.ts";
7
8/**
9 * Shared HTTP scaffolding for Rapid Migration Assessment collector
10 * bindings. NOT exported from index.ts.
11 *
12 * Distilled ops are `OperationMethod`s: yield them once at Layer
13 * construction (after providing Credentials + HttpClient) so the inner
14 * runtime Effect is `Effect<A, E>` and does not leak `GcpOpContext`.
15 */
16export const makeCollectorHttpBinding = <
17 I extends { name?: string },
18 A,
19 E,
20>(options: {
21 tag: string;
22 iam: BindingIam;
23 operation: Effect.Effect<
24 (input: I) => Effect.Effect<A, E>,
25 never,
26 Credentials | HttpClient.HttpClient
27 > &
28 ((input: I) => Effect.Effect<A, E, Credentials | HttpClient.HttpClient>);
29}) =>
30 Effect.gen(function* () {
31 const run = yield* options.operation;
32 return Effect.fn(function* (collector: Collector) {
33 yield* bindGcpHost({
34 tag: options.tag,
35 resource: collector,
36 iam: [grantFor(options.iam, collector.name)],
37 });
38 const name = yield* collector.name;
39 return Effect.fn(`${options.tag}(${collector.LogicalId})`)(function* (
40 request?: Omit<I, "name">,
41 ) {
42 const collectorName = yield* name;
43 return yield* run({
44 ...(request ?? {}),
45 name: collectorName,
46 } as I);
47 });
48 });
49 });