Trying Spark for the first time and DSL doesnt seem to be recognized

Hello Ash friends,

I’m working on implementing a relatively simple DSL. Mostly just a fancy formatting for data, since I know the Spark DSL renders out to plain Elixir maps/structs etc.

I’m working on following the Getting Started guide here: Spark — spark v2.4.1

and I’ve worked through the example to the point that I think it makes sense but I’m getting some compiler errors.

First: the code I’m working with – code snippets here should give you an idea of what I’m building.

# lib/legacy_dsl/application/dsl.ex
defmodule LegacyDSL.Application.Dsl do
  use Spark.Dsl,
    default_extensions: [
      extensions: [LegacyDSL.Application.ApplicationExtension]
    ]
end

#lib/legacy_dsl/application/application_extension.ex
defmodule LegacyDSL.Application.ApplicationExtension do
  defmodule Component do
    # The __spark_metadata__ field is required for Spark entities
    # It stores source location information for better error messages and tooling
    defstruct [:name, :description, :__spark_metadata__]
  end

  @component %Spark.Dsl.Entity{
    name: :component,
    args: [:name, :description],
    target: Component,
    describe: "A component that is either reusable or swappable, the user has some intuition around working with it",
    schema: [
      name: [
        type: :atom,
        required: true,
        doc: "The name of the field"
      ],
      type: [
        type: :string,
        required: false,
        doc: "The type of the field"
      ],
    ]
  }

  @overview %Spark.Dsl.Section{
    name: :overview,
    schema: [
      name: [
        type: :string,
        doc: "Name of the software system"
      ],
      system_maintainer: [
        type: {:list, :atom},
        doc: "Name of responsible system owners"
      ],
      prior_system_maintainer: [
        type: {:list, :atom},
        doc: "Name of prior system owners"
      ],
    ],
    entities: [
      @component,
        #--> @negativeBranch,
      #   @stateLocation
      #   @polymorphism / combinatorics of configurations
    ],
    describe: """
    Global System description for the software
    """
  }

  use Spark.Dsl.Extension, sections: [@overview]

  # def dsl_patches do
  #   :ok
  # end
end

#lib/legacy_dsl/application.ex
defmodule LegacyDSL.Application do

  @overview %Spark.Dsl.Section{
    name: :overview,
    describe: """
    Global System description for the software
    """,
    schema: [
      system_maintainer: [
        type: {:list, :atom},
        doc:
          "Name of responsible system owners"
      ],
      prior_system_maintainer: [
        type: {:list, :atom},
        doc:
          "Name of prior system owners"
      ],
    ],
    # entities: [
    #   @negativeBranch,
    #   @component,
    #   @stateLocation
    # ]
  }

  @sections [@overview]
  # TODO userset


  use Spark.Dsl.Extension,
      sections: @sections
      # transformers: [
      # ],
      # verifiers: [
      # ]

end

And… here’s me trying to use the newly created DSL and … getting my errors

defmodule LegacyDSL.ExampleUsage do
  use LegacyDSL.Application.Dsl

  application do
    overview do
      system_maintainer [:me]
      prior_system_maintainer [:jp]

      components do

      end
    end
  end


end

Errors while trying to run with iex -S mix :

== Compilation error in file lib/legacy_dsl/example_usage.ex ==
** (CompileError) lib/legacy_dsl/example_usage.ex: cannot compile module LegacyDSL.ExampleUsage (errors have been logged)

:error
iex(6)> recompile()
Compiling 4 files (.ex)
    error: undefined function application/1 (there is no such import)
    │
  4 │   application do
    │   ^
    │
    └─ lib/legacy_dsl/example_usage.ex:4:3: LegacyDSL.ExampleUsage (module)

I’m sure there could be some user error, especially as the DSL expands, etc. I’m not really sure what to put under components .. but more especially I’m focused on the error which says that application is not recognized.
I’m trying to use it in the same way I’ve defined Ash resources. I’m also trying to reference the DSL extension stuff in the ash_graphql hex pkg.
I also tried doing a overview block instead of the application block and I get basically the same error:

% iex -S mix 
Erlang/OTP 28 [erts-16.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Compiling 4 files (.ex)
    error: undefined function components/1 (there is no such import)
    │
 21 │     components do
    │     ^
    │
    └─ lib/legacy_dsl/example_usage.ex:21:5: LegacyDSL.ExampleUsage (module)


== Compilation error in file lib/legacy_dsl/example_usage.ex ==
** (CompileError) lib/legacy_dsl/example_usage.ex: cannot compile module LegacyDSL.ExampleUsage (errors have been logged)
    expanding macro: LegacyDSL.Application.ApplicationExtension.overview/1

Anyway. I feel like I’ve done some pretty good due diligence in trying to get this to work. Any help from the community is very much appreciated. Thank you in advance!

Your top is called overview. If you want to use

application do

end

then you’d need to have a section called :application, with a section called :overview inside of it.

Ah. That does help orient me to look in the right place.

I ended up finding an error in my entities definition. Also cloning down ash_graphql to take a closer look at that DSL extension and also the Ash DSL (seeing a working example) helped.

So.. yup I got it working in the end :tada: When I get some time, I’ll try and post the working minimal version.