1import { Credentials } from "@distilled.cloud/gcp/Credentials";
2import * as Effect from "effect/Effect";
3import * as HttpClient from "effect/http/HttpClient";
4import type { Pipeline } from "./Pipeline.ts";
5import { bindGcpHost } from "../Host.ts";
6import { type BindingIam, grantFor } from "../HttpBinding.ts";
7
8/**
9 * Shared HTTP scaffolding for Data Pipelines bindings.
10 * NOT exported from index.ts.
11 *
12 * Distilled ops are `OperationMethod`s: yield them once at Layer construction
13 * (after providing Credentials + HttpClient) so the inner runtime Effect is
14 * `Effect<A, E>` and does not leak `GcpOpContext`.
15 */
16export const makePipelineHttpBinding = <
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* (pipeline: Pipeline) {
33 yield* bindGcpHost({
34 tag: options.tag,
35 resource: pipeline,
36 iam: [grantFor(options.iam, pipeline.name)],
37 });
38 const name = yield* pipeline.name;
39 return Effect.fn(`${options.tag}(${pipeline.LogicalId})`)(function* (
40 request?: Omit<I, "name">,
41 ) {
42 const pipelineName = yield* name;
43 return yield* run({
44 ...(request ?? {}),
45 name: pipelineName,
46 } as I);
47 });
48 });
49 });