Current section
Files
Jump to
Current section
Files
lib/ex_okf.ex
defmodule ExOKF do
@moduledoc """
ExOKF — the reference Elixir implementation of the Open Knowledge Format (OKF).
Provides standards-compliant parsing, validation with rich diagnostics,
lossless reading/writing, link resolution, graph indexing, querying, and
provenance-aware AI context assembly.
## Public API
{:ok, bundle} = ExOKF.load("path/to/bundle")
{:ok, diags} = ExOKF.validate(bundle)
:ok = ExOKF.write(bundle, "path/to/out")
concepts = ExOKF.query(bundle, type: "BigQuery Table")
{:ok, ctx} = ExOKF.context(bundle, "tables/orders")
GraphBLAS acceleration, advanced ranking, and MCP integration are ExOKF
**extensions** layered on top of core OKF conformance — see the roadmap
in the project README.
"""
alias ExOKF.{Bundle, Context, Diagnostics, Parser, Query, Validator, Writer}
@doc """
Loads an OKF bundle from a filesystem path.
Delegates to `ExOKF.Parser.load/2`.
## Parameters
* `path` (`String.t()`) — path to the bundle directory
* `opts` (`keyword()`) — parser options:
* `:max_concurrency` (`pos_integer()`) — parallel parse tasks
* `:timeout` (`timeout()`) — per-task timeout
* `:build_graph` (`boolean()`) — index link graph (default `true`)
## Returns
* `{:ok, ExOKF.Bundle.t()}` — loaded bundle
* `{:error, term()}` — e.g. `{:not_a_directory, path}`
## Examples
iex> {:ok, bundle} = ExOKF.load(ExOKF.TestSupport.minimal_fixture_path())
iex> ExOKF.Bundle.size(bundle) >= 1
true
"""
@spec load(String.t(), keyword()) :: {:ok, Bundle.t()} | {:error, term()}
def load(path, opts \\ []), do: Parser.load(path, opts)
@doc """
Validates a bundle, returning diagnostics.
Warnings alone do not fail validation. Only error-severity diagnostics
produce `{:error, diagnostics}`.
Delegates to `ExOKF.Validator.validate/1`.
## Parameters
* `bundle` (`ExOKF.Bundle.t()`) — loaded OKF bundle
## Returns
* `{:ok, ExOKF.Diagnostics.t()}` — conformant (warnings allowed)
* `{:error, ExOKF.Diagnostics.t()}` — non-conformant
## Examples
iex> bundle = ExOKF.TestSupport.sample_bundle()
iex> {:ok, diags} = ExOKF.validate(bundle)
iex> is_struct(diags, ExOKF.Diagnostics)
true
"""
@spec validate(Bundle.t()) :: {:ok | :error, Diagnostics.t()}
def validate(%Bundle{} = bundle), do: Validator.validate(bundle)
@doc """
Writes a bundle to `destination` (lossless round-trip of known + unknown frontmatter).
Delegates to `ExOKF.Writer.write/2`.
## Parameters
* `bundle` (`ExOKF.Bundle.t()`) — in-memory bundle
* `destination` (`String.t()`) — output directory path
## Returns
* `:ok` — success
* `{:error, term()}` — filesystem error
## Examples
iex> bundle = ExOKF.TestSupport.minimal_bundle()
iex> dest = Path.join(System.tmp_dir!(), "ex_okf_api_write_" <> Integer.to_string(:erlang.phash2(make_ref())))
iex> ExOKF.write(bundle, dest)
:ok
"""
@spec write(Bundle.t(), String.t()) :: :ok | {:error, term()}
def write(%Bundle{} = bundle, destination), do: Writer.write(bundle, destination)
@doc """
Queries concepts in the bundle.
Delegates to `ExOKF.Query.query/2`. See that module for filter types.
## Parameters
* `bundle` (`ExOKF.Bundle.t()`) — loaded OKF bundle
* `filters` (`keyword()`) — AND-combined filters (`:type`, `:tag`, `:id`, `:has_resource`)
## Returns
A list of matching `ExOKF.Concept.t()`.
## Examples
iex> bundle = ExOKF.TestSupport.sample_bundle()
iex> ExOKF.query(bundle, type: "BigQuery Dataset") |> Enum.map(& &1.id)
["datasets/sales"]
"""
@spec query(Bundle.t(), keyword()) :: [ExOKF.Concept.t()]
def query(%Bundle{} = bundle, filters \\ []), do: Query.query(bundle, filters)
@doc """
Assembles provenance-aware context for a concept.
Delegates to `ExOKF.Context.build/3`.
## Parameters
* `bundle` (`ExOKF.Bundle.t()`) — loaded OKF bundle
* `concept_id` (`String.t()`) — seed concept id
* `opts` (`keyword()`) — `:depth`, `:token_budget`, `:include_seed`, `:chars_per_token`
## Returns
* `{:ok, ExOKF.Context.t()}` — assembled context
* `{:error, term()}` — e.g. `{:unknown_concept, id}`
## Examples
iex> bundle = ExOKF.TestSupport.sample_bundle()
iex> {:ok, ctx} = ExOKF.context(bundle, "tables/orders", depth: 1)
iex> ctx.seed
"tables/orders"
"""
@spec context(Bundle.t(), String.t(), keyword()) :: {:ok, Context.t()} | {:error, term()}
def context(%Bundle{} = bundle, concept_id, opts \\ []) do
Context.build(bundle, concept_id, opts)
end
end