1import * as cloudtrail from "@distilled.cloud/aws/cloudtrail";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Binding from "../../Binding.ts";
5import { isBindingHost } from "../Lambda/Function.ts";
6import type { EventDataStore } from "./EventDataStore.ts";
7import { StartQuery, type StartQueryRequest } from "./StartQuery.ts";
8
9/**
10 * Bespoke (not scaffolded): the runtime callable resolves the bound store's
11 * ID out of its ARN and threads it through a `QueryStatement` callback —
12 * CloudTrail Lake SQL references the store by ID in the `FROM` clause rather
13 * than as a request field.
14 */
15export const StartQueryHttp = Layer.effect(
16 StartQuery,
17 Effect.gen(function* () {
18 const startQuery = yield* cloudtrail.startQuery;
19
20 return Effect.fn(function* (store: EventDataStore) {
21 const Arn = yield* store.eventDataStoreArn;
22 if (!globalThis.__ALCHEMY_RUNTIME__) {
23 const host = yield* Binding.Host;
24 if (isBindingHost(host)) {
25 yield* host.bind`Allow(${host}, AWS.CloudTrail.StartQuery(${store}))`(
26 {
27 policyStatements: [
28 {
29 Effect: "Allow",
30 Action: ["cloudtrail:StartQuery"],
31 Resource: [store.eventDataStoreArn],
32 },
33 ],
34 },
35 );
36 }
37 }
38 return Effect.fn(`AWS.CloudTrail.StartQuery(${store.LogicalId})`)(
39 function* (request: StartQueryRequest) {
40 const arn = yield* Arn;
41 const eventDataStoreId = arn.split("/").pop()!;
42 const { QueryStatement, ...rest } = request;
43 return yield* startQuery({
44 ...rest,
45 QueryStatement:
46 typeof QueryStatement === "function"
47 ? QueryStatement(eventDataStoreId)
48 : QueryStatement,
49 });
50 },
51 );
52 });
53 }),
54);