# `Trogon.ObjectId`
[🔗](https://github.com/straw-hat-team/beam-monorepo/blob/trogon_object_id@v0.1.1/apps/trogon_object_id/lib/trogon/object_id.ex#L1)

Macro for defining type-safe, domain-specific object IDs.

ObjectIds are type-safe identifiers that combine a human-readable prefix with a value,
stored as `{prefix}{separator}{id}` (e.g., `"user_abc-123"`).

## Usage

    defmodule MyApp.UserId do
      use Trogon.ObjectId,
        object_type: "user"
    end

    # Create
    user_id = MyApp.UserId.new("abc-123")
    #=> %MyApp.UserId{id: "abc-123"}

    # Convert to string
    to_string(user_id)
    #=> "user_abc-123"

    # Parse
    MyApp.UserId.parse("user_abc-123")
    #=> {:ok, %MyApp.UserId{id: "abc-123"}}

## Type Safety

Each ObjectId type is a separate struct, providing compile-time and runtime type safety:

    def process_user(%MyApp.UserId{} = id), do: ...
    def process_order(%MyApp.OrderId{} = id), do: ...

    process_user(MyApp.OrderId.new("123"))  #=> FunctionClauseError!

## Proto-driven ObjectId

When using `trogon_proto` with `trogon/object_id/v1alpha1/options.proto`, you can
derive `object_type` and `separator` from proto enum value extensions:

    defmodule MyApp.TicketId do
      use Trogon.ObjectId,
        proto: {Acme.Type.V1.ObjectType, :OBJECT_TYPE_TICKET},
        storage_format: :drop_prefix,
        validate: :uuid
    end

This reads `object_type` and `separator` from the proto annotation and forwards
them along with any additional options you provide.

## Ecto Integration

ObjectIds implement `Ecto.Type`, so you can use them directly in schemas:

    schema "users" do
      field :id, MyApp.UserId
    end

# `__using__`
*macro* 

Defines a type-safe ObjectId module.

## Options

* `:object_type` (`t:String.t/0`) - Required. The object type (e.g., `"user"`, `"order"`).

* `:separator` (`t:String.t/0`) - Separator between prefix and id. The default value is `"_"`.

* `:storage_format` - Database storage format.
  - `:full` - Store complete string (e.g., `"user_abc-123"`)
  - `:drop_prefix` - Store only the id (e.g., `"abc-123"`) The default value is `:full`.

* `:json_format` - JSON encoding format.
  - `:full` - Encode complete string (e.g., `"user_abc-123"`)
  - `:drop_prefix` - Encode only the id (e.g., `"abc-123"`) The default value is `:full`.

* `:validate` - Validation for the raw id value (without prefix).
  - `nil` - No validation (default)
  - `:uuid` - Validates that the id is a valid UUID
  - `:integer` - Validates that the id is a valid integer string
  - `{Module, :function}` - Custom validator (compile-time optimized direct call).
    The function receives the raw id value and returns `:ok` or `{:error, reason}`. The default value is `nil`.

## Examples

    defmodule MyApp.UserId do
      use Trogon.ObjectId, object_type: "user"
    end

    defmodule MyApp.OrderId do
      use Trogon.ObjectId, object_type: "order", separator: "#"
    end

    defmodule MyApp.AccountId do
      use Trogon.ObjectId, object_type: "acct", storage_format: :drop_prefix
    end

    # With UUID validation
    defmodule MyApp.ProductId do
      use Trogon.ObjectId, object_type: "product", validate: :uuid
    end

    # With integer validation
    defmodule MyApp.SequenceId do
      use Trogon.ObjectId, object_type: "seq", validate: :integer
    end

    # With custom validator (compile-time optimized)
    defmodule MyApp.CustomId do
      use Trogon.ObjectId,
        object_type: "custom",
        validate: {MyValidator, :check}
    end

# `is_object_id`
*macro* 

Returns true if `term` is an ObjectId struct; otherwise returns false.

Allowed in guard tests.

## Examples

    iex> is_object_id(%MyApp.UserId{id: "abc-123"})
    true

    iex> is_object_id(%{id: "abc-123"})
    false

---

*Consult [api-reference.md](api-reference.md) for complete listing*
