LiveVueContract (live_vue_contract v0.3.1)

Copy Markdown View Source

Makes the props contract between <.vue> and defineProps<T>() red before production.

The single source of truth is the Vue component's defineProps<T>(). A Mix compiler turns every .vue file into assets/vue/contract.json (one JSON-Schema subset per component, regenerated whenever a .vue/.ts source changes); this module checks the Elixir side against it twice:

  • at compile time, in ~H and in the module's .heex files: every literal <.vue v-component="X" ...> (and every <.X> shortcut) must pass exactly the props X declares — missing required prop, undeclared prop, unknown or ambiguous component name are CompileErrors;
  • at render time (dev and test), in vue/1: the encoded props must match the nested schema — renamed key inside a list item, string instead of number, unexpected null raise ArgumentError with the JSON path. Off in prod.

Setup

# mix.exs
{:live_vue_contract, "~> 0.3"},
compilers: [:live_vue_contract, :phoenix_live_view] ++ Mix.compilers()

# lib/my_app_web.ex, in html_helpers, replacing `use LiveVue` and `use LiveVue.Components`
use LiveVueContract

$ npm install -D vue-component-meta typescript

Then mix compile writes assets/vue/contract.json — commit it, so CI and Docker builds without node still get the compile-time check.

Options

  • shared_props: true — compile templates through LiveVue.SharedPropsView (injects v-socket and config :live_vue, :shared_props) instead of the plain ~H.
  • shortcuts: false — do not define <.ComponentName> functions.

Config

config :live_vue_contract,
  vue_root: ["assets/vue"],             # where the components live (like LiveVue.Components)
  watch: [],                            # extra globs that regenerate the contract (prop types are tracked)
  contract: "assets/vue/contract.json",
  tsconfig: "tsconfig.json",
  validate: Mix.env() != :prod,         # render-time validation; :warn = log instead of raise
  strict: false                         # extra nested keys: warning (false) or error (true)

Summary

Functions

~H that compiles as usual and then checks every <.vue> tag against the contract.

Drop-in for LiveVue.vue/1 that validates the props against the contract first.

Functions

sigil_H(template, modifiers)

(macro)

~H that compiles as usual and then checks every <.vue> tag against the contract.

vue(assigns)

Drop-in for LiveVue.vue/1 that validates the props against the contract first.