Skip to content

feat!: generate the REST client with OpenAPI.jl 1.x (0.5.0) - #25

Merged
tanmaykm merged 2 commits into
mainfrom
tan/openapi1-client
Sep 11, 2026
Merged

feat!: generate the REST client with OpenAPI.jl 1.x (0.5.0)#25
tanmaykm merged 2 commits into
mainfrom
tan/openapi1-client

Conversation

@tanmaykm

@tanmaykm tanmaykm commented Sep 11, 2026

Copy link
Copy Markdown
Member

Replaces the openapi-generator (java) client, which needed OpenAPI.jl 0.2 and JSON 0.21, with a module generated natively by OpenAPI.jl 1.1 from the same specification. Two commits: spec corrections, then the migration.

Spec corrections (commit 1)

A strict, validating client exposed places where the spec did not describe what OPA actually sends. The openapi-generator client tolerated them.

  • Values OPA documents as "any JSON value" were typed object: getDocumentSuccessResponse.result (a true result failed response validation), compileSuccessResponse.result, partialQuerySchema.input/options, patchOperation.value, queryParameterPost.input, the createDocument request body. They are now untyped, matching their descriptions and the previous ::Any fields.
  • inputSchema declares its single input property instead of being a free-form object.
  • policy.ast.rules[].body[].terms is an object for a single term and an array for a call; it is now untyped (was object, which broke GET /v1/policies).
  • GET /health 200 and DELETE /v1/policies/{id} 200 return a JSON body ({}, plus metrics for the delete) although they were declared empty; they now reference new healthyResponse / deletePolicySuccessResponse components.
  • The explain enum is a named schema (explainMode) so the generated type has a stable name.

Migration (commit 2)

  • specs/openapi/generate.jl regenerates src/client/OPAClient.jl in strict mode from the pinned environment in specs/openapi/Project.toml (OpenAPI 1.1.0). The generated file is committed; generate.sh and the per-model markdown tree are gone.
  • The module is OPAClient; OpenPolicyAgent.Client is an alias of it, because a module cannot be named Client while defining the Client(server; kwargs...) constructor.
  • Dependencies follow the emitted code: OpenAPI 1.1.1, HTTP 2, JSON 1.7, Julia ≥ 1.10 (drops 1.6–1.9); TimeZones is no longer needed (the spec has no date-time fields).
  • Tests rewritten for the new API; docs (client.md, reference.md, ast_walker.md) and CI updated. docs/src/client.md has a 0.4 → 0.5 migration table.

Breaking changes for callers

0.4 0.5
OpenAPI.Clients.Client(url; escape_path_params=false) Client.Client(url)
api = Client.DataApi(openapi_client) no per-tag API structs; pass client as a keyword
Client.get_document_with_path(api, path, Dict("input" => x)) Client.getdocumentwithpath(path, Client.InputSchema(; input = x); client)
response, http_resp = Client.get_document(api, path) response = Client.getdocument(path; client); with_http_info = true for an ApiResponse
Client.post_compile(api; partial_query_schema = s) Client.postcompile(; body = s, client)
explain = true explain = Client.ExplainMode("full")
error bodies returned as the result Client.ApiError thrown, decoded body in ex.decoded
metrics::Dict{String,Any} metrics structs, entries in metrics.additional_properties

Dependencies

Testing

203/203 locally on Julia 1.10.11 and 1.12.7 (originally against the JuliaComputing/OpenAPI.jl#112 branch, since released as 1.1.1). CI is green on all jobs.

x86 (32-bit) has been dropped from the matrix: Reseau.jl, pulled in via HTTP 2.x, fails to precompile on i686 Linux and Windows (JuliaServices/Reseau.jl#156). 32-bit is therefore untested.

@tanmaykm tanmaykm mentioned this pull request Sep 11, 2026
Several schemas used 'type: object' for values that OPA documents as any
JSON value, and two 200 responses were declared empty although OPA returns
a JSON body. The openapi-generator client tolerated both; a strict,
validating client does not.

- getDocumentSuccessResponse.result, compileSuccessResponse.result,
  partialQuerySchema.input/options, patchOperation.value,
  queryParameterPost.input and the createDocument request body are now
  untyped (any JSON value), matching their descriptions and OPA's behaviour.
- inputSchema declares its single 'input' property instead of being a
  free-form object.
- policy.ast.rules[].body[].terms is untyped: OPA emits an object for a
  single term and an array for a call.
- GET /health 200 and DELETE /v1/policies/{id} 200 carry an application/json
  body ('{}', plus 'metrics' for the delete), so they reference new
  healthyResponse and deletePolicySuccessResponse components instead of
  noContentResponse.
- The explain parameter's enum is a named schema (explainMode) so generated
  clients get a stable type name.
Replace the openapi-generator (java) client, which needed OpenAPI.jl 0.2 and
JSON 0.21, with a module generated natively by OpenAPI.jl 1.1 from the same
specification. specs/openapi/generate.jl regenerates it strictly (a spec
defect fails generation) from the pinned environment in specs/openapi/.

The generated module is OPAClient; OpenPolicyAgent.Client is an alias, since
a module cannot be named Client while defining the Client(server) constructor.

Breaking changes for callers (see docs/src/client.md for a migration table):
- operations are flat functions named after the operationId
  (get_document_with_path -> getdocumentwithpath) taking client as a keyword;
  the per-tag API structs (DataApi, ...) are gone
- operations return the decoded body; with_http_info=true returns an
  ApiResponse; non-2xx responses throw Client.ApiError with the decoded body
  in ex.decoded instead of returning it
- request bodies are typed (InputSchema(; input = ...)); explain takes
  Client.ExplainMode; free-form objects such as metrics are structs whose
  entries live in additional_properties
- the client is constructed with Client.Client(url; headers, request_options)
  and relies on OpenAPI.jl >= 1.1.1 honouring allowReserved on the OPA path
  parameter, replacing escape_path_params=false

Dependencies follow the generated code: HTTP 2, JSON 1.7, OpenAPI 1.1.1,
Julia 1.10; TimeZones is no longer needed. Tests, docs and CI are updated
accordingly. Version 0.5.0.
@tanmaykm
tanmaykm merged commit 4f81512 into main Sep 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant