135 lines · 4.4 KB · TypeScript
RawDownload
import { createClerkBridge } from "@clerk/electron";import { storage } from "@clerk/electron/storage";import * as Context from "effect/Context";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Schema from "effect/Schema";import * as Scope from "effect/Scope"; import { clerkFrontendApiHostnameFromPublishableKey } from "@t3tools/shared/relayAuth";import * as ElectronApp from "../electron/ElectronApp.ts";import * as ElectronProtocol from "../electron/ElectronProtocol.ts";import * as ElectronWindow from "../electron/ElectronWindow.ts";import * as DesktopEnvironment from "./DesktopEnvironment.ts"; declare const __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__: string | undefined; export class DesktopClerkBridgeInitializationError extends Schema.TaggedErrorClass<DesktopClerkBridgeInitializationError>()(  "DesktopClerkBridgeInitializationError",  {    stateDir: Schema.String,    isDevelopment: Schema.Boolean,    cause: Schema.Defect(),  },) {  override get message(): string {    return `Failed to initialize the desktop Clerk bridge for state directory "${this.stateDir}" (development: ${this.isDevelopment}).`;  }} export class DesktopClerkBridgeCleanupError extends Schema.TaggedErrorClass<DesktopClerkBridgeCleanupError>()(  "DesktopClerkBridgeCleanupError",  {    stateDir: Schema.String,    isDevelopment: Schema.Boolean,    cause: Schema.Defect(),  },) {  override get message(): string {    return `Failed to clean up the desktop Clerk bridge for state directory "${this.stateDir}" (development: ${this.isDevelopment}).`;  }} export class DesktopClerk extends Context.Service<  DesktopClerk,  {    readonly configure: Effect.Effect<      void,      never,      ElectronApp.ElectronApp | ElectronWindow.ElectronWindow | Scope.Scope    >;  }>()("@t3tools/desktop/app/DesktopClerk") {} export function resolveDesktopClerkFrontendApiHostname(  publishableKey: string | undefined,): string | undefined {  const normalizedKey = publishableKey?.trim();  if (!normalizedKey) return undefined;   try {    return clerkFrontendApiHostnameFromPublishableKey(normalizedKey);  } catch {    return undefined;  }} export const desktopClerkFrontendApiHostname = resolveDesktopClerkFrontendApiHostname(  typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined"    ? undefined    : __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__,); export function createDesktopClerkBridge(stateDir: string, isDevelopment: boolean) {  return createClerkBridge({    storage: storage({ path: stateDir }),    passkeys: true,    renderer: {      scheme: ElectronProtocol.getDesktopScheme(isDevelopment),      host: ElectronProtocol.DESKTOP_HOST,    },  });} export const make = Effect.gen(function* () {  const environment = yield* DesktopEnvironment.DesktopEnvironment;  yield* Effect.acquireRelease(    Effect.try({      try: () => createDesktopClerkBridge(environment.stateDir, environment.isDevelopment),      catch: (cause) =>        new DesktopClerkBridgeInitializationError({          stateDir: environment.stateDir,          isDevelopment: environment.isDevelopment,          cause,        }),    }),    (bridge) =>      Effect.try({        try: () => bridge.cleanup(),        catch: (cause) =>          new DesktopClerkBridgeCleanupError({            stateDir: environment.stateDir,            isDevelopment: environment.isDevelopment,            cause,          }),      }).pipe(Effect.orDie),  );   return DesktopClerk.of({    configure: Effect.gen(function* () {      const electronApp = yield* ElectronApp.ElectronApp;      const electronWindow = yield* ElectronWindow.ElectronWindow;      const context = yield* Effect.context<ElectronWindow.ElectronWindow>();      const runPromise = Effect.runPromiseWith(context);       if (!(yield* electronApp.requestSingleInstanceLock)) {        yield* electronApp.quit;        return yield* Effect.interrupt;      }       yield* electronApp.on("second-instance", () => {        void runPromise(          Effect.gen(function* () {            const mainWindow = yield* electronWindow.currentMainOrFirst;            if (Option.isSome(mainWindow)) {              yield* electronWindow.reveal(mainWindow.value);            }          }),        );      });    }).pipe(Effect.withSpan("desktop.clerk.configure")),  });}); export const layer = Layer.effect(DesktopClerk, make);