DalaNew.ProjectGenerator (dala_new v0.0.3)

Copy Markdown View Source

Generates a new Dala project from EEx templates in priv/templates/dala.new/.

## Naming conventions

Given app_name = "my_cool_app" and the default bundle prefix:

Naming conventions

Given app_name = "my_cool_app" and the default bundle prefix:

  • module_name"MyCoolApp"
  • display_name"MyCoolApp"
  • bundle_id"com.example.my_cool_app"
  • java_package"com.example.my_cool_app"
  • lib_name"mycoolapp" (no underscores, for System.loadLibrary)
  • java_path"com/example/my_cool_app" (for directory structure)

Bundle prefix

The reverse-DNS prefix for the bundle ID defaults to com.example, the universal "must change before shipping" placeholder. Override at generation time with the DALA_BUNDLE_PREFIX env var:

DALA_BUNDLE_PREFIX=net.acme mix dala.new my_cool_app
# → bundle_id = "net.acme.my_cool_app"

We deliberately do not use com.dala — that's our reverse-DNS namespace, and Apple/Google enforce ownership at submission time, so a project that ships with com.dala.* would have to be renamed before reaching either store.

Summary

Functions

Returns the EEx template assigns map for app_name.

Generates a new project at dest_dir/<app_name> from the bundled templates.

Generates a LiveView-wrapped Dala project at dest_dir/<app_name>.

When generating a LiveView project, mix phx.new already produced its own mix.exs, config/, lib/<app>/, lib/<app>_web/, .gitignore, and assets/ — and those are the correct versions for a Phoenix app (with gettext, telemetry_metrics, etc.). The native template's same-named files are written for the bare-Dala path and would clobber Phoenix's, leaving the project unable to compile.

Functions

assigns(app_name, opts \\ [])

@spec assigns(
  String.t(),
  keyword()
) :: map()

Returns the EEx template assigns map for app_name.

Options:

  • :local — when true, generates path: deps pointing to local dala/dala_dev repos instead of hex version constraints. Paths are resolved from the DALA_DIR and DALA_DEV_DIR environment variables, falling back to ../dala and ../dala_dev relative to the generated project location.

bundle_prefix()

@spec bundle_prefix() :: String.t()

generate(app_name, dest_dir \\ ".", opts \\ [])

@spec generate(String.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Generates a new project at dest_dir/<app_name> from the bundled templates.

Returns {:ok, project_dir} or {:error, reason}.

liveview_generate(app_name, dest_dir \\ ".", opts \\ [])

@spec liveview_generate(String.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Generates a LiveView-wrapped Dala project at dest_dir/<app_name>.

This calls mix phx.new as a subprocess to create the Phoenix project, then:

  • Patches mix.exs to add the dala / dala_dev dependencies

  • Copies the standard Android/iOS native boilerplate

  • Injects DalaHook into assets/js/app.js

  • Injects the bridge <div> into root.html.heex

  • Generates lib/<app>/dala_screen.ex

  • Writes dala.exs with liveview_port: 4000

  • Patches lib/<app>/application.ex to start Dala.App alongside Phoenix

Returns {:ok, project_dir} or {:error, reason}.

liveview_phoenix_owned?(path, root, opts)

@spec liveview_phoenix_owned?(String.t(), String.t(), keyword()) :: boolean()

When generating a LiveView project, mix phx.new already produced its own mix.exs, config/, lib/<app>/, lib/<app>_web/, .gitignore, and assets/ — and those are the correct versions for a Phoenix app (with gettext, telemetry_metrics, etc.). The native template's same-named files are written for the bare-Dala path and would clobber Phoenix's, leaving the project unable to compile.

When :liveview is true in opts, this predicate returns true for any template path that Phoenix already owns, so the copy step skips it. Files that are unique to Dala (dala.exs, src/<app>.erl, android/, ios/) still get emitted normally.

Public for testing — guards against the regression where a new template path lands in the native tree without being added to the LiveView blocklist.