import * as core from "./internal/core.js";
import * as Pipeable from "./Pipeable.js";
import * as Predicate from "./Predicate.js";
/**
 * Base class for immutable data types.
 *
 * Extend `Class` with a type parameter to declare fields. The constructor
 * accepts those fields as a single object argument. When there are no fields
 * the argument is optional.
 *
 * - Use when you need a lightweight immutable value type with `.pipe()` support.
 * - Instances are `Readonly` and `Pipeable`.
 * - If you also need a `_tag` discriminator, use {@link TaggedClass} instead.
 * - If you need a yieldable error, use {@link Error} or {@link TaggedError}.
 *
 * **Example** (defining a value class)
 *
 * ```ts
 * import { Data, Equal } from "effect"
 *
 * class Person extends Data.Class<{ readonly name: string }> {}
 *
 * const mike1 = new Person({ name: "Mike" })
 * const mike2 = new Person({ name: "Mike" })
 *
 * console.log(Equal.equals(mike1, mike2))
 * // true
 * ```
 *
 * @see {@link TaggedClass} — adds a `_tag` field
 * @see {@link Error} — yieldable error variant
 *
 * @category constructors
 * @since 2.0.0
 */
export const Class = class extends Pipeable.Class {
  constructor(props) {
    super();
    if (props) {
      Object.assign(this, props);
    }
  }
};
/**
 * Base class for immutable data types with a `_tag` discriminator.
 *
 * Like {@link Class}, but the resulting instances also carry a
 * `readonly _tag: Tag` property. The `_tag` is excluded from the constructor
 * argument.
 *
 * - Use when you need a single-variant tagged type or an ad-hoc discriminator.
 * - For multi-variant unions, prefer {@link TaggedEnum} + {@link taggedEnum}.
 * - For yieldable errors, use {@link TaggedError}.
 *
 * **Example** (defining a tagged class)
 *
 * ```ts
 * import { Data } from "effect"
 *
 * class Person extends Data.TaggedClass("Person")<{
 *   readonly name: string
 * }> {}
 *
 * const mike = new Person({ name: "Mike" })
 * console.log(mike._tag)
 * // "Person"
 * ```
 *
 * @see {@link Class} — without a `_tag`
 * @see {@link TaggedError} — tagged error variant
 * @see {@link TaggedEnum} — multi-variant unions
 *
 * @category constructors
 * @since 2.0.0
 */
export const TaggedClass = tag => class extends Class {
  _tag = tag;
};
/**
 * Creates runtime constructors, type guards, and pattern matching for a
 * {@link TaggedEnum} type.
 *
 * Returns an object with:
 * - One constructor per variant (keyed by tag name)
 * - `$is(tag)` — returns a type-guard function
 * - `$match` — exhaustive pattern matching (data-first or data-last)
 *
 * - Use when you have a `TaggedEnum` type and need to construct/inspect values.
 * - Constructors produce **plain objects** (not class instances).
 * - For generic enums, pass a {@link TaggedEnum.WithGenerics} interface.
 *
 * **Example** (basic usage)
 *
 * ```ts
 * import { Data } from "effect"
 *
 * type HttpError = Data.TaggedEnum<{
 *   BadRequest: { readonly message: string }
 *   NotFound: { readonly url: string }
 * }>
 *
 * const { BadRequest, NotFound, $is, $match } = Data.taggedEnum<HttpError>()
 *
 * const err = NotFound({ url: "/missing" })
 *
 * // Type guard
 * console.log($is("NotFound")(err)) // true
 *
 * // Pattern matching
 * const msg = $match(err, {
 *   BadRequest: (e) => e.message,
 *   NotFound: (e) => `${e.url} not found`
 * })
 * console.log(msg) // "/missing not found"
 * ```
 *
 * **Example** (generic tagged enum)
 *
 * ```ts
 * import { Data } from "effect"
 *
 * type MyResult<E, A> = Data.TaggedEnum<{
 *   Failure: { readonly error: E }
 *   Success: { readonly value: A }
 * }>
 * interface MyResultDef extends Data.TaggedEnum.WithGenerics<2> {
 *   readonly taggedEnum: MyResult<this["A"], this["B"]>
 * }
 * const { Failure, Success } = Data.taggedEnum<MyResultDef>()
 *
 * const ok = Success({ value: 42 })
 * // ok: { readonly _tag: "Success"; readonly value: number }
 * ```
 *
 * @see {@link TaggedEnum} — the type-level companion
 * @see {@link TaggedEnum.Constructor} — the returned object type
 * @see {@link TaggedEnum.WithGenerics} — generic enum support
 *
 * @category constructors
 * @since 2.0.0
 */
