import type { AuthClientMetadata, AuthClientSession, AuthSessionId, ServerAuthSessionMethod, } from "@t3tools/contracts"; import * as Data from "effect/Data"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Context from "effect/Context"; import type * as Effect from "effect/Effect"; import type * as Stream from "effect/Stream"; export type SessionRole = "owner" | "client"; export interface IssuedSession { readonly sessionId: AuthSessionId; readonly token: string; readonly method: ServerAuthSessionMethod; readonly client: AuthClientMetadata; readonly expiresAt: DateTime.DateTime; readonly role: SessionRole; } export interface VerifiedSession { readonly sessionId: AuthSessionId; readonly token: string; readonly method: ServerAuthSessionMethod; readonly client: AuthClientMetadata; readonly expiresAt?: DateTime.DateTime; readonly subject: string; readonly role: SessionRole; } export type SessionCredentialChange = | { readonly type: "clientUpserted"; readonly clientSession: AuthClientSession; } | { readonly type: "clientRemoved"; readonly sessionId: AuthSessionId; }; export class SessionCredentialError extends Data.TaggedError("SessionCredentialError")<{ readonly message: string; readonly cause?: unknown; }> {} export interface SessionCredentialServiceShape { readonly cookieName: string; readonly issue: (input?: { readonly ttl?: Duration.Duration; readonly subject?: string; readonly method?: ServerAuthSessionMethod; readonly role?: SessionRole; readonly client?: AuthClientMetadata; }) => Effect.Effect; readonly verify: (token: string) => Effect.Effect; readonly issueWebSocketToken: ( sessionId: AuthSessionId, input?: { readonly ttl?: Duration.Duration; }, ) => Effect.Effect< { readonly token: string; readonly expiresAt: DateTime.DateTime; }, SessionCredentialError >; readonly verifyWebSocketToken: ( token: string, ) => Effect.Effect; readonly listActive: () => Effect.Effect< ReadonlyArray, SessionCredentialError >; readonly streamChanges: Stream.Stream; readonly revoke: (sessionId: AuthSessionId) => Effect.Effect; readonly revokeAllExcept: ( sessionId: AuthSessionId, ) => Effect.Effect; readonly markConnected: (sessionId: AuthSessionId) => Effect.Effect; readonly markDisconnected: (sessionId: AuthSessionId) => Effect.Effect; } export class SessionCredentialService extends Context.Service< SessionCredentialService, SessionCredentialServiceShape >()("t3/auth/Services/SessionCredentialService") {}