1import * as bigquery from "@distilled.cloud/gcp/bigquery_v2";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import type { Dataset } from "./Dataset.ts";
5import { Query, type QueryRequest } from "./Query.ts";
6import { bindGcpHost } from "../Host.ts";
7import { grantFor } from "../HttpBinding.ts";
8
9/**
10 * HTTP implementation of {@link Query}.
11 *
12 * @layer
13 * @provides GCP.BigQuery.Query
14 */
15export const QueryHttp = Layer.effect(
16 Query,
17 Effect.gen(function* () {
18 const queryJobs = yield* bigquery.queryJobs;
19 return Effect.fn(function* (dataset: Dataset) {
20 yield* bindGcpHost({
21 tag: "GCP.BigQuery.Query",
22 resource: dataset,
23 iam: [
24 // bigquery.jobs.create is only grantable on the project.
25 { role: "roles/bigquery.jobUser" },
26 // Read access on this dataset only (its access list).
27 grantFor(
28 { role: "roles/bigquery.dataViewer", on: "bigquery.dataset" },
29 dataset.name,
30 ),
31 ],
32 });
33 const project = yield* dataset.project;
34 const datasetId = yield* dataset.datasetId;
35 const location = yield* dataset.location;
36 return Effect.fn(`GCP.BigQuery.Query(${dataset.LogicalId})`)(function* (
37 request: QueryRequest,
38 ) {
39 return yield* queryJobs({
40 projectId: yield* project,
41 body: {
42 useLegacySql: false,
43 location: yield* location,
44 ...request,
45 defaultDataset: request.defaultDataset ?? {
46 projectId: yield* project,
47 datasetId: yield* datasetId,
48 },
49 },
50 });
51 });
52 });
53 }),
54);