import type { AuthClientMetadata, AuthClientSession, AuthSessionId, ServerAuthSessionMethod, } from "@t3tools/contracts"; import { Data, DateTime, Duration, Context } from "effect"; import type { Effect, Stream } from "effect"; 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") {}