1import type { GcpOpContext } from "@distilled.cloud/gcp/contentwarehouse_v1";
2import * as Effect from "effect/Effect";
3import type { Output } from "../../Output.ts";
4import type { Document } from "./Document.ts";
5import type { DocumentSchema } from "./DocumentSchema.ts";
6import type { RuleSet } from "./RuleSet.ts";
7import type { SynonymSet } from "./SynonymSet.ts";
8import { bindGcpHost } from "../Host.ts";
9import { grantFor, type BindingIam } from "../HttpBinding.ts";
10
11/**
12 * Distilled ops are OperationMethods: 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 */
16type GcpHttpOp<I, A, E> = Effect.Effect<
17 (input: I) => Effect.Effect<A, E>,
18 never,
19 GcpOpContext
20> &
21 ((input: I) => Effect.Effect<A, E, GcpOpContext>);
22
23const makeNamedHttpBinding = <
24 Resource extends { name: Output<string, never>; LogicalId: string },
25 I extends { name: string },
26 A,
27 E,
28>(options: {
29 tag: string;
30 iam: BindingIam;
31 operation: GcpHttpOp<I, A, E>;
32}) =>
33 Effect.gen(function* () {
34 const run = yield* options.operation;
35 return Effect.fn(function* (resource: Resource) {
36 yield* bindGcpHost({
37 tag: options.tag,
38 resource: resource,
39 iam: [grantFor(options.iam, resource.name)],
40 });
41 const name = yield* resource.name;
42 return Effect.fn(`${options.tag}(${resource.LogicalId})`)(function* (
43 request?: Omit<I, "name">,
44 ) {
45 const resourceName = yield* name;
46 return yield* run({
47 ...(request ?? {}),
48 name: resourceName,
49 } as I);
50 });
51 });
52 });
53
54/**
55 * Shared HTTP scaffolding for Content Warehouse bindings.
56 * NOT exported from index.ts.
57 */
58export const makeDocumentSchemaHttpBinding = <
59 I extends { name: string },
60 A,
61 E,
62>(options: {
63 tag: string;
64 iam: BindingIam;
65 operation: GcpHttpOp<I, A, E>;
66}) => makeNamedHttpBinding<DocumentSchema, I, A, E>(options);
67
68export const makeDocumentHttpBinding = <
69 I extends { name: string },
70 A,
71 E,
72>(options: {
73 tag: string;
74 iam: BindingIam;
75 operation: GcpHttpOp<I, A, E>;
76}) => makeNamedHttpBinding<Document, I, A, E>(options);
77
78export const makeRuleSetHttpBinding = <
79 I extends { name: string },
80 A,
81 E,
82>(options: {
83 tag: string;
84 iam: BindingIam;
85 operation: GcpHttpOp<I, A, E>;
86}) => makeNamedHttpBinding<RuleSet, I, A, E>(options);
87
88export const makeSynonymSetHttpBinding = <
89 I extends { name: string },
90 A,
91 E,
92>(options: {
93 tag: string;
94 iam: BindingIam;
95 operation: GcpHttpOp<I, A, E>;
96}) => makeNamedHttpBinding<SynonymSet, I, A, E>(options);