Pristine
Pristine is the shared runtime and build-time bridge for first-party OpenAPI-based Elixir SDKs.
The recommended provider-SDK boundary is:
Pristine.execute_request/3Pristine.foundation_context/1Pristine.SDK.*
The retained build-time seam is Pristine.OpenAPI.Bridge.run/3.
Pristine.context/1 also remains available when you want full manual
ports-and-adapters control, but provider SDKs should treat Pristine.Core.*
and Pristine.OpenAPI.* as internal implementation detail rather than as the
blessed SDK contract.
Runtime Boundary
Use Pristine.foundation_context/1 for the recommended production runtime:
context =
Pristine.foundation_context(
base_url: "https://api.example.com",
transport: Pristine.Adapters.Transport.Finch,
transport_opts: [finch: MyApp.Finch],
serializer: Pristine.Adapters.Serializer.JSON,
auth: [Pristine.Adapters.Auth.Bearer.new(System.fetch_env!("API_TOKEN"))]
)
Execute a normalized request spec through Pristine.execute_request/3:
request_spec = %{
id: "widgets.list",
method: :get,
path: "/v1/widgets",
path_params: %{},
query: %{"limit" => 10},
headers: %{},
body: nil,
form_data: nil,
auth: nil,
security: [%{"bearerAuth" => []}],
request_schema: nil,
response_schema: nil,
resource: "widgets",
retry: "widgets.read",
rate_limit: "widgets.integration",
circuit_breaker: "core_api",
telemetry: "request.widgets"
}
{:ok, response} = Pristine.execute_request(request_spec, context)Pristine.execute_request/3 also accepts the generated request maps emitted by
Pristine.SDK.OpenAPI.Client. In both cases, the same runtime path validation,
serialization, auth, retry, telemetry, rate-limit, and circuit-breaker wiring
still applies.
Pristine.SDK.* exposes the stable runtime-facing types used by downstream SDKs:
Pristine.SDK.ContextPristine.SDK.ResponsePristine.SDK.ErrorPristine.SDK.ResultClassificationPristine.SDK.OpenAPI.*Pristine.SDK.OAuth2.*Pristine.SDK.Profiles.Foundation
Manual Context Construction
Use Pristine.context/1 when you want complete control over the raw runtime
ports and adapters:
context =
Pristine.context(
base_url: "https://api.example.com",
transport: Pristine.Adapters.Transport.Finch,
transport_opts: [finch: MyApp.Finch],
serializer: Pristine.Adapters.Serializer.JSON,
retry: Pristine.Adapters.Retry.Noop,
telemetry: Pristine.Adapters.Telemetry.Noop
)That lower-level constructor is useful for bespoke clients and tests. The Foundation profile exists so production callers do not have to hand-wire the same resilience and telemetry stack repeatedly.
OAuth Provider Construction
SDK-facing OAuth provider construction stays tied to OpenAPI security scheme metadata, not to manifests.
provider =
Pristine.SDK.OAuth2.Provider.from_security_scheme!(
"notionOAuth",
%{
"type" => "oauth2",
"flows" => %{
"authorizationCode" => %{
"authorizationUrl" => "/v1/oauth/authorize",
"tokenUrl" => "/v1/oauth/token",
"scopes" => %{"workspace.read" => "Read workspace data"}
}
},
"x-pristine-flow" => "authorizationCode",
"x-pristine-token-content-type" => "application/json"
},
site: "https://api.notion.com"
)Pristine.SDK.OAuth2 uses the in-tree
Pristine.Adapters.OAuthBackend.Native backend by default. Browser launch and
loopback callback capture stay optional adapter seams:
Pristine.Adapters.OAuthBrowser.SystemCmdPristine.Adapters.OAuthCallbackListener.Bandit
Manual paste-back still works without those adapters, and persisted token
load/save/refresh orchestration lives in Pristine.OAuth2.SavedToken on top of
the token-source boundary.
Build-Time Bridge
Pristine.OpenAPI.Bridge.run/3 is the retained first-party build-time seam for
SDK generation. It is not the normal consumer runtime entry.
The bridge needs at least a base module and output directory:
result =
Pristine.OpenAPI.Bridge.run(
:widgets_sdk,
["openapi/widgets.json"],
base_module: WidgetsSDK,
output_dir: "lib/widgets_sdk/generated",
source_contexts: %{
{:get, "/v1/widgets"} => %{
title: "Widgets",
url: "https://docs.example.com/widgets"
}
}
)
sources = Pristine.OpenAPI.Bridge.generated_sources(result)
The returned %Pristine.OpenAPI.Result{} contains:
irsource_contextsdocs_manifest
That lets first-party SDK generators reuse the same IR, generated files, and docs manifest without exposing a manifest-shaped runtime API.