1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as vault from "@distilled.cloud/gcp/vault_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import * as Schedule from "effect/Schedule";
7import {
8 logLevel,
9 runAccountLifecycle,
10 sampleMailQuery,
11 vaultAccount,
12} from "./common.ts";
13
14const { test } = Test.make({ providers: GCP.providers() });
15
16const waitUntilGone = (matterId: string, savedQueryId: string) =>
17 vault.getMattersSavedQueries({ matterId, savedQueryId }).pipe(
18 Effect.as("found" as const),
19 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
20 Effect.repeat({
21 schedule: Schedule.spaced("1 second"),
22 until: (status) => status === "gone",
23 times: 10,
24 }),
25 );
26
27test.provider(
28 "getMattersSavedQueries on a missing saved query fails with a typed tag",
29 (stack) =>
30 Effect.gen(function* () {
31 yield* stack.destroy();
32
33 const error = yield* Effect.flip(
34 vault.getMattersSavedQueries({
35 matterId: "alchemy-missing-matter",
36 savedQueryId: "alchemy-missing-query",
37 }),
38 );
39 expect(error._tag).toEqual("VaultScopeInsufficient");
40
41 yield* stack.destroy();
42 }).pipe(logLevel),
43 { tags: ["provider:gcp", "provider:gcp:vault", "live"], timeout: 90_000 },
44);
45
46test.provider.skipIf(!!process.env.GCP_TEST_VAULT)(
47 "createMattersSavedQueries without Vault access fails with a typed tag",
48 (stack) =>
49 Effect.gen(function* () {
50 yield* stack.destroy();
51
52 const error = yield* Effect.flip(
53 vault.createMattersSavedQueries({
54 matterId: "alchemy-missing-matter",
55 body: {
56 displayName: "Alchemy Vault Saved Query Probe",
57 query: sampleMailQuery("probe@example.com"),
58 },
59 }),
60 );
61 expect(error._tag).toEqual("VaultScopeInsufficient");
62
63 yield* stack.destroy();
64 }).pipe(logLevel),
65 { tags: ["provider:gcp", "provider:gcp:vault", "live"], timeout: 90_000 },
66);
67
68test.provider.skipIf(!runAccountLifecycle)(
69 "create and delete a saved query",
70 (stack) =>
71 Effect.gen(function* () {
72 yield* stack.destroy();
73
74 const email = vaultAccount ?? "";
75
76 const created = yield* stack.deploy(
77 Effect.gen(function* () {
78 const matter = yield* GCP.Vault.Matter("QueryCase", {
79 name: "Query Case",
80 description: "saved query parent",
81 });
82 const saved = yield* GCP.Vault.MattersSavedQuery("Contracts", {
83 matterId: matter.matterId,
84 displayName: "contracts",
85 query: sampleMailQuery(email),
86 });
87 return { matter, saved };
88 }),
89 );
90
91 expect(created.saved.savedQueryId.length).toBeGreaterThan(0);
92 expect(created.saved.matterId).toEqual(created.matter.matterId);
93 expect(created.saved.displayName).toEqual("contracts");
94
95 const fetched = yield* vault.getMattersSavedQueries({
96 matterId: created.saved.matterId,
97 savedQueryId: created.saved.savedQueryId,
98 });
99 expect(fetched.savedQueryId).toEqual(created.saved.savedQueryId);
100 expect(fetched.displayName).toContain("[alchemy ");
101
102 yield* stack.destroy();
103
104 const gone = yield* waitUntilGone(
105 created.saved.matterId,
106 created.saved.savedQueryId,
107 );
108 expect(gone).toEqual("gone");
109 }).pipe(logLevel),
110 { tags: ["provider:gcp", "provider:gcp:vault", "live"], timeout: 90_000 },
111);