fix: make the document projectable into Java
The java row could not produce a client that compiles. Four separate causes,
all found by building the tree rather than reading it:
- library `native` is unusable at this spec size. Its oneof_model.mustache
iterates the raw `oneOf` type-name set and emits `{{{.}}}.class`, which stops
being legal Java the moment a variant is an array — `List<CloudEvent>.class`.
Three schemas have an inline array in a oneOf, and that is 532 javac errors.
Every other Java library iterates `composedSchemas.oneOf` and guards on
`isArray`; okhttp-gson, jersey3 and apache-httpclient all compile. Still
broken in 7.24.0, so it is not waiting on a version bump. okhttp-gson also
puts the two JVM rows on one HTTP+JSON stack — kotlin is already okhttp4+gson.
- `skipFormModel` defaults to true, so the generator skips a multipart form
model but still imports it from the API class that used it. edge_deployFunction
offers octet-stream AND multipart, so FunctionsApi imported a class nobody
emitted. generate.py now merges a per-row `global:` map into
--global-property; only the java row sets it, because changing it for
everyone would churn every other client's committed output.
- affiliates' `isAffiliate: {type: boolean, const: true|false}` projects as a
single-member enum whose member is a String assigned to a Boolean field. The
invariant moves into the description; the wire value is unchanged.
- vector's PointId is `oneOf: [integer, string+format:uuid]`, and inside a
oneOf that format maps to java.util.UUID, on which the generator then calls
UUID.validateJsonElement() — a method only its own models have. `format` is
an annotation, not a constraint, so dropping it changes no wire value and the
description still says what the field is.
The two spec edits are at the per-service source and re-woven, so merge.py does
not undo them: 2 insertions, 3 deletions in hanzo.yaml and nothing else.
Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -354,7 +354,11 @@ components:
|
||||
properties:
|
||||
isAffiliate:
|
||||
type: boolean
|
||||
const: false
|
||||
# Always false — this is the not-enrolled shape. Stated in prose
|
||||
# rather than as `const: false` because openapi-generator projects a
|
||||
# boolean const as a single-member enum whose member is a String
|
||||
# assigned to a Boolean field, which is not valid Java (or Kotlin).
|
||||
description: Always false — this is the not-enrolled shape.
|
||||
defaultRateBps:
|
||||
type: integer
|
||||
format: int64
|
||||
@@ -366,7 +370,9 @@ components:
|
||||
properties:
|
||||
isAffiliate:
|
||||
type: boolean
|
||||
const: true
|
||||
# Always true here — see the note on NotEnrolled.isAffiliate for why
|
||||
# this is prose and not `const: true`.
|
||||
description: Always true — this org is an affiliate.
|
||||
id:
|
||||
type: string
|
||||
status:
|
||||
|
||||
+8
-2
@@ -88,13 +88,19 @@ def prune(stage, drops):
|
||||
def emit(name, cfg, spec, version, out):
|
||||
"""Run the generator for one language into a staging dir."""
|
||||
props = ",".join(f"{k}={v}" for k, v in cfg.get("properties", {}).items())
|
||||
# Docs and stub tests are ~4000 files of nothing at this spec size. A row
|
||||
# may add its own global properties; they are per-language for the same
|
||||
# reason `properties` is — changing one here would churn every other
|
||||
# client's committed output.
|
||||
glob = ["apis", "models", "supportingFiles",
|
||||
"apiDocs=false", "modelDocs=false", "apiTests=false", "modelTests=false"]
|
||||
glob += [f"{k}={v}" for k, v in cfg.get("global", {}).items()]
|
||||
cmd = [
|
||||
"java", "-Xmx2g", "-jar", jar(version), "generate",
|
||||
"-g", cfg["generator"],
|
||||
"-i", spec,
|
||||
"-o", out,
|
||||
# Docs and stub tests are ~4000 files of nothing at this spec size.
|
||||
"--global-property", "apis,models,supportingFiles,apiDocs=false,modelDocs=false,apiTests=false,modelTests=false",
|
||||
"--global-property", ",".join(glob),
|
||||
]
|
||||
if props:
|
||||
cmd += ["--additional-properties", props]
|
||||
|
||||
+2
-3
@@ -58346,7 +58346,7 @@ components:
|
||||
properties:
|
||||
isAffiliate:
|
||||
type: boolean
|
||||
const: true
|
||||
description: "Always true \u2014 this org is an affiliate."
|
||||
id:
|
||||
type: string
|
||||
status:
|
||||
@@ -58460,7 +58460,7 @@ components:
|
||||
properties:
|
||||
isAffiliate:
|
||||
type: boolean
|
||||
const: false
|
||||
description: "Always false \u2014 this is the not-enrolled shape."
|
||||
defaultRateBps:
|
||||
type: integer
|
||||
format: int64
|
||||
@@ -90874,7 +90874,6 @@ components:
|
||||
oneOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
format: uuid
|
||||
vector_PointStruct:
|
||||
type: object
|
||||
required:
|
||||
|
||||
@@ -107,8 +107,28 @@ sdks:
|
||||
repo: java-sdk
|
||||
generator: java
|
||||
take: { src/main/java/ai/hanzo/cloud: hanzo-java-cloud/src/main/java/ai/hanzo/cloud }
|
||||
# edge_deployFunction offers both application/octet-stream and
|
||||
# multipart/form-data. The generator skips a multipart form model by default
|
||||
# yet still imports it from the API class that used it, so FunctionsApi
|
||||
# imports a class nobody emitted. Emitting it is the fix; it is set here and
|
||||
# not in generate.py because it would churn every other client's output.
|
||||
global:
|
||||
skipFormModel: "false"
|
||||
properties:
|
||||
library: native # java.net.http — no third-party HTTP dependency
|
||||
# `native` (java.net.http, no third-party HTTP dependency) is the library
|
||||
# this row wants and cannot have: its oneof_model.mustache iterates the
|
||||
# raw `oneOf` type-name set and emits `{{{.}}}.class`, which is illegal
|
||||
# Java the moment a variant is an array — `List<CloudEvent>.class`. Three
|
||||
# schemas in hanzo.yaml have an inline array in a oneOf
|
||||
# (cloud_post_v1_event's body, gateway_createCompletion's `prompt`,
|
||||
# search_deleteDocumentsByFilter's `filter`), so `native` produces 532
|
||||
# javac errors. Every other Java library iterates `composedSchemas.oneOf`
|
||||
# and guards on `isArray`, so okhttp-gson, jersey3 and apache-httpclient
|
||||
# all compile; the bug is still present in 7.24.0, so this is not waiting
|
||||
# on a version bump. okhttp-gson is the generator's default and puts the
|
||||
# two JVM rows on ONE HTTP+JSON stack — the kotlin row below is already
|
||||
# okhttp4 + gson.
|
||||
library: okhttp-gson
|
||||
groupId: ai.hanzo
|
||||
artifactId: hanzo-java-cloud
|
||||
invokerPackage: ai.hanzo.cloud
|
||||
|
||||
+5
-1
@@ -105,8 +105,12 @@ components:
|
||||
description: A point identifier — an integer or a UUID string.
|
||||
oneOf:
|
||||
- type: integer
|
||||
# `format: uuid` is deliberately absent: inside a oneOf, openapi-generator
|
||||
# maps it to java.util.UUID and then emits UUID.validateJsonElement(),
|
||||
# a method only its own generated models have. The format is an
|
||||
# annotation, not a constraint — the wire value is unchanged and the
|
||||
# description above still says what it is.
|
||||
- type: string
|
||||
format: uuid
|
||||
DenseVector:
|
||||
description: One unnamed vector.
|
||||
type: array
|
||||
|
||||
Reference in New Issue
Block a user