Skip to content

Expand Lua DSL#1

Merged
zachdaniel merged 5 commits into
ash-project:mainfrom
olivermt:dsl-expansion
Jun 3, 2026
Merged

Expand Lua DSL#1
zachdaniel merged 5 commits into
ash-project:mainfrom
olivermt:dsl-expansion

Conversation

@olivermt

@olivermt olivermt commented May 30, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds explicit Lua surface DSL for AshLua, plus Lua-facing field and argument aliases.
The PR is split into three reviewable commits, each green on its own.

Commit 1: Add domain-owned Lua surface DSL

This commit introduces domain-owned Lua namespaces and public action aliases.

Example:

lua do
  namespace "surface" do
    action :page_list, MyApp.Page, :list_for_storefront
  end
end

This exposes:

surface.page_list(...)

while dispatch still calls the internal Ash action:

MyApp.Page.list_for_storefront

Main Ideas

Domains own the public Lua namespace.

Resources still own the Ash implementation.

The Manifest remains the source of truth. AshLua.Surface now generates/annotates %Ash.Info.Manifest{} entrypoints with:

entrypoint.config[:ash_lua]

containing public path metadata such as:

%{
  path: ["surface", "page_list"],
  path_string: "surface.page_list",
  path_source: :explicit,
  lua_action: "page_list",
  domain: MyApp.Surface
}

Runtime and docs no longer independently reconstruct callable paths. They read the public path from the annotated manifest entrypoint.

Backwards Compatibility

This is opt-in per domain.

Domains without explicit lua namespace ... action ... config keep the old inferred callable shape:

<domain>.<resource>.<ash_action>

So existing calls like this continue to work:

posts.post.read(...)

Once a domain declares explicit namespaces, that domain exposes only the configured public actions. This avoids accidentally creating two public APIs for the same domain.

Other domains in the same OTP app remain on the legacy inferred shape until they opt in.

Commit 2: Add Lua field and argument aliases

This commit adds Lua-facing names for resource fields and action arguments.

Example:

lua do
  field_names title: "headline", featured?: "featured"
  argument_names summarize: [title_text: "headlineText"]
end

This lets Lua use:

surface.page_list({
  fields = { "headline", "featured" },
  filter = { headline = "Home", featured = true },
  sort = "headline"
})

while Ash still receives internal names:

:title
:featured?
:title_text

Main Ideas

AshLua.FieldNames owns exact name mapping at the Lua boundary.

Aliases are applied in both directions:

Lua -> Ash:

  • action input maps
  • fields
  • filter
  • sort
  • operation

Ash -> Lua:

  • encoded output records
  • docs tables
  • filterable/sortable field docs
  • Ash error fields

I have not attempted to solve a general manifest-level “filter object schema/traversal” system, that is something you intend to solve in Manifest itself it seems?

Commit 3: Add surface fixture coverage

This commit adds a focused fixture domain/resource and tests that exercise the whole surface.

The fixture exposes:

lua do
  namespace "surface" do
    action :page_create, AshLua.Test.Surface.Page, :create
    action :page_list, AshLua.Test.Surface.Page, :list_for_storefront
    action :page_rename, AshLua.Test.Surface.Page, :rename
    action :page_summarize, AshLua.Test.Surface.Page, :summarize
  end
end

The returned record type remains documented as:

surface.page

So docs now show a coherent shape like:

surface.page
surface.page_create
surface.page_list
surface.page_rename
surface.page_summarize

Comment thread lib/ash_lua/surface.ex Outdated
olivermt added 3 commits June 1, 2026 11:15
Resolve public callable paths through Manifest entrypoint metadata, with explicit domain namespaces and eval/docs/runtime consuming the annotated manifest.
Map configured field_names and argument_names across inputs, fields, filters, sorts, operations, outputs, docs, and Ash error fields.
Cover explicit public paths, Manifest entrypoint metadata, eval/docs scoping, aliases, and verifier failures with focused fixtures.
@olivermt olivermt marked this pull request as ready for review June 1, 2026 09:17

alias Spark.Dsl.Verifier

@reserved_input_keys ~w(fields filter sort limit offset page operation)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@olivermt this points out an issue: we should put all the input arguments into an input named argument, not combine them all up at the top 😓

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that means breaking backwards compability on whats already there does it not? Maybe thats fine on a 0.2.x ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have found a possible path forward:

  • namespaces nest under input
  • old auto-derived stuff stays as-is

Means we need two parse paths, but it means we can mark it deprecated, although how that will work when exposing an integrated runtime internally I don't know. I guess it mostly applies to people exposing user codable sandboxes and stuff (which I do, but no customers is using it yet, so I don't care).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this maybe? olivermt@b0f4a10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to maintain backwards compatibility. This package came out like 2 weeks ago and is pre 1.0

@zachdaniel

Copy link
Copy Markdown
Contributor

@olivermt mind checking the failing checks?

@olivermt

olivermt commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Checks are fixed

@zachdaniel zachdaniel merged commit d36aa69 into ash-project:main Jun 3, 2026
@zachdaniel

Copy link
Copy Markdown
Contributor

🚀 Thank you for your contribution! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants