import { AuthClientMetadataDeviceType, AuthSessionId } from "@t3tools/contracts"; import { Option, Schema, Context } from "effect"; import type { Effect } from "effect"; import type { AuthSessionRepositoryError } from "../Errors.ts"; export const AuthSessionClientMetadataRecord = Schema.Struct({ label: Schema.NullOr(Schema.String), ipAddress: Schema.NullOr(Schema.String), userAgent: Schema.NullOr(Schema.String), deviceType: AuthClientMetadataDeviceType, os: Schema.NullOr(Schema.String), browser: Schema.NullOr(Schema.String), }); export type AuthSessionClientMetadataRecord = typeof AuthSessionClientMetadataRecord.Type; export const AuthSessionRecord = Schema.Struct({ sessionId: AuthSessionId, subject: Schema.String, role: Schema.Literals(["owner", "client"]), method: Schema.Literals(["browser-session-cookie", "bearer-session-token"]), client: AuthSessionClientMetadataRecord, issuedAt: Schema.DateTimeUtcFromString, expiresAt: Schema.DateTimeUtcFromString, lastConnectedAt: Schema.NullOr(Schema.DateTimeUtcFromString), revokedAt: Schema.NullOr(Schema.DateTimeUtcFromString), }); export type AuthSessionRecord = typeof AuthSessionRecord.Type; export const CreateAuthSessionInput = Schema.Struct({ sessionId: AuthSessionId, subject: Schema.String, role: Schema.Literals(["owner", "client"]), method: Schema.Literals(["browser-session-cookie", "bearer-session-token"]), client: AuthSessionClientMetadataRecord, issuedAt: Schema.DateTimeUtcFromString, expiresAt: Schema.DateTimeUtcFromString, }); export type CreateAuthSessionInput = typeof CreateAuthSessionInput.Type; export const GetAuthSessionByIdInput = Schema.Struct({ sessionId: AuthSessionId, }); export type GetAuthSessionByIdInput = typeof GetAuthSessionByIdInput.Type; export const ListActiveAuthSessionsInput = Schema.Struct({ now: Schema.DateTimeUtcFromString, }); export type ListActiveAuthSessionsInput = typeof ListActiveAuthSessionsInput.Type; export const RevokeAuthSessionInput = Schema.Struct({ sessionId: AuthSessionId, revokedAt: Schema.DateTimeUtcFromString, }); export type RevokeAuthSessionInput = typeof RevokeAuthSessionInput.Type; export const RevokeOtherAuthSessionsInput = Schema.Struct({ currentSessionId: AuthSessionId, revokedAt: Schema.DateTimeUtcFromString, }); export type RevokeOtherAuthSessionsInput = typeof RevokeOtherAuthSessionsInput.Type; export const SetAuthSessionLastConnectedAtInput = Schema.Struct({ sessionId: AuthSessionId, lastConnectedAt: Schema.DateTimeUtcFromString, }); export type SetAuthSessionLastConnectedAtInput = typeof SetAuthSessionLastConnectedAtInput.Type; export interface AuthSessionRepositoryShape { readonly create: ( input: CreateAuthSessionInput, ) => Effect.Effect; readonly getById: ( input: GetAuthSessionByIdInput, ) => Effect.Effect, AuthSessionRepositoryError>; readonly listActive: ( input: ListActiveAuthSessionsInput, ) => Effect.Effect, AuthSessionRepositoryError>; readonly revoke: ( input: RevokeAuthSessionInput, ) => Effect.Effect; readonly revokeAllExcept: ( input: RevokeOtherAuthSessionsInput, ) => Effect.Effect, AuthSessionRepositoryError>; readonly setLastConnectedAt: ( input: SetAuthSessionLastConnectedAtInput, ) => Effect.Effect; } export class AuthSessionRepository extends Context.Service< AuthSessionRepository, AuthSessionRepositoryShape >()("t3/persistence/Services/AuthSessions/AuthSessionRepository") {}