Skip to content

Merge devt into main - #45

Merged
Bombardier-C-Kram merged 17 commits into
mainfrom
devt
Oct 6, 2026
Merged

Bombardier-C-Kram merged 17 commits into
mainfrom
devt

Conversation

@Bombardier-C-Kram

@Bombardier-C-Kram Bombardier-C-Kram commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Model generation
  • Docs upgrade: per-tag docs pages (docs/tag.md.scriban), slimmer README template
  • Upgrade Scriban to 7.5.0 and Microsoft.OpenApi to 3.10.2
  • Update bundled HttpCommand to 5.11.1
  • Percent-encode path parameters
  • Send explode: false array query parameters as one delimited value
  • Let --no-validation proceed past reader errors

Scriban 7.0.6 has four advisories (GHSA-24c8-4792-22hx, GHSA-6q7j-xr26-3h2c,
GHSA-7jvp-hj45-2f2m, GHSA-q6rr-fm2g-g5x8) and Microsoft.OpenApi 3.3.0 has
GHSA-v5pm-xwqc-g5wc. The test project still referenced Scriban 6.5.2, which
failed the build with NU1605; both projects now use 7.5.0.
A value containing "/" was substituted into the path as is, so
GetProduct (productId:'N B/x') requested /products/N%20B/x, a different
route. Each value now goes through HttpCommand.UrlEncode and stays in its
own segment: /products/N%20B%2Fx.
The style and explode of query parameters were ignored, and arrays were
handed to HttpCommand.UrlEncode as they were. For Open-Meteo, whose hourly,
daily and current parameters are explode: false,
GetV1Forecast (latitude:… ⋄ longitude:… ⋄ hourly:,⊂'temperature_2m')
failed with LENGTH ERROR in UrlEncode. Such parameters are now joined by
utils.joinArray with the delimiter for their style (',' form,
' ' spaceDelimited, '|' pipeDelimited): hourly=temperature_2m%2Crain.

Also add the missing '/' between name and version in the User-Agent, and
document path parameter encoding.
The CLI documents that generation proceeds even if the spec contains
errors, but the run still failed whenever the reader reported one, such as
an "example" on a Response Object. With --no-validation, any document the
reader produced is now used, and its errors are logged as warnings.
Copilot AI balanced review requested due to automatic review settings October 6, 2026 10:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved documentation-generation, path-safety, model-serialization, enum, nullable-array, and SSE framing defects affect correctness and security.

Review effort: Balanced
Findings: 3 High severity · 6 Medium severity

Open (9)
What changed in this PR

Adds model generation, richer generated documentation, improved parameter serialization, validation bypass behavior, and dependency/runtime upgrades.

Changes:

  • Generates APL models and per-tag API documentation.
  • Adds path encoding and non-exploded array query serialization.
  • Upgrades Scriban, OpenAPI, and bundled HttpCommand.
File Description
src/​OpenAPIDyalog/​Utils/​SchemaTypeMapper.cs Handles nullable schema flags.
src/​OpenAPIDyalog/​Utils/​PathConverter.cs Percent-encodes path parameters.
src/​OpenAPIDyalog/​Templates/​README.md.scriban Simplifies generated README.
src/​OpenAPIDyalog/​Templates/​docs/​tag.md.scriban Adds per-tag documentation template.
src/​OpenAPIDyalog/​Templates/​APLSource/​utils.apln.scriban Adds array query serialization.
src/​OpenAPIDyalog/​Templates/​APLSource/​models/​model.aplc.scriban Expands generated model behavior.
src/​OpenAPIDyalog/​Templates/​APLSource/​HttpCommand.aplc Updates HttpCommand and adds SSE support.
src/​OpenAPIDyalog/​Templates/​APLSource/​_tags/​endpoint.aplf.scriban Handles comments and array query parameters.
src/​OpenAPIDyalog/​Services/​OpenApiService.cs Allows reader errors when validation is disabled.
src/​OpenAPIDyalog/​Services/​ModelGeneratorService.cs Implements model generation.
src/​OpenAPIDyalog/​Services/​CodeGeneratorService.cs Integrates model generation.
src/​OpenAPIDyalog/​Services/​ArtifactGeneratorService.cs Adds tag-document generation.
src/​OpenAPIDyalog/​OpenAPIDyalog.csproj Upgrades dependencies.
src/​OpenAPIDyalog/​Models/​TemplateContext.cs Adds documentation metadata mapping.
src/​OpenAPIDyalog/​Models/​ModelTemplateContext.cs Adds model and enum metadata.
src/​OpenAPIDyalog/​GeneratorApplication.cs Wires services and reports ignored errors.
src/​OpenAPIDyalog/​Constants/​GeneratorConstants.cs Defines the tag template path.
src/​OpenAPIDyalog.Tests/​Utils/​PathConverterTests.cs Updates encoded-path expectations.
src/​OpenAPIDyalog.Tests/​Services/​OpenApiServiceTests.cs Tests validation bypass behavior.
src/​OpenAPIDyalog.Tests/​Services/​EndpointGeneratorServiceTests.cs Tests array query serialization.
src/​OpenAPIDyalog.Tests/​OpenAPIDyalog.Tests.csproj Upgrades Scriban.
install.sh Adds a Linux installer.
docs/​generated-client/​utils.md Documents joinArray.
docs/​generated-client/​operations.md Documents parameter serialization.
docs/​_archive/​usage-guide.md Corrects configuration casing.
docs/​_archive/​examples.md Corrects configuration casing.
dev-docs/​templates.md Updates path-generation examples.
dev-docs/​architecture.md Documents path encoding.
dev-docs/​api-reference.md Updates converter documentation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/OpenAPIDyalog/Services/ArtifactGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Templates/APLSource/HttpCommand.aplc
Comment thread src/OpenAPIDyalog/Templates/README.md.scriban Outdated
Comment thread src/OpenAPIDyalog/Models/TemplateContext.cs Outdated
Comment thread src/OpenAPIDyalog/Services/CodeGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Services/ModelGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Templates/APLSource/models/model.aplc.scriban Outdated
Comment thread src/OpenAPIDyalog/Templates/APLSource/models/model.aplc.scriban Outdated
Comment thread src/OpenAPIDyalog/Templates/docs/tag.md.scriban Outdated
Generated docs:
- Fix the README's API reference, which was wrapped in a Scriban escape
  block and rendered as raw template code, and its empty models list
