| 1 | import { SharedAccountError } from "@t3tools/contracts"; |
| 2 | import * as Context from "effect/Context"; |
| 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as Layer from "effect/Layer"; |
| 5 | import * as Option from "effect/Option"; |
| 6 | import * as Redacted from "effect/Redacted"; |
| 7 | import * as Schema from "effect/Schema"; |
| 8 | import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; |
| 9 | |
| 10 | const Connection = Schema.Struct({ url: Schema.String, token: Schema.NonEmptyString }); |
| 11 | const decode = Schema.decodeEffect(Schema.fromJsonString(Connection)); |
| 12 | const encode = Schema.encodeEffect(Schema.fromJsonString(Connection)); |
| 13 | |
| 14 | export class SharedServer extends Context.Service< |
| 15 | SharedServer, |
| 16 | { |
| 17 | readonly connection: Effect.Effect<Option.Option<typeof Connection.Type>, SharedAccountError>; |
| 18 | readonly save: (connection: typeof Connection.Type) => Effect.Effect<void, SharedAccountError>; |
| 19 | readonly disconnect: Effect.Effect<void, SharedAccountError>; |
| 20 | } |
| 21 | >()("t3/environment/SharedServer") {} |
| 22 | |
| 23 | export const layer = Layer.effect( |
| 24 | SharedServer, |
| 25 | Effect.gen(function* () { |
| 26 | const secrets = yield* ServerSecretStore.ServerSecretStore; |
| 27 | const storageError = (cause: unknown) => |
| 28 | new SharedAccountError({ reason: "storage", cause: Redacted.make(cause) }); |
| 29 | return SharedServer.of({ |
| 30 | connection: secrets.get("shared-server").pipe( |
| 31 | Effect.flatMap((bytes) => |
| 32 | Option.isNone(bytes) |
| 33 | ? Effect.succeedNone |
| 34 | : decode(new TextDecoder().decode(bytes.value)).pipe(Effect.asSome), |
| 35 | ), |
| 36 | Effect.mapError(storageError), |
| 37 | ), |
| 38 | save: (value) => |
| 39 | encode(value).pipe( |
| 40 | Effect.flatMap((json) => secrets.set("shared-server", new TextEncoder().encode(json))), |
| 41 | Effect.mapError(storageError), |
| 42 | ), |
| 43 | disconnect: secrets.remove("shared-server").pipe(Effect.mapError(storageError)), |
| 44 | }); |
| 45 | }), |
| 46 | ); |