| ... | @@ -7,6 +7,7 @@ import { | ... | @@ -7,6 +7,7 @@ import { |
| 7 | import { RelayOkResponse } from "@t3tools/contracts/relay"; | 7 | import { RelayOkResponse } from "@t3tools/contracts/relay"; |
| 8 | import * as RelayClient from "@t3tools/shared/relayClient"; | 8 | import * as RelayClient from "@t3tools/shared/relayClient"; |
| 9 | import { withRelayClientTracing } from "@t3tools/shared/relayTracing"; | 9 | import { withRelayClientTracing } from "@t3tools/shared/relayTracing"; |
| | 10 | import * as Cause from "effect/Cause"; |
| 10 | import * as Console from "effect/Console"; | 11 | import * as Console from "effect/Console"; |
| 11 | import * as Duration from "effect/Duration"; | 12 | import * as Duration from "effect/Duration"; |
| 12 | import * as Effect from "effect/Effect"; | 13 | import * as Effect from "effect/Effect"; |
| ... | @@ -179,7 +180,7 @@ const withCloudCliSessionToken = <A, E, R>( | ... | @@ -179,7 +180,7 @@ const withCloudCliSessionToken = <A, E, R>( |
| 179 | type LiveCloudActionResult = | 180 | type LiveCloudActionResult = |
| 180 | | { readonly status: "not-running" } | 181 | | { readonly status: "not-running" } |
| 181 | | { readonly status: "succeeded" } | 182 | | { readonly status: "succeeded" } |
| 182 | | { readonly status: "failed"; readonly cause: unknown }; | 183 | | { readonly status: "failed"; readonly cause: Cause.Cause<unknown> }; |
| 183 | | 184 | |
| 184 | const runLiveCloudUnlink = Effect.fn("cloud.cli.run_live_unlink")(function* () { | 185 | const runLiveCloudUnlink = Effect.fn("cloud.cli.run_live_unlink")(function* () { |
| 185 | const config = yield* ServerConfig.ServerConfig; | 186 | const config = yield* ServerConfig.ServerConfig; |
| ... | @@ -211,6 +212,21 @@ type RelayUnlinkResult = | ... | @@ -211,6 +212,21 @@ type RelayUnlinkResult = |
| 211 | | { readonly status: "revoked" } | 212 | | { readonly status: "revoked" } |
| 212 | | { readonly status: "not-linked" }; | 213 | | { readonly status: "not-linked" }; |
| 213 | | 214 | |
| | 215 | type CloudDisconnectOperation = "live-server-unlink" | "relay-environment-unlink"; |
| | 216 | |
| | 217 | const logCloudDisconnectFailure = ( |
| | 218 | operation: CloudDisconnectOperation, |
| | 219 | clearAuthorization: boolean, |
| | 220 | cause: Cause.Cause<unknown>, |
| | 221 | ) => |
| | 222 | Effect.logWarning("T3 Connect disconnect operation failed.").pipe( |
| | 223 | Effect.annotateLogs({ |
| | 224 | operation, |
| | 225 | clearAuthorization, |
| | 226 | cause: Cause.pretty(cause), |
| | 227 | }), |
| | 228 | ); |
| | 229 | |
| 214 | const unlinkRelayEnvironment = Effect.fn("cloud.cli.unlink_relay_environment")(function* () { | 230 | const unlinkRelayEnvironment = Effect.fn("cloud.cli.unlink_relay_environment")(function* () { |
| 215 | const tokens = yield* CliTokenManager.CloudCliTokenManager; | 231 | const tokens = yield* CliTokenManager.CloudCliTokenManager; |
| 216 | const token = yield* tokens.getExisting; | 232 | const token = yield* tokens.getExisting; |
| ... | @@ -236,6 +252,42 @@ const unlinkRelayEnvironment = Effect.fn("cloud.cli.unlink_relay_environment")(f | ... | @@ -236,6 +252,42 @@ const unlinkRelayEnvironment = Effect.fn("cloud.cli.unlink_relay_environment")(f |
| 236 | : ({ status: "not-linked" } satisfies RelayUnlinkResult); | 252 | : ({ status: "not-linked" } satisfies RelayUnlinkResult); |
| 237 | }); | 253 | }); |
| 238 | | 254 | |
| | 255 | export const reportCloudDisconnectResults = Effect.fn("cloud.cli.report_disconnect_results")( |
| | 256 | function* (input: { |
| | 257 | readonly clearAuthorization: boolean; |
| | 258 | readonly liveResult: LiveCloudActionResult; |
| | 259 | readonly relayResult: Exit.Exit<RelayUnlinkResult, unknown>; |
| | 260 | }) { |
| | 261 | if (input.liveResult.status === "failed") { |
| | 262 | yield* logCloudDisconnectFailure( |
| | 263 | "live-server-unlink", |
| | 264 | input.clearAuthorization, |
| | 265 | input.liveResult.cause, |
| | 266 | ); |
| | 267 | yield* Console.warn( |
| | 268 | "T3 Connect is disabled, but the running server could not stop its tunnel.\nRestart that server to stop the connector.", |
| | 269 | ); |
| | 270 | } else { |
| | 271 | yield* Console.log("T3 Connect is disabled locally."); |
| | 272 | } |
| | 273 | |
| | 274 | if (Exit.isFailure(input.relayResult)) { |
| | 275 | yield* logCloudDisconnectFailure( |
| | 276 | "relay-environment-unlink", |
| | 277 | input.clearAuthorization, |
| | 278 | input.relayResult.cause, |
| | 279 | ); |
| | 280 | yield* Console.warn( |
| | 281 | input.clearAuthorization |
| | 282 | ? "Could not revoke the relay-side environment record before signing out.\nThe stored CLI authorization was still removed locally." |
| | 283 | : "Could not revoke the relay-side environment record yet.\nRun `t3 connect unlink` again when the relay is reachable.", |
| | 284 | ); |
| | 285 | } else if (input.relayResult.value.status === "revoked") { |
| | 286 | yield* Console.log("Revoked the relay-side environment record."); |
| | 287 | } |
| | 288 | }, |
| | 289 | ); |
| | 290 | |
| 239 | const disconnectCloud = Effect.fn("cloud.cli.disconnect")(function* (options: { | 291 | const disconnectCloud = Effect.fn("cloud.cli.disconnect")(function* (options: { |
| 240 | readonly clearAuthorization: boolean; | 292 | readonly clearAuthorization: boolean; |
| 241 | }) { | 293 | }) { |
| ... | @@ -249,23 +301,11 @@ const disconnectCloud = Effect.fn("cloud.cli.disconnect")(function* (options: { | ... | @@ -249,23 +301,11 @@ const disconnectCloud = Effect.fn("cloud.cli.disconnect")(function* (options: { |
| 249 | yield* tokens.clear; | 301 | yield* tokens.clear; |
| 250 | } | 302 | } |
| 251 | | 303 | |
| 252 | if (liveResult.status === "failed") { | 304 | yield* reportCloudDisconnectResults({ |
| 253 | yield* Console.warn( | 305 | clearAuthorization: options.clearAuthorization, |
| 254 | `T3 Connect is disabled, but the running server could not stop its tunnel: ${String(liveResult.cause)}\nRestart that server to stop the connector.`, | 306 | liveResult, |
| 255 | ); | 307 | relayResult, |
| 256 | } else { | 308 | }); |
| 257 | yield* Console.log("T3 Connect is disabled locally."); | | |
| 258 | } | | |
| 259 | | | |
| 260 | if (Exit.isFailure(relayResult)) { | | |
| 261 | yield* Console.warn( | | |
| 262 | options.clearAuthorization | | |
| 263 | ? `Could not revoke the relay-side environment record before signing out: ${String(relayResult.cause)}\nThe stored CLI authorization was still removed locally.` | | |
| 264 | : `Could not revoke the relay-side environment record yet: ${String(relayResult.cause)}\nRun \`t3 connect unlink\` again when the relay is reachable.`, | | |
| 265 | ); | | |
| 266 | } else if (relayResult.value.status === "revoked") { | | |
| 267 | yield* Console.log("Revoked the relay-side environment record."); | | |
| 268 | } | | |
| 269 | | 309 | |
| 270 | if (options.clearAuthorization) { | 310 | if (options.clearAuthorization) { |
| 271 | yield* Console.log("Signed out of T3 Connect locally."); | 311 | yield* Console.log("Signed out of T3 Connect locally."); |