1import * as cloudchannel from "@distilled.cloud/gcp/cloudchannel_v1";
2import * as Effect from "effect/Effect";
3import { MinimumLogLevel } from "effect/References";
4import * as Schedule from "effect/Schedule";
5
6export const logLevel = Effect.provideService(
7 MinimumLogLevel,
8 process.env.DEBUG ? "Debug" : "Info",
9);
10
11// Cloud Channel needs a reseller/distributor account and credentials with the
12// apps.order scope; the service account profile is rejected with Forbidden:
13// "Request had insufficient authentication scopes." Set
14// GOOGLE_CLOUDCHANNEL_ACCOUNT to the reseller account to run the lifecycles.
15export const runLifecycle = !!process.env.GOOGLE_CLOUDCHANNEL_ACCOUNT?.trim();
16
17export const probeAccount =
18 process.env.GOOGLE_CLOUDCHANNEL_ACCOUNT?.trim() || "C00000000";
19
20export const probeAccountName = probeAccount.startsWith("accounts/")
21 ? probeAccount
22 : `accounts/${probeAccount}`;
23
24export const probePostalAddress: cloudchannel.GoogleTypePostalAddress = {
25 regionCode: "US",
26 postalCode: "94105",
27 administrativeArea: "CA",
28 locality: "San Francisco",
29 addressLines: ["100 Market Street"],
30};
31
32export const probeCustomerBody = {
33 orgDisplayName: "Alchemy Cloudchannel Probe",
34 domain: "alchemy-cloudchannel-probe.example.com",
35 orgPostalAddress: probePostalAddress,
36 primaryContactInfo: {
37 firstName: "Alchemy",
38 lastName: "Probe",
39 email: "admin@alchemy-cloudchannel-probe.example.com",
40 },
41} satisfies cloudchannel.GoogleCloudChannelV1Customer;
42
43export const waitUntilCustomerGone = (name: string) =>
44 cloudchannel.getAccountsCustomers({ name }).pipe(
45 Effect.as("found" as const),
46 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
47 Effect.repeat({
48 schedule: Schedule.spaced("1 second"),
49 until: (status) => status === "gone",
50 times: 10,
51 }),
52 );
53
54export const waitUntilPartnerCustomerGone = (name: string) =>
55 cloudchannel.getAccountsChannelPartnerLinksCustomers({ name }).pipe(
56 Effect.as("found" as const),
57 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
58 Effect.repeat({
59 schedule: Schedule.spaced("1 second"),
60 until: (status) => status === "gone",
61 times: 10,
62 }),
63 );
64
65export const waitUntilCustomerRepricingGone = (name: string) =>
66 cloudchannel.getAccountsCustomersCustomerRepricingConfigs({ name }).pipe(
67 Effect.as("found" as const),
68 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
69 Effect.repeat({
70 schedule: Schedule.spaced("1 second"),
71 until: (status) => status === "gone",
72 times: 10,
73 }),
74 );
75
76export const waitUntilPartnerRepricingGone = (name: string) =>
77 cloudchannel
78 .getAccountsChannelPartnerLinksChannelPartnerRepricingConfigs({ name })
79 .pipe(
80 Effect.as("found" as const),
81 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
82 Effect.repeat({
83 schedule: Schedule.spaced("1 second"),
84 until: (status) => status === "gone",
85 times: 10,
86 }),
87 );