- Turn per-tag docs/<tag>.md generation back on. Files are named by the
  tag's APL name (its Client field), so a tag cannot escape docs/ and
  tags that share a Client field share a page
- Give each operation an anchor that its link targets, a runnable usage
  example, and parameter, request body and response tables
- Build the docs in DocsBuilder from naming rules shared with endpoint
  generation (OperationNaming), so they document the names the
  generated functions read

Endpoints:
- Read path-item parameters, not only operation parameters
- Read parameters whose names are not valid APL (X-Trace, page[size])
  under their mangled names, and send them under the original ones
- Accept model instances as JSON bodies (they were sent as "")
- Send a JSON body with no model (a string, say) as "body"

Models:
- Fix the required-field check for a model with one required field,
  which always failed
- Treat nullable arrays as arrays
- Leave read-only properties out of FormatNS
- Emit enum constants as typed, escaped literals with distinct names
- Keep numeric arrays flat, and JSON null as null, in FormatNS
- Give map types a niladic constructor and FromResponse
Add a Models page, and update the generated client and contributor docs
for generated docs/<tag>.md pages, model classes, request body naming,
mangled parameter names and the new utils functions.
Copilot AI balanced review requested due to automatic review settings October 6, 2026 11:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/OpenAPIDyalog/Services/CodeGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Templates/APLSource/models/model.aplc.scriban Outdated
Comment thread install.sh
Comment thread src/OpenAPIDyalog/Services/ModelGeneratorService.cs
Comment thread src/OpenAPIDyalog/Utils/DocsBuilder.cs Outdated
Copilot AI balanced review requested due to automatic review settings October 6, 2026 11:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

SSE framing, numeric array encoding, model collisions, documentation naming, and inherited required-field handling remain incorrect.

Review effort: Balanced
Findings: 4 High severity · 4 Medium severity

Open (8)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Honor outer-schema required fields for inherited properties

src/​OpenAPIDyalog/​Services/​ModelGeneratorService.cs:122

Inherited properties are marked required only from the allOf sub-schema passed to AddProperty. A required entry on the outer schema that names an inherited property is valid, but it is ignored here, so the generated constructor accepts a model missing that required field. Compute requiredness from both the outer schema and the declaring sub-schema when flattening.

Medium severity Expand numeric vectors into repeated form pairs

src/​OpenAPIDyalog/​Templates/​APLSource/​utils.apln.scriban:115

Numeric vectors are treated as a single scalar value here because a simple numeric vector has depth 1. For a default form array with explode: true, values such as 1 2 therefore become one ids=1%202 pair instead of ids=1&ids=2. Keep character vectors scalar, but expand simple numeric vectors into repeated pairs.

Comment thread src/OpenAPIDyalog/Services/EndpointGeneratorService.cs
- Number an inline model whose name a component model already takes, and
  document the name it was given
