Packages

phoenix_kit

2.41.2
2.64.0 2.63.0 2.62.2 2.62.1 2.62.0 2.61.0 2.60.3 2.60.2 2.60.1 2.60.0 2.59.0 2.58.0 2.57.1 2.57.0 2.56.1 2.56.0 2.55.1 2.55.0 2.54.2 2.54.1 2.54.0 2.53.0 2.52.2 2.52.1 2.52.0 2.51.0 2.50.0 2.49.1 2.49.0 2.48.0 2.47.0 2.46.0 2.45.0 2.44.0 2.43.1 2.43.0 2.42.1 2.42.0 2.41.6 2.41.4 2.41.3 2.41.2 2.41.1 2.41.0 2.40.1 2.40.0 2.39.0 2.38.1 2.38.0 2.37.5 2.37.4 2.37.3 2.37.2 2.37.1 2.37.0 2.36.1 2.36.0 2.35.0 2.34.0 2.33.0 2.32.1 2.32.0 2.31.1 2.31.0 2.30.0 2.29.1 2.29.0 2.28.2 2.28.1 2.28.0 2.27.2 2.27.1 2.27.0 2.26.1 2.26.0 2.25.0 2.24.0 2.23.3 2.23.2 2.23.1 2.23.0 2.22.24 2.22.23 2.22.22 2.22.21 2.22.20 2.22.19 2.22.18 2.22.17 2.22.16 2.22.15 2.22.14 2.22.13 2.22.12 2.22.11 2.22.10 2.22.9 2.22.8 2.22.7 2.22.6 2.22.5 2.22.4 2.22.3 2.22.2 2.22.1 2.22.0 2.21.5 2.21.4 2.21.3 2.21.2 2.21.1 2.21.0 2.20.0 2.19.0 2.18.1 2.18.0 2.17.0 2.16.0 2.15.1 2.15.0 2.14.2 2.14.1 2.14.0 2.13.19 2.13.18 2.13.17 2.13.16 2.13.15 2.13.13 2.13.12 2.13.11 2.13.10 2.13.9 2.13.8 2.13.7 2.13.6 2.13.5 2.13.4 2.13.3 2.13.2 2.13.1 2.13.0 2.12.1 2.12.0 2.11.0 2.10.0 2.9.0 2.8.1 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.0 2.0.1 2.0.0 1.7.236 1.7.235 1.7.234 1.7.233 1.7.232 1.7.231 1.7.230 1.7.229 1.7.228 1.7.227 1.7.226 1.7.225 1.7.224 1.7.223 1.7.222 1.7.221 1.7.220 1.7.219 1.7.218 1.7.217 1.7.216 1.7.215 1.7.214 1.7.213 1.7.212 1.7.211 1.7.210 1.7.209 1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules storage schemas file_instance.ex
Raw

lib/modules/storage/schemas/file_instance.ex

