# `LiveVueContract`
[🔗](https://github.com/Egorrko/live_vue_contract/blob/v0.3.1/lib/live_vue_contract.ex#L1)

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
    `CompileError`s;
  * 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)

# `sigil_H`
*macro* 

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

# `vue`

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