- Warn when component schemas map to the same model class
- Resolve allOf references in inline models
- Treat an inherited property as required if the outer schema says so
- Send a numeric vector query parameter as one pair per item
- Detect macOS in install.sh, and reject unsupported platforms
Copilot AI balanced review requested due to automatic review settings October 6, 2026 11:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Model inheritance, naming collisions, referenced non-object schemas, and SSE chunk framing can produce incorrect generated clients.

Review effort: Balanced
Findings: 6 High severity · 1 Medium severity

Open (7)
Resolved since last review (4)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Recursively flatten allOf schemas in documentation examples

src/​OpenAPIDyalog/​Utils/​DocsBuilder.cs:375

The documentation flattener also stops after one allOf level. For multi-level inheritance, generated usage examples omit inherited fields (including required ones), so the examples no longer describe the generated request shape. Reuse a recursive, cycle-safe schema traversal shared with model generation.

Comment thread src/OpenAPIDyalog/Models/ModelTemplateContext.cs Outdated
Comment thread src/OpenAPIDyalog/Services/ModelGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Utils/OperationNaming.cs Outdated
- Resolve a request body's $ref before classifying it: a reference to an
  array of models is a vector of them, and anything else is sent as given
- Generate model classes only for object schemas
- Flatten allOf to any depth, in models and docs, via SchemaHelpers
- Stop generation when two schema names make the same model class
- Give enum constants distinct names when property names differ only
  in punctuation
Copilot AI balanced review requested due to automatic review settings October 6, 2026 12:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

SSE framing, nullable arrays and enums, required-field validation, free-form objects, and reference chains have unresolved correctness issues.

Review effort: Balanced
Findings: 5 High severity · 2 Medium severity

Open (7)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Handle nullable array flags when determining parameter serialization

src/​OpenAPIDyalog/​Templates/​APLSource/​_tags/​endpoint.aplf.scriban:63

JsonSchemaType is a flags enum. A nullable array has a value such as Array | Null, so this equality fails and an explode: false parameter is sent as repeated query keys instead of one delimited value. Use the same null-stripping array test as OperationNaming.IsType.

Medium severity Allow null values in nullable enum setters

src/​OpenAPIDyalog/​Templates/​APLSource/​models/​model.aplc.scriban:78

Nullable enum schemas can explicitly include JSON null, but null enum entries are discarded before rendering while this setter requires every assigned value to be present in the remaining constants. Assigning ⊂'null' is then rejected even though the schema allows it. Preserve whether the enum contains null and allow that representation in the generated setter.

This issue also appears on line 111 of the same file.

Comment thread src/OpenAPIDyalog/Services/ModelGeneratorService.cs Outdated
Comment thread src/OpenAPIDyalog/Utils/SchemaHelpers.cs Outdated
- Treat an object schema with no properties as a map of arbitrary keys
- Follow $ref chains between components, stopping at a cycle
- Join nullable array query parameters that have explode: false
- Let nullable enums accept null, and skip the JSON null sentinel
- Accept and send a model property that holds one nested model or
  namespace, and recognise it as present when required
Copilot AI balanced review requested due to automatic review settings October 6, 2026 12:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Primitive allOf schemas, model-member collisions, and multiline APL literals can produce incorrect or invalid generated clients.

Review effort: Balanced
Findings: 2 High severity · 2 Low severity

Open (4)
Resolved since last review (7)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Primitive allOf schemas are misclassified as object models

src/​OpenAPIDyalog/​Utils/​SchemaHelpers.cs:37

Treating every schema with allOf as an object misclassifies valid primitive compositions such as { "allOf": [{ "type": "string" }] }. Such a component will get an empty model class, and references to it will be handled as namespaces instead of strings. Determine objectness from the schema or resolved allOf members actually describing objects rather than from allOf being non-empty.

Comment thread src/OpenAPIDyalog/Templates/APLSource/models/model.aplc.scriban Outdated
Comment thread src/OpenAPIDyalog/Utils/StringHelpers.cs Outdated
Comment thread docs/generated-client/operations.md Outdated
Comment thread src/OpenAPIDyalog/Utils/OperationNaming.cs Outdated
- Store model property values in a private namespace, by JSON name, and
  append _ to a property named like a member the class defines
- Write control characters in APL string literals as ⎕UCS codes
- Treat an allOf as an object only if one of its members is
- Correct the docs for free-form inline request bodies
Copilot AI balanced review requested due to automatic review settings October 6, 2026 13:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Endpoint collisions can overwrite generated functions, while optional bodies and hybrid object schemas can serialize incorrectly.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (4)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Omit HTTP body and content type when optional body is absent

src/​OpenAPIDyalog/​Templates/​APLSource/​_tags/​endpoint.aplf.scriban:104

