# `AshNeo4j`
[🔗](https://github.com/diffo-dev/ash_neo4j/blob/v0.8.1/lib/ash_neo4j.ex#L5)

Top-level helpers for the AshNeo4j data layer.

## N-world projection (`worlds/1`)

> #### Exploratory (#273) {: .warning}
>
> `worlds/1` is a pre-1.0 exploration to unblock cross-domain late
> binding in downstream consumers ([diffo#172](https://github.com/diffo-dev/diffo/issues/172)).
> Its shape may change before 1.0 — feedback from real use is the point.

# `world`

```elixir
@type world() :: {domain :: module(), resource :: module()}
```

A `(domain, resource)` world the node participates in.

# `worlds`

```elixir
@spec worlds(Ash.Resource.record()) :: [world()]
```

The `(domain, resource)` worlds a node participates in, **outermost-first**.

An Ash read returns a struct of the queried resource type — the "base
world." But a Neo4j node carries labels for *every* `(Domain, Resource)`
world it participates in (the data layer records them on the read
struct's `__metadata__.labels`). A polymorphic node typically belongs to
several. An **outer** world contains the inner worlds and introduces new
aspects, so it carries more labels — the more labels, the more nuanced
(more outer) the world. `worlds/1` projects the node's labels back to the
loadable resource modules, **outermost-first**, so a consumer can recover
the outer type(s) without reaching into AshNeo4j internals or dropping to
Cypher.

    record = Ash.get!(SomeBaseInstance, id)
    AshNeo4j.worlds(record)
    #=> [{MyApp, MyApp.ConcreteInstance}, {Diffo.Provider, Diffo.Provider.Instance}]

    # Consumers typically want the outermost (most-nuanced) world:
    {domain, resource} = hd(AshNeo4j.worlds(record))

## Resolution

Resolution is **dynamic against whatever modules are loaded** — no
registry. A candidate is a loaded resource using `AshNeo4j.DataLayer`
whose own labels (`AshNeo4j.Resource.Info.all_labels/1`) are a subset of
the node's labels. Candidates are grouped by domain; the **outermost** —
the most-nuanced world, the one carrying the most labels — is kept per
domain, and the result is sorted outermost-first across domains. Outer
worlds carve known structure out of the node; what can't be resolved to a
loaded module is left **unknown** — omitted, never coerced into a known
world. The metadata describes the node, not the caller.

Returns `[]` for a record without AshNeo4j read metadata (e.g. one not
produced by this data layer).

> #### Cost {: .info}
>
> Lazy and uncached. Nothing on the read path calls this — it runs only
> when you call `worlds/1`, and each call scans the loaded modules for
> AshNeo4j resources and subset-checks their labels. Not a hot path by
> construction; if real use shows otherwise, a supervised ETS index is the
> follow-up.

---

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