1import { GcpEnvironment } from "@/GCP/Environment";
2import * as GCP from "@/GCP";
3import * as Test from "@/Test/Alchemy";
4import * as discoveryengine from "@distilled.cloud/gcp/discoveryengine_v1";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import { MinimumLogLevel } from "effect/References";
8import * as Schedule from "effect/Schedule";
9import { ensureDataStore, quotaTolerant } from "./parent.ts";
10
11const { test } = Test.make({ providers: GCP.providers() });
12
13const logLevel = Effect.provideService(
14 MinimumLogLevel,
15 process.env.DEBUG ? "Debug" : "Info",
16);
17
18const runLifecycle = !process.env.FAST;
19const parentId = "alchds3site";
20
21const waitUntilGone = (name: string) =>
22 discoveryengine
23 .getProjectsLocationsDataStoresSiteSearchEngineTargetSites({ name })
24 .pipe(
25 Effect.as("found" as const),
26 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
27 Effect.repeat({
28 schedule: Schedule.spaced("2 seconds"),
29 until: (status) => status === "gone",
30 times: 10,
31 }),
32 );
33
34test.provider(
35 "getProjectsLocationsDataStoresSiteSearchEngineTargetSites on a missing site fails with a typed tag",
36 (stack) =>
37 Effect.gen(function* () {
38 const { project } = yield* GcpEnvironment.current;
39
40 yield* stack.destroy();
41
42 const error = yield* Effect.flip(
43 discoveryengine.getProjectsLocationsDataStoresSiteSearchEngineTargetSites(
44 {
45 name: `projects/${project}/locations/global/dataStores/alchemy-missing/siteSearchEngine/targetSites/alchemy-missing`,
46 },
47 ),
48 );
49 expect(error._tag).toEqual("NotFound");
50
51 yield* stack.destroy();
52 }).pipe(logLevel, quotaTolerant),
53 {
54 tags: ["provider:gcp", "provider:gcp:discoveryengine", "live"],
55 timeout: 90_000,
56 },
57);
58
59test.provider.skipIf(!runLifecycle)(
60 "create, update, and delete a site search target site",
61 (stack) =>
62 Effect.gen(function* () {
63 const { project } = yield* GcpEnvironment.current;
64
65 yield* stack.destroy();
66
67 const parent = yield* ensureDataStore(project, parentId, {
68 contentConfig: "PUBLIC_WEBSITE",
69 });
70
71 const created = yield* stack.deploy(
72 Effect.gen(function* () {
73 return yield* GCP.DiscoveryEngine.DataStoresSiteSearchEngineTargetSite(
74 "Docs",
75 {
76 dataStore: parent.name ?? "",
77 providedUriPattern: "www.example.com/alchemy-docs/*",
78 type: "INCLUDE",
79 },
80 );
81 }),
82 );
83
84 expect(created.name).toContain("/targetSites/");
85 expect(created.providedUriPattern).toEqual(
86 "www.example.com/alchemy-docs/*",
87 );
88
89 const fetched =
90 yield* discoveryengine.getProjectsLocationsDataStoresSiteSearchEngineTargetSites(
91 { name: created.name },
92 );
93 expect(fetched.name).toEqual(created.name);
94
95 const updated = yield* stack.deploy(
96 Effect.gen(function* () {
97 return yield* GCP.DiscoveryEngine.DataStoresSiteSearchEngineTargetSite(
98 "Docs",
99 {
100 dataStore: parent.name ?? "",
101 providedUriPattern: "www.example.com/alchemy-docs/*",
102 type: "INCLUDE",
103 },
104 );
105 }),
106 );
107
108 expect(updated.name).toEqual(created.name);
109
110 yield* stack.destroy();
111
112 const gone = yield* waitUntilGone(created.name);
113 expect(gone).toEqual("gone");
114 }).pipe(logLevel, quotaTolerant),
115 {
116 tags: ["provider:gcp", "provider:gcp:discoveryengine", "live"],
117 timeout: 120_000,
118 },
119);