1import { EnvironmentRegistry, removedWithRelay } from "@t3tools/client-runtime/connection";
2import { createRuntimeCommand } from "@t3tools/client-runtime/state/runtime";
3import * as Effect from "effect/Effect";
4import * as Schema from "effect/Schema";
5import * as SubscriptionRef from "effect/SubscriptionRef";
6
7import { connectionAtomRuntime } from "../../connection/runtime";
8import { archiveCloudComposerDrafts } from "../../state/use-composer-drafts";
9
10export class CloudDraftArchiveError extends Schema.TaggedError<CloudDraftArchiveError>()(
11 "CloudDraftArchiveError",
12 {
13 environmentCount: Schema.Number,
14 hasAccountId: Schema.Boolean,
15 cause: Schema.Defect(),
16 },
17) {
18 override get message(): string {
19 return `Could not preserve local drafts for ${this.environmentCount} cloud environments before sign-out.`;
20 }
21}
22
23export const removeCloudEnvironments = createRuntimeCommand(connectionAtomRuntime, {
24 label: "cloud:preserve-drafts-and-remove-environments",
25 execute: Effect.fn("removeCloudEnvironments")(function* (accountId: string | null) {
26 const registry = yield* EnvironmentRegistry.EnvironmentRegistry;
27 const entries = yield* SubscriptionRef.get(registry.entries);
28 const environmentIds = new Set(
29 [...entries.values()]
30 // Only environments that sign-out removes entirely lose their drafts.
31 .filter(removedWithRelay)
32 .map((entry) => entry.target.environmentId),
33 );
34 // Credentials are already revoked. A failed backup must leave the local
35 // owners intact so a later sign-in can retry without losing their files.
36 yield* Effect.tryPromise({
37 try: () => archiveCloudComposerDrafts(accountId, environmentIds),
38 catch: (cause) =>
39 new CloudDraftArchiveError({
40 environmentCount: environmentIds.size,
41 hasAccountId: accountId !== null,
42 cause,
43 }),
44 });
45 yield* registry.removeRelayEnvironments();
46 }),
47});