/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-explicit-any */ import type * as S from "effect/Schema" import { type AnyWithProps } from "effect/unstable/rpc/Rpc" import * as Context from "../Context.js" import { type RpcDynamic } from "./RpcMiddleware.js" type Values> = T[keyof T] /** * Middleware is inactivate by default, the Key is optional in route context, and the service is optionally provided as Effect Context. * Unless explicitly configured as `true`. */ export type RpcContextMap = { // todo; rename Provides service: Service error: E contextActivation: true inverted: false } export declare namespace RpcContextMap { /** * Middleware is active by default, and provides the Service at Key in route context, and the Service is provided as Effect Context. * Unless explicitly omitted. */ export type Inverted = { service: Service error: E contextActivation: false inverted: true } export type Custom = { service: Service error: E contextActivation: C inverted: false } export type Any = { service: any error: S.Top contextActivation: any inverted: boolean } } export type GetContextConfig> = { [K in keyof RequestContextMap]?: RequestContextMap[K]["inverted"] extends true ? RequestContextMap[K]["contextActivation"] extends true ? false : RequestContextMap[K]["contextActivation"] extends false ? true : RequestContextMap[K]["contextActivation"] : RequestContextMap[K]["contextActivation"] } export type GetEffectContext, T> = Values< // inverted: contextActivation is false => remove if explicitly set to true (like allowAnonymous: true disables auth and auth service and related errors) & { [ key in keyof RequestContextMap as RequestContextMap[key]["contextActivation"] extends true ? never : key extends keyof T ? T[key] extends true ? never : key : key ]: // TODO: or as an Optional available? RequestContextMap[key]["service"] } // normal: contextActivation is true => add if explicitly set to true & { [ key in keyof RequestContextMap as RequestContextMap[key]["contextActivation"] extends false ? never : key extends keyof T ? T[key] extends true ? key : never : never ]: // TODO: or as an Optional available? RequestContextMap[key]["service"] } > export type GetEffectError, T> = Values< // inverted: contextActivation is false => remove if explicitly set to true (like allowAnonymous: true disables auth and auth service and related errors) & { [ key in keyof RequestContextMap as RequestContextMap[key]["contextActivation"] extends true ? never : key extends keyof T ? T[key] extends true ? never : key : key ]: // TODO: or as an Optional available? RequestContextMap[key]["error"] } // normal: contextActivation is true => add if explicitly set to true & { [ key in keyof RequestContextMap as RequestContextMap[key]["contextActivation"] extends false ? never : key extends keyof T ? T[key] extends true ? key : never : never ]: // TODO: or as an Optional available? RequestContextMap[key]["error"] } > const tag = Context.Service("RequestContextConfig") export const makeMap = >(config: Config) => { const cls = class { readonly config: Config constructor() { this.config = config } } return Object.assign(cls, { config, /** Retrieves RequestContextConfig out of the Rpc annotations */ getConfig: (rpc: AnyWithProps): GetContextConfig => { return Context.getOrElse(rpc.annotations, tag as any, () => ({})) }, /** Adapter used when setting the dynamic prop on a middleware implementation */ get: < Key extends (keyof Config) & string >(key: Key): RpcDynamic => ({ key, settings: { service: config[key]!["service"] } as Config[Key] }) }) } export const make = () => ( error: E ): RpcContextMap => ({ service: null as Service, error, contextActivation: true, inverted: false }) export const makeInverted = () => ( error: E ): RpcContextMap.Inverted => ({ service: null as Service, error, contextActivation: false, inverted: true }) export const makeCustom = () => ( error: E, contextActivation: C ): RpcContextMap.Custom => ({ service: null as Service, error, contextActivation, inverted: false }) export type RequestContextMapTagAny = { readonly config: Record }