Packages
A driver for TypeDB 3.12+ in Elixir, built on the TypeDB gRPC API. Streaming answers with no count limit, and transactions that pipeline.
Current section
Files
Jump to
Current section
Files
typedb_grpc
mix.exs
mix.exs
defmodule TypeDB.GRPC.MixProject do
use Mix.Project
@version "0.2.0"
@source_url "https://github.com/NoeticEcho/TypedbEx"
def project do
[
app: :typedb_grpc,
version: @version,
elixir: "~> 1.18",
elixirc_paths: elixirc_paths(Mix.env()),
# The generated protobuf modules are machine-written and 3,000 lines wide.
# Compiling them under --warnings-as-errors would make this package's
# build hostage to whichever protoc-gen-elixir generated them, so they are
# excluded from the strict pass rather than edited by hand — editing them
# is what `mix typedb.grpc.gen` exists to make unnecessary.
elixirc_options: [debug_info: Mix.env() != :prod],
start_permanent: Mix.env() == :prod,
deps: deps(),
aliases: aliases(),
description: description(),
package: package(),
docs: docs(),
name: "TypeDB.GRPC",
source_url: @source_url,
dialyzer: [
plt_add_apps: [:mix, :ex_unit],
ignore_warnings: ".dialyzer_ignore.exs",
list_unused_filters: true,
flags: [:error_handling, :extra_return, :missing_return, :unmatched_returns]
]
]
end
def cli do
[preferred_envs: [docs: :docs, "hex.publish": :docs]]
end
def application do
[extra_applications: [:logger]]
end
# `TYPEDB_GRPC_PUBLISH=1` changes what `:typedb` *is* — a path dependency in
# this repository, a Hex package when published — so `deps/` has to be fetched
# again under the same variable. Forgetting that is not a subtle failure but it
# is an unhelpful one: `mix hex.publish` builds documentation, the docs
# environment finds no Hex copy of `typedb`, and the message says
# "run mix deps.get" without saying that the variable has to be set for it too.
#
# So the fetch and the build travel together, and the irreversible step stays
# separate and deliberate: this prepares and shows the artefact, and publishing
# it is still a thing a person types.
defp aliases do
["publish.prepare": ["deps.get", "hex.build"]]
end
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
defp deps do
[
# The point of depending on the HTTP driver rather than vendoring its
# value types: an application that switches transports keeps every
# pattern match it wrote. `%TypeDB.Error{}`, `%TypeDB.Concept.Attribute{}`
# and the rest are the same structs from the same module, so switching is
# a line in a data-access module rather than a rewrite above it.
{:typedb, typedb_dependency()},
# gRPC and protobuf are hard dependencies, unlike this driver's sibling
# where every transport is optional. There is no second way to speak this
# protocol, so pretending otherwise would only move the failure later.
{:grpc, "~> 1.0"},
# `Google.Rpc.ErrorInfo` and `Google.Rpc.DebugInfo` are where TypeDB puts
# the error code and the human message, so this driver reads them by name.
# It arrives transitively through `:grpc` today; depending on a dependency
# of a dependency is how a build breaks on an unrelated upgrade.
{:googleapis, "~> 0.1"},
{:protobuf, "~> 0.17"},
{:gun, "~> 2.0"},
# Optional for the same reason and on the same terms as in the sibling
# package: TypeDB's `decimal` values decode to `Decimal.t()` when the host
# application already has the library and to a float otherwise. Declared
# so the version this driver is written against is visible and resolvable,
# never fetched on its own.
{:decimal, "~> 2.4 or ~> 3.0", optional: true},
# Test-only, and only for the shared behaviour suite: it drives `typedb`
# as well as this package, and `typedb`'s default transport is Finch —
# which is optional there, so nothing pulls it in here. Running the suite
# through the default adapter rather than through `:httpc` keeps it
# comparing what people actually use.
{:finch, "~> 0.23", only: [:dev, :test]},
{:stream_data, "~> 1.1", only: [:dev, :test], runtime: false},
{:ex_doc, "~> 0.34", only: :docs, runtime: false},
{:credo, "~> 1.7", only: [:dev], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev], runtime: false}
]
end
# A path in this repository, a version requirement when publishing.
#
# The path is what makes the monorepo worth having: a change to the shared
# structs is visible to both packages without a release. Hex refuses a path
# dependency outright, so the release workflow sets `TYPEDB_GRPC_PUBLISH=1`
# and gets the version instead.
#
# Keyed on an environment variable rather than on `Mix.env/0`, because
# `mix hex.build` runs in `:dev` like everything else and would otherwise
# build an unpublishable package that fails at the last step of a release.
#
# Pinned to the sibling's *minor*, not just below 1.0: `~> 0.10` would admit
# 0.11, and this repository's own rule is that while `typedb` is in 0.x a minor
# carries anything a 1.x would call breaking. This package pattern-matches the
# sibling's structs, so that is exactly the kind of change it would meet.
@typedb_requirement "~> 0.10.0"
defp typedb_dependency do
if System.get_env("TYPEDB_GRPC_PUBLISH") in [nil, "", "0"] and File.exists?("../typedb/mix.exs") do
[path: "../typedb", override: true]
else
@typedb_requirement
end
end
defp description do
"A driver for TypeDB 3.12+ in Elixir, built on the TypeDB gRPC API. " <>
"Streaming answers with no count limit, and transactions that pipeline."
end
defp package do
[
name: "typedb_grpc",
licenses: ["Apache-2.0"],
files: ~w(lib .formatter.exs mix.exs README.md LICENSE CHANGELOG.md CONTRIBUTING.md),
links: %{
"GitHub" => @source_url,
"Changelog" => "#{@source_url}/blob/main/typedb_grpc/CHANGELOG.md",
"TypeDB" => "https://typedb.com",
"TypeDB protocol" => "https://github.com/typedb/typedb-protocol"
}
]
end
defp docs do
[
main: "readme",
# This package's tags are prefixed — two packages in one repository cannot
# both answer to `v*` — and ex_doc builds source links relative to the Mix
# project root, which here is one level below the repository root. 0.1.0
# got both wrong, so every "source" link it published was a 404.
source_ref: "typedb_grpc-v#{@version}",
source_url: @source_url,
source_url_pattern: "#{@source_url}/blob/typedb_grpc-v#{@version}/typedb_grpc/%{path}#L%{line}",
extras: ["README.md", "CHANGELOG.md", "CONTRIBUTING.md", "LICENSE"],
# The generated protocol modules are an implementation detail with 3,000
# lines of machine-written documentation-free structs. They are public
# only because Elixir has no other visibility.
filter_modules: fn module, _meta ->
not String.starts_with?(inspect(module), "Typedb.Protocol")
end,
groups_for_modules: [
Connection: [TypeDB.GRPC, TypeDB.GRPC.Connection, TypeDB.GRPC.Config],
Querying: [TypeDB.GRPC.Transaction],
Administration: [TypeDB.GRPC.Database, TypeDB.GRPC.Server, TypeDB.GRPC.User]
]
]
end
end