1import * as sqladmin from "@distilled.cloud/gcp/sqladmin_v1";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Output from "../../Output.ts";
5import { ExecuteSql, type ExecuteSqlRequest } from "./ExecuteSql.ts";
6import type { Instance } from "./Instance.ts";
7import { bindGcpHost } from "../Host.ts";
8import { grantFor } from "../HttpBinding.ts";
9
10/**
11 * HTTP implementation of {@link ExecuteSql}.
12 *
13 * @layer
14 * @provides GCP.SQL.ExecuteSql
15 */
16export const ExecuteSqlHttp = Layer.effect(
17 ExecuteSql,
18 Effect.gen(function* () {
19 const execute = yield* sqladmin.executeSqlInstances;
20 return Effect.fn(function* (instance: Instance) {
21 yield* bindGcpHost({
22 tag: "GCP.SQL.ExecuteSql",
23 resource: instance,
24 // Cloud SQL has no instance-level IAM policy; an IAM Condition
25 // scopes the project grant to this instance.
26 iam: [
27 grantFor(
28 { role: "roles/cloudsql.instanceUser", scopeByCondition: true },
29 Output.interpolate`projects/${instance.project}/instances/${instance.instanceName}`,
30 ),
31 ],
32 });
33 const instanceName = yield* instance.instanceName;
34 const project = yield* instance.project;
35 return Effect.fn(`GCP.SQL.ExecuteSql(${instance.LogicalId})`)(function* (
36 request: ExecuteSqlRequest,
37 ) {
38 return yield* execute({
39 ...request,
40 instance: yield* instanceName,
41 project: yield* project,
42 });
43 });
44 });
45 }),
46);