Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/renderer-parity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- run: bun run build:native
if: matrix.renderer == 'native'

- name: Check naming regressions
- name: Check configuration parity and runtime regressions
if: matrix.renderer == 'native'
run: bun run test:parity
env:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ node_modules
test/*
!test/config.ts
!test/petstore.yaml
!test/configuration.yaml
!test/generated/.gitkeep
!test/generated/base/.gitkeep
!test/generated/next/.gitkeep
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ Set `OPENAPI_CODEGEN_NATIVE=0` to force the TypeScript path, or `OPENAPI_CODEGEN

Release packages include native binaries for Linux x64, macOS arm64, and Windows x64. Build a binary for the current platform with `bun run build:native`.

Run `bun run test:parity` after building the addon to compare every generated file across 64 layout combinations and representative values for every other renderer option. The matrix uses both `test/petstore.yaml` and `test/configuration.yaml`, exercises complete native and hybrid native generation, and loads generated models to check runtime references. The contradictory combination `modelsInCommon: true` with `modelsInModules: true` is rejected explicitly. Arbitrary strings and lists are covered by representative cases, not every possible value.

The separate Renderer parity workflow generates this matrix with JavaScript and native on Linux and macOS, then compares exact file lists and SHA-256 hashes. Artifacts include route reports identifying complete versus hybrid native generation. Runner integration tests cover input/output, stale-file cleanup, and unchanged files; `incremental` is currently retained as a compatibility option and does not change the writer's unchanged-file optimization.

## Common Issues

### App REST Client Interceptors
Expand Down
19 changes: 19 additions & 0 deletions native/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,25 @@ impl<'a> EndpointExtractor<'a> {
} else {
obj.get("schema").unwrap_or(&Value::Null)
};
let mut described_schema;
let schema = if self.options.with_description {
described_schema = schema.clone();
if let Some(object) = described_schema.as_object_mut() {
object.insert(
"description".into(),
Value::String(
obj.get("description")
.and_then(Value::as_str)
.unwrap_or("")
.trim()
.to_string(),
),
);
}
&described_schema
} else {
schema
};
let required = location == "path"
|| obj
.get("required")
Expand Down
16 changes: 16 additions & 0 deletions native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,21 @@ pub fn compile_data(source: String, yaml: bool, options_json: String) -> Result<
ordered_schemas.extend(schemas);
let mut usage_tags: rustc_hash::FxHashMap<String, rustc_hash::FxHashSet<String>> =
rustc_hash::FxHashMap::default();
// Direct inline responses need not produce a named generated schema. Keep
// the resolver's reference usage too, so those endpoints still contribute
// to ownership when the rendered-schema graph is propagated below.
for (reference, tags) in &resolver.schema_tags {
let name = zod::schema_name(
reference.rsplit('/').next().unwrap_or_default(),
&options.schema_suffix,
);
if ordered_schemas.contains_key(&name) {
usage_tags
.entry(name)
.or_default()
.extend(tags.iter().cloned());
}
}
for endpoint in &endpoints {
let tag = endpoint
.get("tags")
Expand Down Expand Up @@ -413,6 +428,7 @@ pub fn compile_data(source: String, yaml: bool, options_json: String) -> Result<
"endpoints": if rendered_complete { Value::Array(Vec::new()) } else { Value::Array(endpoints) },
"schemas": if rendered_complete { compact() } else { Value::Object(ordered_schemas) },
"schemaOwners": if rendered_complete { compact() } else { Value::Object(schema_owners) },
"schemaUsageTags": if rendered_complete { compact() } else { serde_json::to_value(usage_tags).unwrap() },
"schemaRefs": if rendered_complete { compact() } else { Value::Object(schema_refs) },
"circularSchemas": if rendered_complete { Value::Array(Vec::new()) } else { serde_json::to_value(circular_schemas).unwrap() },
"topologyOrder": if rendered_complete { Value::Array(Vec::new()) } else { serde_json::to_value(topology_order).unwrap() },
Expand Down
Loading
Loading