// @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off import type { FileSystem, Path } from 'effect'; import * as Context from 'effect/Context'; import type { Etag, HttpPlatform, HttpRouter } from 'effect/http'; import type { HttpApi, HttpApiClient, HttpApiGroup } from 'effect/http-api'; import type * as Layer from 'effect/Layer'; import type { Rpc, RpcGroup } from 'effect/rpc'; import type { createHttpApiHandler } from './http'; import type { createRpcApiHandler } from './rpc'; export type EffectRuntimeRequirements = | Etag.Generator | FileSystem.FileSystem | HttpPlatform.HttpPlatform | HttpRouter.HttpRouter | HttpRouter.Request<'Error', unknown> | HttpRouter.Request<'GlobalError', unknown> | HttpRouter.Request<'GlobalRequires', unknown> | HttpRouter.Request<'Requires', unknown> | Path.Path; export type EffectRuntimeLayer = Layer.Layer< never, never, EffectRuntimeRequirements >; const emptyEffectServiceContext = Context.empty() as Context.Context; const isEffectServiceContext = ( context: unknown, ): context is Context.Context => typeof context === 'object' && context !== null && 'mapUnsafe' in context; export const toEffectServiceContext = (context: unknown) => isEffectServiceContext(context) ? context : emptyEffectServiceContext; export type EffectRpcSerialization = | 'json' | 'ndjson' | 'jsonRpc' | 'ndJsonRpc'; export type EffectRpcRuntimeLayer = Layer.Layer< Rpc.ToHandler | Rpc.Middleware | Rpc.ServicesServer, unknown, never >; export type EffectRpcBffDefinition< TRpcs extends Rpc.Any = Rpc.Any, TRpcLayer extends EffectRpcRuntimeLayer = EffectRpcRuntimeLayer, > = { group: RpcGroup.RpcGroup; layer: TRpcLayer; path?: `/${string}`; serialization?: EffectRpcSerialization; disableTracing?: boolean; spanPrefix?: string; spanAttributes?: Record; disableFatalDefects?: boolean; }; export type EffectRpcBffHandlerOptions = Pick< EffectRpcBffDefinition, | 'path' | 'serialization' | 'disableTracing' | 'spanPrefix' | 'spanAttributes' | 'disableFatalDefects' >; export type EffectApiClientFromApi< TApi extends HttpApi.Constraint = HttpApi.Top, > = TApi extends HttpApi.HttpApi ? HttpApiClient.Client< Extract, never, never > : never; export type EffectBffDefinition< TApi extends HttpApi.Constraint = HttpApi.Top, TLayer extends EffectRuntimeLayer = EffectRuntimeLayer, TRpcs extends Rpc.Any = Rpc.Any, > = { api: TApi; layer: TLayer; rpc?: EffectRpcBffDefinition; dataPlatform?: EffectDataPlatformValidationOptions; interceptRequest?: EffectRequestInterceptor; }; export type EffectDataPlatformSelectionValidationOptions = { maxDepth?: number; maxFields?: number; allowedLeafPaths?: string[]; }; export type EffectDataPlatformBatchOptions = { /** * Enable network batching endpoint for Effect HttpApi requests. * Defaults to `true`. */ enabled?: boolean; /** * Batch endpoint path mounted under BFF prefix. * Defaults to `/_data/batch`. */ endpoint?: `/${string}`; /** * Maximum request items accepted per batch call. * Defaults to `16`. */ maxBatchSize?: number; /** * Maximum serialized request payload size in bytes. * Defaults to `65536` (64KiB). */ maxBatchBytes?: number; /** * Maximum per-batch internal request concurrency. * Defaults to `4`. */ maxConcurrency?: number; /** * Optional timeout per internal request in milliseconds. * Defaults to `10000`. */ requestTimeoutMs?: number; /** * Allowed HTTP methods for internal batched dispatch. * Defaults to `['GET']`. */ allowedMethods?: string[]; }; export type EffectDataPlatformValidationOptions = { /** * Enable envelope validation for HttpApi requests. * Defaults to `true`. */ enabled?: boolean; /** * Require every HttpApi request to include an envelope header. * Defaults to `false`. */ requireEnvelope?: boolean; /** * Header name used by client/server for the serialized request envelope. * Defaults to `x-modernjs-data-envelope`. */ envelopeHeader?: string; /** * Optional namespace assertion for envelope validation. */ expectedNamespace?: string; /** * Validate envelope origin against incoming request origin. * Defaults to `true`. */ validateOrigin?: boolean; /** * Require trace context inside request envelope. * Defaults to `false`. */ requireTraceContext?: boolean; /** * Selection plan guardrails for server-side validation. */ selection?: EffectDataPlatformSelectionValidationOptions; /** * Network batching gateway configuration. */ batch?: EffectDataPlatformBatchOptions; }; /** * Server-seam request validator applied to every HttpApi request — direct, * batched (per item) and rpc. Returning a Response short-circuits the * request; returning `null`/`undefined` lets it through. Used by the effect * adapter to enforce the cross-project policy at one seam so batched items * cannot bypass it. */ export type EffectRequestValidator = ( request: Request, ) => Response | null | undefined; export type EffectRequestInterceptor = (options: { request: Request; next: () => Promise; }) => Response | Promise; export type EffectBffHandlerFactory< _TApi extends HttpApi.Constraint = HttpApi.Top, _TLayer extends EffectRuntimeLayer = EffectRuntimeLayer, > = (options?: { openapi?: EffectBffOpenApiConfig; rpc?: Partial; dataPlatform?: Partial; validateRequest?: EffectRequestValidator; }) => ReturnType; export type EffectBffRuntime< TApi extends HttpApi.Constraint = HttpApi.Top, TLayer extends EffectRuntimeLayer = EffectRuntimeLayer, > = { createHandler: EffectBffHandlerFactory; }; export type EffectBffOpenApiConfig = | boolean | { path?: string; }; export type EffectRpcBffHandlerFactory = ( options?: Partial, ) => ReturnType>;