For an optional JSON request body, the absent branch leaves body as the initial empty namespace, while clientArgs still always includes Params: body and the JSON content type. HttpCommand therefore sends {} instead of omitting the body, which is observably different for APIs where no body and an empty object have different meanings. Track whether the argument was supplied and only add Params/ContentType when it is present (while retaining the required-body error).

Medium severity Preserve additional properties in hybrid object schemas

src/​OpenAPIDyalog/​Utils/​SchemaHelpers.cs:71

This only treats property-less objects as maps. An object with declared properties still permits additional properties by default (or may explicitly define additionalProperties), but the regular model template copies only Properties; extra constructor keys are silently discarded by FormatNS. Preserve additional entries alongside the declared fields so hybrid object/map schemas can round-trip valid payloads.

Comment thread src/OpenAPIDyalog/Services/EndpointGeneratorService.cs
- Stop generation when two operations make the same function
- Leave out an optional body that is not given, with no Content-Type
- Keep and send model properties beyond those declared, unless forbidden
- Write numbers in URLs as JSON (-0.12, not ¯0.12) at full precision
- Accept config.headers as pairs, a flat list or a matrix (pairs failed)
- Send operations that accept only unsupported auth (OAuth) as they are,
  so credentials can go in config.headers; fix basic auth lookup
- Make path parameters match the path's {placeholders}
- Fail clearly for a multipart field whose name is not valid APL
- README: base URL from path-level servers, mark a relative one, show
  the first GET as the example, link to dyalog-labs
- Docs: show oneOf/anyOf fields by their first alternative
Copilot AI balanced review requested due to automatic review settings October 6, 2026 13:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Required empty multipart bodies can be omitted, and mixed-type enums can generate colliding constants.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Mixed-type enum values can produce duplicate constants

src/​OpenAPIDyalog/​Services/​ModelGeneratorService.cs:192

The fallback does not guarantee unique constant names for valid mixed-type JSON Schema enums. For example, enum: ["1", 1] initially maps both values to ⍙1, and this fallback maps both raw ApiValue strings to ⍙1 again. The generated enum namespace then has duplicate fields (or loses one value), so the setter cannot accept every declared value. After fallback, detect remaining collisions and disambiguate by JSON type or a stable suffix.

Comment thread src/OpenAPIDyalog/Templates/APLSource/_tags/endpoint.aplf.scriban
- Send a required request body even when none of its fields are given
- Number enum constants whose values are the same text but different
  JSON types ("1" and 1)
Copilot AI balanced review requested due to automatic review settings October 6, 2026 13:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Optional multipart bodies, nullable model references, typed maps, and Windows-reserved generated names have unresolved correctness issues.

Review effort: Balanced
Findings: 3 High severity

Open (3)
Resolved since last review (2)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Resolve nullable references before schema classification

src/​OpenAPIDyalog/​Services/​ModelGeneratorService.cs:205

Nullable model references expressed in OpenAPI 3.1 as anyOf: [$ref, null] are missed here because the outer schema has no reference ID. Such a property is emitted as a plain value, so FormatNS copies a model class instance into the JSON namespace instead of invoking its FormatNS, and ⎕JSON cannot serialize it. Resolve a union's single non-null alternative before classifying references/arrays and nullable state.

Medium severity Check optional multipart body presence before required fields

src/​OpenAPIDyalog/​Templates/​APLSource/​_tags/​endpoint.aplf.scriban:131

An optional multipart body cannot actually be omitted when its schema has required fields. With no form arguments, each required field takes the Else branch below and signals before hasBody is checked, even though requestBody.required is false. Detect whether the optional body is present first; only enforce schema-required form fields after at least one body field is supplied.

Medium severity Recursively format typed map model values

src/​OpenAPIDyalog/​Templates/​APLSource/​models/​model.aplc.scriban:27

Typed map models do not recursively format model values. For additionalProperties: { $ref: ... }, FormatNS returns _data unchanged, leaving any generated model instances inside the namespace; the request formatter explicitly relies on FormatNS because ⎕JSON cannot serialize class instances. Preserve the additional-properties schema in the context and convert model values (including vectors) before returning the map namespace.

Comment thread src/OpenAPIDyalog/Utils/OperationNaming.cs
Comment thread src/OpenAPIDyalog/Utils/OperationNaming.cs
Comment thread src/OpenAPIDyalog/Utils/SchemaHelpers.cs
@Bombardier-C-Kram
Bombardier-C-Kram merged commit 80d090a into main Oct 6, 2026
9 checks passed

This branch was successfully deployed

1 active deployment
github-pages — 80d090a0 Deployed Oct 6, 2026 by Bombardier-C-Kram via deploy #12
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.

2 participants