Packages

Under heavy development: not for production use before 1.0.0. DXN (Data eXchange Notation) for Elixir -- .dxn text, .dxnb binary, and .dxns schema documents, built on the Ichor grammar compiler.

Current section

Files

Jump to
dextrin mix.exs
Raw

mix.exs

defmodule Dextrin.MixProject do
  use Mix.Project

  @version "0.3.3"

  def project do
    [
      app: :dextrin,
      version: @version,
      elixir: "~> 1.19",
      start_permanent: Mix.env() == :prod,
      elixirc_paths: elixirc_paths(Mix.env()),
      # test/fixtures/ holds data and the scripts that wrote it, which are
      # run against an old release by hand, never as tests.
      test_ignore_filters: [&String.starts_with?(&1, "test/fixtures/")],
      deps: deps(),
      description: description(),
      package: package(),
      name: "Dextrin",
      docs: docs(),
      aliases: aliases(),
      test_coverage: [tool: ExCoveralls],
      dialyzer: [plt_add_apps: [:mix]]
    ]
  end

  def cli do
    [preferred_envs: [precommit: :test]]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      # :inets/:ssl (pulling in :public_key/:crypto transitively) are
      # needed by Mix.Tasks.Dextrin.Gen.Unicode to fetch UCD data over
      # HTTPS.
      extra_applications: [:logger, :inets, :ssl]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # === CODE QUALITY & STATIC ANALYSIS ===
      {:credo, "~> 1.7", only: [:dev, :test], runtime: false},
      {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
      {:sobelow, "~> 0.14", only: [:dev, :test], runtime: false},
      {:excoveralls, "~> 0.18", only: [:dev, :test], runtime: false},
      # Credo is invoked via `MIX_ENV=test mix credo`
      # Dialyzer is invoked via `MIX_ENV=test mix dialyzer`
      # Sobelow is invoked via `MIX_ENV=test mix sobelow`
      # Coveralls is invoked via `MIX_ENV=test mix coveralls

      # === TESTING ===
      {:mox, "~> 1.2", only: [:dev, :test]},
      {:faker, "~> 0.19", only: [:test]},
      {:stream_data, "~> 1.4", only: [:test]},

      # === DEVELOPMENT TOOLING ===
      # Mix, and Hex are built-in (no deps needed)
      {:ex_doc, "~> 0.40", only: [:dev], runtime: false},
      # ExDoc is invoked via `MIX_ENV=dev mix docs`

      # === RUNTIME ===
      # ichor_runtime is the only actual runtime dependency -- the ~18
      # modules a generated parser (from `mix ichor.gen`) calls at
      # runtime (Ichor.Actions, Ichor.Error, the compiled Tokenizer/
      # Parser combinators, the LR/GLR runtime). ichor proper (the
      # Aether front-end, format importers, Grammar.Analysis, both
      # codegen backends) is only ever needed by `mix ichor.gen`, which
      # generates lib/dextrin/text/grammar/native.ex ahead of time --
      # it's never referenced by any code that ships, hence `only:
      # :dev, runtime: false`.
      {:ichor_runtime, "~> 0.6.3"},
      {:ichor, "~> 0.7.3", only: :dev, runtime: false},

      # `~> 3.0`, not `~> 2.1` -- 2.4.1 (the version that constraint
      # resolved to) carries a real, published MEDIUM-severity DoS
      # advisory (EEF-CVE-2026-32686, "unbounded exponent in decimal
      # enables unauthenticated DoS"), confirmed via `mix hex.audit`
      # while adding a downstream consumer. This library parses
      # untrusted `.dxn`/`.dxnb` input directly into `Decimal.new/1,3`
      # (`lib/dextrin/text/actions.ex`, `lib/dextrin/binary/decoder.ex`)
      # -- exactly the attack surface the advisory describes, not an
      # incidental transitive path. Every `Decimal.*` call this package
      # makes (`new/1`, `new/3`, `to_float/1`, `to_string/2`) is
      # unchanged, stable core API across 2.x and 3.x -- confirmed by
      # this package's own test suite passing unmodified against 3.1.1.
      {:decimal, "~> 3.0"}
    ]
  end

  # Fast/cheap checks first so a broken commit fails quickly; dialyzer
  # (slowest, especially its first PLT build) runs last.
  defp aliases do
    [
      # HexDocs gets the README through `doc_src/` (see `readme_for_docs/1`);
      # `mix hex.publish` builds the docs through this alias too.
      docs: [&readme_for_docs/1, "docs"],
      precommit: [
        "format",
        "compile --warnings-as-errors",
        "credo --strict",
        "sobelow",
        "test",
        "dialyzer"
      ]
    ]
  end

  defp description do
    "Under heavy development: not for production use before 1.0.0. " <>
      "DXN (Data eXchange Notation) for Elixir -- .dxn text, .dxnb binary, " <>
      "and .dxns schema documents, built on the Ichor grammar compiler."
  end

  defp package do
    [
      licenses: ["Apache-2.0"],
      links: %{
        "GitHub" => "https://github.com/joetjen/dextrin",
        "Docs (main)" => "https://joetjen.github.io/dextrin",
        "node-dextrin (npm)" => "https://www.npmjs.com/package/@joetjen/dextrin",
        "php-dextrin (Packagist)" => "https://packagist.org/packages/joetjen/dextrin"
      },
      files:
        ~w(lib priv/grammar priv/unicode priv/schema .formatter.exs mix.exs README.md CHANGELOG.md LICENSE)
    ]
  end

  defp docs do
    [
      main: "readme",
      source_url: "https://github.com/joetjen/dextrin",
      source_ref: "v#{@version}",
      extras: extras(),
      groups_for_extras: groups_for_extras(),
      groups_for_modules: groups_for_modules()
    ]
  end

  defp extras do
    [
      {"doc_src/README.md", filename: "readme", source: "README.md"},
      "guides/TUTORIAL.md",
      "guides/EXAMPLES.md",
      "guides/CHEATSHEET.md",
      "guides/dxn/TUTORIAL.md",
      "guides/dxn/DXN.md",
      "guides/dxn/DXN_EXAMPLES.md",
      "guides/dxn/DXN_CHEATSHEET.md",
      {"guides/dxns/TUTORIAL.md", filename: "dxns-tutorial", title: "DXNS Tutorial"},
      "guides/dxns/DXNS.md",
      "guides/dxns/DXNS_EXAMPLES.md",
      "guides/dxns/DXNS_CHEATSHEET.md",
      "CHANGELOG.md",
      "CONTRIBUTING.md",
      "LICENSE"
    ]
  end

  # The README as HexDocs is given it (Jan, 2026-10-20): ExDoc renders
  # no GitHub alert, so each `> [!WARNING]` becomes ExDoc's own warning
  # admonition, and the README itself stays as GitHub shows it. Agreed
  # with Ichor and Cooper, which do the same.
  defp readme_for_docs(_args) do
    File.mkdir_p!("doc_src")

    readme =
      "README.md"
      |> File.read!()
      |> String.replace(~r/^> \[!WARNING\]$/m, "> #### Warning {: .warning}")

    File.write!("doc_src/README.md", readme)
  end

  defp groups_for_extras do
    [
      Guides: ["guides/TUTORIAL.md", "guides/EXAMPLES.md", "guides/CHEATSHEET.md"],
      "DXN Format": Path.wildcard("guides/dxn/*.md"),
      "DXNS Schemas": Path.wildcard("guides/dxns/*.md"),
      Project: ["CHANGELOG.md", "CONTRIBUTING.md", "LICENSE"]
    ]
  end

  defp groups_for_modules do
    [
      Core: [
        Dextrin,
        Dextrin.Value,
        Dextrin.Registry,
        Dextrin.Error
      ],
      "Value types": [
        Dextrin.Array,
        Dextrin.Bytes,
        Dextrin.Char,
        Dextrin.CustomTag,
        Dextrin.Duration,
        Dextrin.Keyword,
        Dextrin.OrderedMap,
        Dextrin.Rational,
        Dextrin.SortedSet,
        Dextrin.Struct,
        Dextrin.Symbol,
        Dextrin.Tuple,
        Dextrin.Uri,
        Dextrin.Uuid
      ],
      "Text pipeline (.dxn)": [
        Dextrin.Text.Grammar,
        Dextrin.Text.Actions,
        Dextrin.Text.Printer,
        Dextrin.Text.Formatter,
        Dextrin.Text.Escapes
      ],
      "Binary pipeline (.dxnb)": [
        Dextrin.Binary.Encoder,
        Dextrin.Binary.Decoder,
        Dextrin.Binary.Tags
      ],
      "Schema (.dxns)": [
        Dextrin.Schema,
        Dextrin.Schema.Compiler,
        Dextrin.Schema.Compiled,
        Dextrin.Schema.Field,
        Dextrin.Schema.TypeExpr,
        Dextrin.Schema.Validator,
        Dextrin.Schema.Validated,
        Dextrin.Schema.Std,
        Dextrin.Schema.FileResolver,
        Dextrin.Schema.Provider
      ],
      Unicode: [
        Dextrin.Unicode.RangeGenerator
      ],
      "Mix tasks": [
        Mix.Tasks.Dextrin.Validate,
        Mix.Tasks.Dextrin.Encode,
        Mix.Tasks.Dextrin.Decode,
        Mix.Tasks.Dextrin.Format,
        Mix.Tasks.Dextrin.Gen.Schema,
        Mix.Tasks.Dextrin.Gen.Unicode
      ]
    ]
  end
end