/** * @since 1.0.0 */ import * as Context from "effect/Context" import type * as Effect from "effect/Effect" import { hasProperty } from "effect/Predicate" import * as Schema from "effect/Schema" import type { Mutable, Simplify } from "effect/Types" import type * as HttpApiSecurity from "./HttpApiSecurity.js" import type * as HttpRouter from "./HttpRouter.js" /** * @since 1.0.0 * @category type ids */ export const TypeId: unique symbol = Symbol.for("@effect/platform/HttpApiMiddleware") /** * @since 1.0.0 * @category type ids */ export type TypeId = typeof TypeId /** * @since 1.0.0 * @category type ids */ export const SecurityTypeId: unique symbol = Symbol.for("@effect/platform/HttpApiMiddleware/Security") /** * @since 1.0.0 * @category type ids */ export type SecurityTypeId = typeof SecurityTypeId /** * @since 1.0.0 * @category guards */ export const isSecurity = (u: TagClassAny): u is TagClassSecurityAny => hasProperty(u, SecurityTypeId) /** * @since 1.0.0 * @category models */ export interface HttpApiMiddleware extends Effect.Effect {} /** * @since 1.0.0 * @category models */ export type HttpApiMiddlewareSecurity, Provides, E> = { readonly [K in keyof Security]: ( _: HttpApiSecurity.HttpApiSecurity.Type ) => Effect.Effect } /** * @since 1.0.0 * @category models */ export declare namespace HttpApiMiddleware { /** * @since 1.0.0 * @category models */ export interface Any { readonly [TypeId]: TypeId } /** * @since 1.0.0 * @category models */ export interface AnyId { readonly [TypeId]: { readonly provides: any } } /** * @since 1.0.0 * @category models */ export type Provides = A extends { readonly [TypeId]: { readonly provides: infer P } } ? P : never /** * @since 1.0.0 * @category models */ export type ExtractProvides = Provides> /** * @since 1.0.0 * @category models */ export type Error = A extends { readonly [TypeId]: { readonly failure: infer E } } ? E : never /** * @since 1.0.0 * @category models */ export type ErrorContext = A extends { readonly [TypeId]: { readonly failureContext: infer R } } ? R : never /** * @since 1.0.0 * @category models */ export type Only = Extract /** * @since 1.0.0 * @category models */ export type Without = Exclude } /** * @since 1.0.0 * @category models */ export type TagClass< Self, Name extends string, Options > = Options extends { readonly security: Record } ? TagClass.BaseSecurity< Self, Name, Options, Simplify< HttpApiMiddlewareSecurity< Options["security"], TagClass.Service, TagClass.FailureService > >, Options["security"] > : TagClass.Base< Self, Name, Options, HttpApiMiddleware< TagClass.Service, TagClass.FailureService > > /** * @since 1.0.0 * @category models */ export declare namespace TagClass { /** * @since 1.0.0 * @category models */ export type Provides = Options extends { readonly provides: Context.Tag readonly optional?: false } ? Context.Tag.Identifier : never /** * @since 1.0.0 * @category models */ export type Service = Options extends { readonly provides: Context.Tag } ? Context.Tag.Service : void /** * @since 1.0.0 * @category models */ export type FailureSchema = Options extends { readonly failure: Schema.Schema.All; readonly optional?: false } ? Options["failure"] : typeof Schema.Never /** * @since 1.0.0 * @category models */ export type Failure = Options extends { readonly failure: Schema.Schema; readonly optional?: false } ? _A : never /** * @since 1.0.0 * @category models */ export type FailureContext = Schema.Schema.Context> /** * @since 1.0.0 * @category models */ export type FailureService = Optional extends true ? unknown : Failure /** * @since 1.0.0 * @category models */ export type Optional = Options extends { readonly optional: true } ? true : false /** * @since 1.0.0 * @category models */ export interface Base extends Context.Tag { new(_: never): & Context.TagClassShape & { readonly [TypeId]: { readonly provides: Provides readonly failure: Failure readonly failureContext: FailureContext } } readonly [TypeId]: TypeId readonly optional: Optional readonly failure: FailureSchema readonly provides: Options extends { readonly provides: Context.Tag } ? Options["provides"] : undefined } /** * @since 1.0.0 * @category models */ export interface BaseSecurity< Self, Name extends string, Options, Service, Security extends Record > extends Base { readonly [SecurityTypeId]: SecurityTypeId readonly security: Security } } /** * @since 1.0.0 * @category models */ export interface TagClassAny extends Context.Tag { readonly [TypeId]: TypeId readonly optional: boolean readonly provides?: Context.Tag readonly failure: Schema.Schema.All } /** * @since 1.0.0 * @category models */ export interface TagClassSecurityAny extends TagClassAny { readonly [SecurityTypeId]: SecurityTypeId readonly security: Record } /** * @since 1.0.0 * @category tags */ export const Tag = (): < const Name extends string, const Options extends { readonly optional?: boolean readonly failure?: Schema.Schema.All readonly provides?: Context.Tag readonly security?: Record } >( id: Name, options?: Options | undefined ) => TagClass => ( id: string, options?: { readonly optional?: boolean readonly security?: Record readonly failure?: Schema.Schema.All readonly provides?: Context.Tag } ) => { const Err = globalThis.Error as any const limit = Err.stackTraceLimit Err.stackTraceLimit = 2 const creationError = new Err() Err.stackTraceLimit = limit function TagClass() {} const TagClass_ = TagClass as any as Mutable Object.setPrototypeOf(TagClass, Object.getPrototypeOf(Context.GenericTag(id))) TagClass.key = id Object.defineProperty(TagClass, "stack", { get() { return creationError.stack } }) TagClass_[TypeId] = TypeId TagClass_.failure = options?.optional === true || options?.failure === undefined ? Schema.Never : options.failure if (options?.provides) { TagClass_.provides = options.provides } TagClass_.optional = options?.optional ?? false if (options?.security) { if (Object.keys(options.security).length === 0) { throw new Error("HttpApiMiddleware.Tag: security object must not be empty") } TagClass_[SecurityTypeId] = SecurityTypeId TagClass_.security = options.security } return TagClass as any }