/**
 * @since 4.0.0
 */
import * as Context from "../../Context.js";
import * as Effect from "../../Effect.js";
import * as Layer from "../../Layer.js";
import { hasProperty } from "../../Predicate.js";
import { Scope } from "../../Scope.js";
import { HttpApiSchemaError } from "./HttpApiError.js";
const TypeId = "~effect/httpapi/HttpApiMiddleware";
const SecurityTypeId = "~effect/httpapi/HttpApiMiddleware/Security";
/**
 * @since 4.0.0
 * @category guards
 */
export const isSecurity = u => hasProperty(u, SecurityTypeId);
/**
 * @since 4.0.0
 * @category Schemas
 */
export const Service = () => (id, options) => {
  const Err = globalThis.Error;
  const limit = Err.stackTraceLimit;
  Err.stackTraceLimit = 2;
  const creationError = new Err();
  Err.stackTraceLimit = limit;
  /** @effect-diagnostics-next-line classSelfMismatch:off */
  class Service extends Context.Service()(id) {}
  const self = Service;
  Object.defineProperty(Service, "stack", {
    get() {
      return creationError.stack;
    }
  });
  self[TypeId] = TypeId;
  self.error = getError(options?.error);
  self.requiredForClient = options?.requiredForClient ?? false;
  if (options?.security !== undefined) {
    if (Object.keys(options.security).length === 0) {
      throw new Error("HttpApiMiddleware.Service: security object must not be empty");
    }
    self[SecurityTypeId] = SecurityTypeId;
    self.security = options.security;
  }
  return self;
};
function getError(error) {
  if (error === undefined) return new Set();
  return new Set(Array.isArray(error) ? error : [error]);
}
/**
 * Implement a middleware Layer that transforms `SchemaError`'s.
 *
 * ```ts
 * import { Effect, Schema } from "effect"
 * import { HttpApiMiddleware } from "effect/unstable/httpapi"
 *
 * export class CustomError extends Schema.TaggedErrorClass<CustomError>()("CustomError", {}) {}
 *
 * export class ErrorHandler extends HttpApiMiddleware.Service<ErrorHandler>()("api/ErrorHandler", {
 *   error: CustomError
 * }) {}
 *
 * export const ErrorHandlerLayer = HttpApiMiddleware.layerSchemaErrorTransform(
 *   ErrorHandler,
 *   (schemaError) =>
 *     Effect.log("Got SchemaError", schemaError).pipe(
 *       Effect.andThen(Effect.fail(new CustomError()))
 *     )
 * )
 * ```
 *
 * @since 4.0.0
 * @category SchemaError transform
 */
export const layerSchemaErrorTransform = (service, transform) => Layer.succeed(service, (httpEffect, options) => Effect.catch(httpEffect, e => HttpApiSchemaError.is(e) ? transform(e, options) : Effect.fail(e)));
/**
 * @since 4.0.0
 * @category client
 */
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=HttpApiMiddleware.js.map