defmodule PhoenixKit.Modules.Storage.FileInstance do
  @moduledoc """
  Schema for file variants (thumbnails, resizes, video qualities).

  Each file can have multiple instances representing different versions:
  - **original** - The unchanged uploaded file
  - **thumbnail** - Small preview (150x150)
  - **small** - Small variant (300x300)
  - **medium** - Medium variant (800x600)
  - **large** - Large variant (1920x1080)
  - **360p** - Video quality variant (640x360)
  - **720p** - Video quality variant (1280x720)
  - **1080p** - Video quality variant (1920x1080)
  - **video_thumbnail** - Thumbnail extracted from video (640x360)

  All instances are stored next to the original file in the same directory.

  ## Processing Status

  - `pending` - Instance not yet processed
  - `processing` - Currently being generated
  - `completed` - Successfully generated
  - `failed` - Generation failed

  ## Fields

  - `variant_name` - Name of the variant (original, thumbnail, medium, etc.)
  - `file_name` - System filename (uuid_v7-variant.ext)
  - `mime_type` - MIME type of this variant
  - `ext` - File extension
  - `checksum` - Hash for integrity verification
  - `size` - Variant file size in bytes
  - `width` - Width in pixels (nullable)
  - `height` - Height in pixels (nullable)
  - `processing_status` - Current processing state
  - `file_uuid` - Parent file reference

  ## Examples

      # Original instance
      %FileInstance{
        variant_name: "original",
        file_name: "018e3c4a-9f6b-7890-original.jpg",
        mime_type: "image/jpeg",
        ext: "jpg",
        checksum: "abc123...",
        size: 524_288,
        width: 2000,
        height: 2000,
        processing_status: "completed",
        file_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890"
      }

      # Thumbnail instance
      %FileInstance{
        variant_name: "thumbnail",
        file_name: "018e3c4a-9f6b-7890-thumbnail.jpg",
        mime_type: "image/jpeg",
        ext: "jpg",
        checksum: "def456...",
        size: 8_192,  # 8 KB
        width: 150,
        height: 150,
        processing_status: "completed",
        file_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890"
      }

      # Video quality variant
      %FileInstance{
        variant_name: "720p",
        file_name: "018e3c4a-9f6b-7890-720p.mp4",
        mime_type: "video/mp4",
        ext: "mp4",
        size: 5_242_880,  # 5 MB
        width: 1280,
        height: 720,
        processing_status: "processing"
      }
  """
  use Ecto.Schema
  use PhoenixKit.SchemaPrefix
  import Ecto.Changeset

  @primary_key {:uuid, UUIDv7, autogenerate: true}
  @foreign_key_type UUIDv7

  @type t :: %__MODULE__{
          uuid: UUIDv7.t() | nil,
          variant_name: String.t(),
          file_name: String.t(),
          mime_type: String.t(),
          ext: String.t(),
          checksum: String.t(),
          size: integer(),
          width: integer() | nil,
          height: integer() | nil,
          processing_status: String.t(),
          spec_hash: String.t() | nil,
          file_uuid: UUIDv7.t() | nil,
          file: PhoenixKit.Modules.Storage.File.t() | Ecto.Association.NotLoaded.t(),
          locations:
            [PhoenixKit.Modules.Storage.FileLocation.t()] | Ecto.Association.NotLoaded.t(),
          inserted_at: DateTime.t() | nil,
          updated_at: DateTime.t() | nil
        }

  schema "phoenix_kit_file_instances" do
    field :variant_name, :string
    field :file_name, :string
    field :mime_type, :string
    field :ext, :string
    field :checksum, :string
    field :size, :integer
    field :width, :integer
    field :height, :integer
    field :processing_status, :string, default: "pending"
    # Which spec of a size made this instance (V205,
    # `Storage.VariantSets.spec_hash/2`); nil for one not made from a size
    # (the original, an annotated thumbnail, a render).
    field :spec_hash, :string

    belongs_to :file, PhoenixKit.Modules.Storage.File, foreign_key: :file_uuid, references: :uuid
    has_many :locations, PhoenixKit.Modules.Storage.FileLocation, foreign_key: :file_instance_uuid

    timestamps(type: :utc_datetime)
  end

  @doc """
  Changeset for creating or updating a file instance.

  ## Required Fields

  - `variant_name`
  - `file_name`
  - `mime_type`
  - `ext`
  - `checksum`
  - `size`
  - `file_uuid`

  ## Validation Rules

  - Processing status must be valid (pending, processing, completed, failed)
  - Size must be positive
  - Width/height must be positive (if provided)
  - Unique variant_name per file
  """
  def changeset(instance, attrs) do
    instance
    |> cast(attrs, [
      :variant_name,
      :file_name,
      :mime_type,
      :ext,
      :checksum,
      :size,
      :width,
      :height,
      :processing_status,
      :file_uuid,
      :spec_hash
    ])
    |> validate_required([
      :variant_name,
      :file_name,
      :mime_type,
      :ext,
      :checksum,
      :size,
      :file_uuid
    ])
    |> validate_inclusion(:processing_status, ["pending", "processing", "completed", "failed"])
    |> validate_number(:size, greater_than: 0)
    |> validate_number(:width, greater_than: 0)
    |> validate_number(:height, greater_than: 0)
    |> unique_constraint([:file_uuid, :variant_name],
      name: :phoenix_kit_file_instances_file_uuid_variant_name_index
    )
    |> foreign_key_constraint(:file_uuid, name: :phoenix_kit_file_instances_file_id_fkey)
  end

  @doc """
  Returns whether this is the original file instance.
  """
  def original?(%__MODULE__{variant_name: "original"}), do: true
  def original?(_), do: false

  @doc """
  Returns whether this instance has been successfully processed.
  """
  def completed?(%__MODULE__{processing_status: "completed"}), do: true
  def completed?(_), do: false

  @doc """
  Returns whether this instance failed processing.
  """
  def failed?(%__MODULE__{processing_status: "failed"}), do: true
  def failed?(_), do: false

  @doc """
  Returns whether this instance is currently being processed.
  """
  def processing?(%__MODULE__{processing_status: "processing"}), do: true
  def processing?(_), do: false

  @doc """
  Returns whether this instance is pending processing.
  """
  def pending?(%__MODULE__{processing_status: "pending"}), do: true
  def pending?(_), do: false
end