1import * as Effect from "effect/Effect";
2import type { Model } from "./Model.ts";
3import type { ModelsVersion } from "./ModelsVersion.ts";
4import { bindGcpHost } from "../Host.ts";
5import { grantFor, type BindingIam, type GcpHttpOp } from "../HttpBinding.ts";
6
7/**
8 * Shared HTTP scaffolding for AI Platform (legacy ML Engine) bindings.
9 * NOT exported from index.ts.
10 */
11export const makeModelHttpBinding = <
12 I extends { name?: string },
13 A,
14 E,
15>(options: {
16 tag: string;
17 iam: BindingIam;
18 operation: GcpHttpOp<I, A, E>;
19}) =>
20 Effect.gen(function* () {
21 const run = yield* options.operation;
22 return Effect.fn(function* (model: Model) {
23 yield* bindGcpHost({
24 tag: options.tag,
25 resource: model,
26 iam: [grantFor(options.iam, model.name)],
27 });
28 const name = yield* model.name;
29 return Effect.fn(`${options.tag}(${model.LogicalId})`)(function* (
30 request?: Omit<I, "name">,
31 ) {
32 return yield* run({
33 ...(request as I),
34 name: yield* name,
35 } as I);
36 });
37 });
38 });
39
40/**
41 * Versions have no IAM policy of their own; `iam.on` (`ml.model`) is
42 * granted on the version's parent model.
43 */
44export const makeVersionHttpBinding = <
45 I extends { name?: string },
46 A,
47 E,
48>(options: {
49 tag: string;
50 iam: BindingIam;
51 operation: GcpHttpOp<I, A, E>;
52}) =>
53 Effect.gen(function* () {
54 const run = yield* options.operation;
55 return Effect.fn(function* (version: ModelsVersion) {
56 yield* bindGcpHost({
57 tag: options.tag,
58 resource: version,
59 iam: [grantFor(options.iam, version.model)],
60 });
61 const name = yield* version.name;
62 return Effect.fn(`${options.tag}(${version.LogicalId})`)(function* (
63 request?: Omit<I, "name">,
64 ) {
65 return yield* run({
66 ...(request as I),
67 name: yield* name,
68 } as I);
69 });
70 });
71 });