# `Oasis.Spec.OpenAPIRefResolver`
[🔗](https://github.com/xinz/oasis/blob/main/lib/oasis/spec/openapi_ref_resolver.ex#L1)

Resolves the structural OpenAPI Reference Objects selected by Oasis preparation.

This module is intentionally OpenAPI-aware and deliberately **not** a generic
JSON Schema `$ref` expander. It selects structural OpenAPI Reference Object
locations such as:

- Path Item Objects
- Parameter Objects
- Request Body Objects
- Response Objects
- Security Scheme Objects

The generic `$ref` mechanics are delegated to `JSONSchex.Ref.resolve_selected/2`:
URI resolution, JSON Pointer lookup, external loading, base URI propagation,
and cycle detection.

Schema Object `$ref` values are not selected here. They are preserved so
`JSONSchex.bundle_fragment/2` can resolve the schema graph with proper JSON
Schema Draft 2020-12 semantics.

## Selection rules

`openapi_reference_object?/2` returns `true` only for the following
structural OpenAPI Reference Object locations, and `false` everywhere else
(including any Schema Object location):

- `#/paths/{url}` — Path Item Object
- `#/paths/{url}/parameters/{i}` — path-item-level Parameter Object
- `#/paths/{url}/{verb}/parameters/{i}` — operation-level Parameter Object
- `#/paths/{url}/{verb}/requestBody` — Request Body Object
- `#/paths/{url}/{verb}/responses/{status}` — Response Object
- `#/components/securitySchemes/{name}` — Security Scheme Object

where `{url}` starts with `/` and `{verb}` is one of the standard HTTP
methods Oasis generates routes for (`get`, `head`, `post`, `put`, `patch`,
`delete`, `options`). Anything outside this list — Schema Object refs,
callbacks, links, examples, server objects, etc. — is left intact.

## Loader

External OpenAPI references (e.g. `./common.yaml#/components/parameters/UserId`)
are loaded through `JSONSchex.Ref.resolve_selected/2`'s `:loader` option.
`resolve/2` defaults `:loader` to `&Oasis.Spec.Document.load_external/1`
via `Keyword.put_new/3`, so callers may override it by passing their own
loader. JSONSchex accepts `{:ok, schema}` or an atom-keyed metadata wrapper
`{:ok, %{document: schema, base_uri: base_uri}}`.

JSONSchex owns resource base propagation for loaded documents. Oasis's role in
this resolver is limited to choosing which OpenAPI Reference Objects should be
resolved before generation.

## Caller `opts` contract

`resolve/2` is deliberately opinionated about the options it forwards to
`JSONSchex.Ref.resolve_selected/2`:

- `:select` — **force-overridden** to `&openapi_reference_object?/2`. A
  caller-supplied `:select` is silently discarded. This is intentional:
  the whole point of this module is to fix the OpenAPI selection policy
  so the Oasis/JSONSchex boundary (Schema Object refs are preserved for
  JSONSchex) stays consistent across all callers.
- `:loader` — **defaulted** via `Keyword.put_new/3`. Callers may override
  it with a custom loader, or pass `loader: nil` to opt out of external
  loading entirely.
- `:base_uri` — **caller-controlled**. Used by JSONSchex to resolve
  relative external OpenAPI refs. The `resolve/1` arity-1 form sets it to
  `document.source_path` automatically; the arity-2 form takes whatever
  the caller passes.
- Any other option recognized by `JSONSchex.Ref.resolve_selected/2` is
  forwarded unchanged.

# `openapi_reference_object?`

```elixir
@spec openapi_reference_object?(list(), map()) :: boolean()
```

Returns `true` when the path/node pair represents an OpenAPI Reference Object
location that Oasis needs to dereference before generation.

Schema Object locations intentionally return `false` so JSON Schema refs remain
available for JSONSchex fragment compilation/bundling.

# `resolve`

```elixir
@spec resolve(Oasis.Spec.Document.t()) :: Oasis.Spec.Document.t()
```

Resolves OpenAPI Reference Objects inside a loaded `Oasis.Spec.Document`.

The returned document keeps Schema Object refs intact, but selected path items,
parameters, request bodies, responses, and security schemes are dereferenced.
Response refs are prepared eagerly even though current request-handler
generation does not otherwise consume response schemas; a missing selected
response resource therefore remains an invalid specification.

# `resolve`

```elixir
@spec resolve(
  map(),
  keyword()
) :: map()
```

Resolves OpenAPI Reference Objects in a decoded OpenAPI map.

## Options

- `:base_uri` — file path or URI used to resolve relative external OpenAPI
  refs. Required when the document contains external refs.
- `:loader` — optional. Defaults to `&Oasis.Spec.Document.load_external/1`. Pass
  a custom function to use your own loader, or `nil` to disable external loading.
  Success may return `{:ok, schema}` or an atom-keyed metadata wrapper
  `{:ok, %{document: schema, base_uri: base_uri}}`.
- Any other option recognized by `JSONSchex.Ref.resolve_selected/2` is
  forwarded unchanged.

## Reserved options

- `:select` — **force-overridden** to `&openapi_reference_object?/2`. A
  caller-supplied `:select` is silently discarded. See the moduledoc
  "Caller `opts` contract" section for the rationale.

---

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