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