To create a custom Domain Specific Language (DSL), you define a Spark.Dsl.Extension. This involves using the builder API (Spark.Builder.Section, Spark.Builder.Entity, and Spark.Builder.Field) to construct the schema of your DSL.
Key Requirements:
- Every entity struct must include a
__spark_metadata__ field. This field is used by Spark to store source location information, which enables better error messages and tooling. - Use
Entity.new/3 to define entities (like a field). - Use
Section.new/3 to define sections (like fields) that contain entities. - Use
Spark.Dsl.Extension.use to register your sections.
defmodule MyLibrary.Validator.Dsl do
alias Spark.Builder.{Entity, Field, Section}
defmodule Field do
# The __spark_metadata__ field is required for Spark entities
defstruct [:name, :type, :transform, :check, :__spark_metadata__]
end
@field Entity.new(:field, Field,
describe: "A field that is accepted by the validator",
args: [:name, :type],
schema: [
Field.new(:name, :atom, required: true, doc: "The name of the field"),
Field.new(:type, {:one_of, [:integer, :string]}, required: true, doc: "The type of the field"),
Field.new(:check, {:fun, 1}, doc: "A function to check validity"),
Field.new(:transform, {:fun, 1}, doc: "A function to transform the value")
]
) |> Entity.build!()
@fields Section.new(:fields,
describe: "Configure the fields",
schema: [
Field.new(:required, {:list, :atom}, doc: "Required fields")
],
entities: [@field]
) |> Section.build!()
use Spark.Dsl.Extension, sections: [@fields]
end