export const taggedEnum = () => new Proxy({}, {
  get(_target, tag, _receiver) {
    if (tag === "$is") {
      return Predicate.isTagged;
    } else if (tag === "$match") {
      return taggedMatch;
    }
    return props => ({
      ...props,
      _tag: tag
    });
  }
});
function taggedMatch() {
  if (arguments.length === 1) {
    const cases = arguments[0];
    return function (value) {
      return cases[value._tag](value);
    };
  }
  const value = arguments[0];
  const cases = arguments[1];
  return cases[value._tag](value);
}
/**
 * Base class for yieldable errors.
 *
 * Extends `Cause.YieldableError`, so instances can be yielded inside
 * `Effect.gen` to fail the enclosing effect. Fields are passed as a single
 * object; when there are no fields the argument is optional.
 *
 * - Use for errors that do **not** need tag-based discrimination.
 * - If you need `Effect.catchTag` support, use {@link TaggedError} instead.
 * - If a `message` field is provided, it becomes the error's `.message`.
 *
 * **Example** (defining a yieldable error)
 *
 * ```ts
 * import { Data, Effect } from "effect"
 *
 * class NetworkError extends Data.Error<{
 *   readonly code: number
 *   readonly message: string
 * }> {}
 *
 * const program = Effect.gen(function*() {
 *   return yield* new NetworkError({ code: 500, message: "timeout" })
 * })
 *
 * // The effect fails with a NetworkError
 * Effect.runSync(Effect.exit(program))
 * ```
 *
 * @see {@link TaggedError} — adds a `_tag` for `Effect.catchTag`
 * @see {@link Class} — non-error data class
 *
 * @category constructors
 * @since 2.0.0
 */
export const Error = core.Error;
/**
 * Creates a tagged error class with a `_tag` discriminator.
 *
 * Like {@link Error}, but instances also carry a `readonly _tag` property,
 * enabling `Effect.catchTag` and `Effect.catchTags` for tag-based recovery.
 * The `_tag` is excluded from the constructor argument.
 *
 * - Use for domain errors in Effect applications where you want
 *   discriminated-union error handling.
 * - Yielding an instance inside `Effect.gen` fails the effect with this error.
 *
 * **Example** (tag-based error recovery)
 *
 * ```ts
 * import { Data, Effect } from "effect"
 *
 * class NotFound extends Data.TaggedError("NotFound")<{
 *   readonly resource: string
 * }> {}
 *
 * class Forbidden extends Data.TaggedError("Forbidden")<{
 *   readonly reason: string
 * }> {}
 *
 * const program = Effect.gen(function*() {
 *   return yield* new NotFound({ resource: "/users/42" })
 * })
 *
 * const recovered = program.pipe(
 *   Effect.catchTag("NotFound", (e) =>
 *     Effect.succeed(`missing: ${e.resource}`))
 * )
 * ```
 *
 * @see {@link Error} — without a `_tag`
 * @see {@link TaggedClass} — tagged class that is not an error
 *
 * @category constructors
 * @since 2.0.0
 */
export const TaggedError = core.TaggedError;
//# sourceMappingURL=Data.js.map