/**
 * Middleware services for the unstable RPC runtime.
 *
 * A middleware service wraps server handler execution and can also install a
 * client-side wrapper for generated clients. Its metadata records the services
 * provided to downstream handlers, the services required by the middleware
 * implementation, the schema for server-visible failures, the client-only error
 * type, and whether generated clients must require the matching client layer.
 *
 * **Mental model**
 *
 * A server {@link RpcMiddleware} receives the target RPC, decoded payload,
 * request headers, request id, and `Rpc.ServerClient`, then wraps the handler
 * effect. `provides` removes services from the downstream handler requirement,
 * while `requires` adds the services needed by the middleware. A client
 * {@link RpcMiddlewareClient} is installed with {@link layerClient}; it can
 * inspect, rewrite, retry, or short-circuit outgoing requests before calling
 * `next`.
 *
 * **Common tasks**
 *
 * Use {@link Service} to define authentication, authorization, logging,
 * tracing, metrics, rate limiting, header propagation, or request-scoped
 * service injection. Attach the service to individual RPCs or whole groups,
 * then provide the server implementation like any other `Context.Service`.
 * Provide a client implementation with {@link layerClient} when outgoing
 * requests need matching behavior.
 *
 * **Gotchas**
 *
 * Middleware failures that cross the RPC boundary must be declared with a
 * `Schema`, and any encoding or decoding services required by that schema stay
 * in the generated RPC environments. `clientError` contributes only to the
 * client-side call error channel, while the middleware `error` schema is shared
 * with server failures. Set `requiredForClient` only when typed clients must
 * reject calls unless the matching client middleware layer is installed.
 *
 * @since 4.0.0
 */
import * as Context from "../../Context.js";
import * as Effect from "../../Effect.js";
import * as Layer from "../../Layer.js";
import * as Schema from "../../Schema.js";
import { Scope } from "../../Scope.js";
/**
 * The runtime type id used to attach and inspect RPC middleware metadata.
 *
 * @category type IDs
 * @since 4.0.0
 */
export const TypeId = "~effect/rpc/RpcMiddleware";
/**
 * Creates a typed RPC middleware service class, with optional service
 * requirements, provided services, error schema, and client-side requirement
 * metadata.
 *
 * @category constructors
 * @since 4.0.0
 */
export const Service = () => (id, options) => {
  const Err = globalThis.Error;
  const limit = Err.stackTraceLimit;
  Err.stackTraceLimit = 2;
  const creationError = new Err();
  Err.stackTraceLimit = limit;
  function ServiceClass() {}
  const ServiceClass_ = ServiceClass;
  Object.setPrototypeOf(ServiceClass, Object.getPrototypeOf(Context.Service(id)));
  ServiceClass.key = id;
  Object.defineProperty(ServiceClass, "stack", {
    get() {
      return creationError.stack;
    }
  });
  ServiceClass_[TypeId] = TypeId;
  ServiceClass_.error = options?.error ?? Schema.Never;
  ServiceClass_.requiredForClient = options?.requiredForClient ?? false;
  return ServiceClass;
};
/**
 * Provides the client-side implementation for an RPC middleware service,
 * capturing the layer's environment and merging it into each middleware
 * invocation.
 *
 * @category client
 * @since 4.0.0
 */
export const layerClient = (tag, service) => Layer.effectContext(Effect.gen(function* () {
  const services = (yield* Effect.context()).pipe(Context.omit(Scope));
  const middleware = Effect.isEffect(service) ? yield* service : service;
  return Context.makeUnsafe(new Map([[`${tag.key}/Client`, options => Effect.updateContext(middleware(options), requestContext => Context.merge(services, requestContext))]]));
}));
//# sourceMappingURL=RpcMiddleware.js.map