diff --git a/.github/issue-proposals/openapi-32-additional-operations.md b/.github/issue-proposals/openapi-32-additional-operations.md new file mode 100644 index 000000000..f885b7f71 --- /dev/null +++ b/.github/issue-proposals/openapi-32-additional-operations.md @@ -0,0 +1,29 @@ +--- +title: "OpenAPI 3.2: Support additionalOperations for arbitrary HTTP methods" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 introduces an `additionalOperations` key on the Path Item Object for HTTP methods that do not have a dedicated field (e.g. `LINK`, `UNLINK`, `LOCK`). Values are Operation Objects keyed by the method name in its correct capitalisation. + +## Current state + +The generator in `src/typescript-generator/generate.ts` iterates over all top-level keys in each path item, so keys like `get`, `post`, etc. are processed automatically. However, `additionalOperations` is a *nested* object and would not be unwrapped by the current loop; those operations would be silently ignored. + +## Proposed changes + +- Detect the `additionalOperations` key during code generation in `src/typescript-generator/generate.ts` and flatten its entries into the same processing loop as standard methods +- Update the Koa middleware and/or dispatcher to forward requests with custom method names to the matching handler +- Update `src/server/registry.ts` to accept and store handlers for arbitrary method names + +## Acceptance criteria + +- [ ] An operation defined under `additionalOperations` (e.g. `LINK`) in an OpenAPI 3.2 spec generates a corresponding route handler file +- [ ] A request using an arbitrary HTTP method (e.g. `LINK`) is routed to the correct handler and returns the expected response +- [ ] Standard method operations (`get`, `post`, etc.) continue to be generated and routed correctly +- [ ] A test covers code generation for an `additionalOperations` entry +- [ ] A test covers end-to-end routing for a custom HTTP method diff --git a/.github/issue-proposals/openapi-32-components-mediatypes.md b/.github/issue-proposals/openapi-32-components-mediatypes.md new file mode 100644 index 000000000..e649b4cc7 --- /dev/null +++ b/.github/issue-proposals/openapi-32-components-mediatypes.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Verify $ref resolution for components/mediaTypes entries" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 introduces a `mediaTypes` key under `components` to allow reuse of Media Type Objects (similar to how `schemas`, `responses`, `parameters`, and `examples` are reused today). A spec may define a Media Type Object once under `#/components/mediaTypes/...` and reference it via `$ref` from multiple operations. + +## Current state + +`src/typescript-generator/generate.ts` reads `#/paths` and `#/components/securitySchemes`. Other component types are resolved via `$ref` by the bundler. It is likely that `$ref` values pointing to `#/components/mediaTypes/...` are already handled automatically, but this has not been explicitly tested. + +## Proposed changes + +- Add a test that uses a spec with a `$ref` pointing to `#/components/mediaTypes/...` and confirms that the bundler resolves it correctly +- Confirm that code generation and runtime routing work correctly for an operation that references a component media type + +## Acceptance criteria + +- [ ] A spec with `#/components/mediaTypes/...` entries and `$ref` references to them is loaded and bundled without errors +- [ ] Code generation for such a spec produces correct TypeScript output +- [ ] A request to the mock server returns the expected response for an operation that uses a `$ref` media type +- [ ] A regression test covers `$ref` resolution for `components/mediaTypes` entries diff --git a/.github/issue-proposals/openapi-32-datavalue-serializedvalue-examples.md b/.github/issue-proposals/openapi-32-datavalue-serializedvalue-examples.md new file mode 100644 index 000000000..f62ae8655 --- /dev/null +++ b/.github/issue-proposals/openapi-32-datavalue-serializedvalue-examples.md @@ -0,0 +1,34 @@ +--- +title: "OpenAPI 3.2: Prefer dataValue and serializedValue in example responses" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds two new fields to the Example Object: + +- `dataValue` — the example expressed as a structured (parsed) value, analogous to the existing `value` field. +- `serializedValue` — the example as it would appear on the wire, as a string. + +The existing `externalValue` is now explicitly documented as a serialized value. + +## Current state + +Counterfact's random-response logic reads the `value` field from Example Objects when returning example responses. The new `dataValue` and `serializedValue` fields are not recognised. + +## Proposed changes + +- When selecting an example response, prefer `dataValue` over `value` so that structured data is used correctly (update the response-building / example-selection logic, likely in the server dispatcher or response helper) +- Optionally support `serializedValue` for content types where the wire format differs from the parsed form (e.g. `application/x-www-form-urlencoded`) +- Ensure backward compatibility: fall back to `value` when `dataValue` is absent + +## Acceptance criteria + +- [ ] An example with `dataValue` is returned as the response body in preference to `value` +- [ ] An example with only `value` (and no `dataValue`) continues to be returned correctly +- [ ] `serializedValue` is returned verbatim as the response body for appropriate content types +- [ ] Existing behaviour for specs that do not use `dataValue` or `serializedValue` is unchanged +- [ ] A unit test covers each of the three cases: `dataValue` present, `value`-only, and `serializedValue` diff --git a/.github/issue-proposals/openapi-32-deprecated-security-scheme.md b/.github/issue-proposals/openapi-32-deprecated-security-scheme.md new file mode 100644 index 000000000..96221331a --- /dev/null +++ b/.github/issue-proposals/openapi-32-deprecated-security-scheme.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Emit @deprecated JSDoc for operations using deprecated security schemes" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 allows security schemes to be marked `deprecated: true`. When a generated handler uses such a scheme, Counterfact should surface this intent to developers as a TypeScript `@deprecated` JSDoc comment, which causes IDEs to show a strikethrough warning. + +## Current state + +`OperationTypeCoder` in `src/typescript-generator/operation-type-coder.ts` generates handler types for operations but does not inspect the `deprecated` flag on security schemes referenced by an operation. + +## Proposed changes + +- In `OperationTypeCoder`, check whether any security scheme referenced by an operation has `deprecated: true` +- If so, emit a `/** @deprecated The security scheme '' is deprecated. */` JSDoc comment above the generated handler type + +## Acceptance criteria + +- [ ] A generated handler for an operation that references a deprecated security scheme includes a `@deprecated` JSDoc comment +- [ ] The generated TypeScript passes `tsc --noEmit` without errors +- [ ] A handler for an operation that uses only non-deprecated security schemes does not include a `@deprecated` comment +- [ ] A unit test covers both the deprecated and non-deprecated cases diff --git a/.github/issue-proposals/openapi-32-discriminator-default-mapping.md b/.github/issue-proposals/openapi-32-discriminator-default-mapping.md new file mode 100644 index 000000000..c293ad833 --- /dev/null +++ b/.github/issue-proposals/openapi-32-discriminator-default-mapping.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Use discriminator defaultMapping for more accurate union types" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds a `defaultMapping` field to the Discriminator Object. This field specifies which schema to use when `propertyName` is absent or the discriminator value is not found in the `mapping`. It improves the accuracy of polymorphic schema representations. + +## Current state + +`SchemaTypeCoder.writeGroup()` in `src/typescript-generator/schema-type-coder.ts` generates union types based on `allOf`/`anyOf`/`oneOf` but does not inspect the `discriminator.defaultMapping` field. As a result, the default variant of a discriminated union may be missing from the generated TypeScript type. + +## Proposed changes + +- In `SchemaTypeCoder.writeGroup()`, read the `discriminator.defaultMapping` field when present +- Include the default variant schema in the emitted union type so the generated TypeScript accurately represents all possible values + +## Acceptance criteria + +- [ ] A discriminated schema with `defaultMapping` generates a union type that includes the default variant +- [ ] The generated TypeScript for such a schema passes `tsc --noEmit` +- [ ] A discriminated schema without `defaultMapping` continues to generate the same types as before +- [ ] A unit test covers a discriminator with `defaultMapping` and confirms the correct union type is emitted diff --git a/.github/issue-proposals/openapi-32-json-schema-alignment.md b/.github/issue-proposals/openapi-32-json-schema-alignment.md new file mode 100644 index 000000000..04dba188e --- /dev/null +++ b/.github/issue-proposals/openapi-32-json-schema-alignment.md @@ -0,0 +1,30 @@ +--- +title: "OpenAPI 3.2: Verify json-schema-faker alignment with draft-bhutton-json-schema-01" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 updates its embedded JSON Schema reference to [draft-bhutton-json-schema-01](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html) and [draft-bhutton-json-schema-validation-01](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html). The notable additions compared to earlier drafts include a revised `unevaluatedProperties`, `unevaluatedItems`, and `prefixItems`. + +## Current state + +Counterfact uses `json-schema-faker` to generate random values from schemas. The library's supported JSON Schema draft determines which keywords are available when generating mock data. It is unclear whether the current version of `json-schema-faker` supports all keywords in `draft-bhutton-json-schema-01`. + +## Proposed changes + +- Audit which `draft-bhutton-json-schema-01` keywords are used in practice and verify that `json-schema-faker` handles them correctly +- In particular, verify support for `prefixItems`, `unevaluatedItems`, and `unevaluatedProperties` +- If the current version of `json-schema-faker` does not support these keywords, upgrade the library or add workarounds (e.g. stripping unsupported keywords before passing the schema to the faker) +- Add tests using schemas that exercise the new keywords to confirm correct random value generation + +## Acceptance criteria + +- [ ] A schema using `prefixItems` generates random tuple values with correct types for each position +- [ ] A schema using `unevaluatedProperties: false` does not include extra properties in generated values +- [ ] A schema using `unevaluatedItems: false` does not include extra items in generated array values +- [ ] All existing random-generation tests continue to pass +- [ ] If `json-schema-faker` is upgraded, no regressions are introduced in existing mock response generation diff --git a/.github/issue-proposals/openapi-32-oauth2-device-authorization.md b/.github/issue-proposals/openapi-32-oauth2-device-authorization.md new file mode 100644 index 000000000..b12eb97c2 --- /dev/null +++ b/.github/issue-proposals/openapi-32-oauth2-device-authorization.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Support OAuth2 Device Authorization flow in generated handler types" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds a `deviceAuthorization` entry to the OAuth2 Security Scheme Flows Object, with a `deviceAuthorizationUrl` field per [RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628). This flow is commonly used for CLI tools, smart TVs, and other input-constrained devices. + +## Current state + +`OperationTypeCoder` in `src/typescript-generator/operation-type-coder.ts` checks for `type === "http" && scheme === "basic"` to determine the `user` type on the `$` argument. Other flows, including `deviceAuthorization`, are not specially handled. + +## Proposed changes + +- Recognise the `deviceAuthorization` flow in `OperationTypeCoder` +- Generate the correct credential shape (device-flow tokens) on the `$` argument for operations secured by the device authorisation flow + +## Acceptance criteria + +- [ ] An operation secured by an OAuth2 `deviceAuthorization` flow generates a `$` argument with the correct device-flow credential type +- [ ] The generated TypeScript passes `tsc --noEmit` without errors +- [ ] Existing operations secured by other OAuth2 flows or HTTP basic auth continue to generate correct types +- [ ] A unit test covers type generation for an operation using the device authorization flow diff --git a/.github/issue-proposals/openapi-32-oauth2-metadata-url.md b/.github/issue-proposals/openapi-32-oauth2-metadata-url.md new file mode 100644 index 000000000..07cb35ccb --- /dev/null +++ b/.github/issue-proposals/openapi-32-oauth2-metadata-url.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Display oauth2MetadataUrl in the built-in dashboard" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds an `oauth2MetadataUrl` field to the OAuth2 Security Scheme. This field provides the URL of the authorisation server's metadata document per [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414), helping developers configure OAuth2 clients. + +## Current state + +The built-in dashboard (`src/client/`) does not display any metadata about security schemes defined in the spec. + +## Proposed changes + +- In the built-in dashboard templates (`src/client/`), read the `oauth2MetadataUrl` field from each OAuth2 Security Scheme in the spec +- Display this URL in the security section of the dashboard so developers can easily locate the authorisation server's metadata document when configuring OAuth2 clients against the mock server + +## Acceptance criteria + +- [ ] A spec with an OAuth2 security scheme that has `oauth2MetadataUrl` displays the URL in the dashboard +- [ ] The dashboard renders correctly when `oauth2MetadataUrl` is absent (no regression) +- [ ] The displayed URL is a clickable link +- [ ] The change does not affect server behaviour — only the UI rendering diff --git a/.github/issue-proposals/openapi-32-optional-discriminator-propertyname.md b/.github/issue-proposals/openapi-32-optional-discriminator-propertyname.md new file mode 100644 index 000000000..cdc4a54d2 --- /dev/null +++ b/.github/issue-proposals/openapi-32-optional-discriminator-propertyname.md @@ -0,0 +1,26 @@ +--- +title: "OpenAPI 3.2: Handle optional discriminator propertyName gracefully" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +In OpenAPI 3.2, the `discriminator.propertyName` field is now optional. When absent, a `defaultMapping` must be provided instead. Previously, `propertyName` was required, so existing code may assume it is always present. + +## Current state + +`SchemaTypeCoder.writeGroup()` relies on `allOf`/`anyOf`/`oneOf` without inspecting the `discriminator` object; `propertyName` being absent would not cause an error in the generated union type. However, any code that accesses `discriminator.propertyName` without a null-check could throw at runtime during type generation. + +## Proposed changes + +- Add a defensive null-check in `src/typescript-generator/schema-type-coder.ts` wherever `discriminator.propertyName` is accessed, so that its absence does not cause a runtime error during code generation + +## Acceptance criteria + +- [ ] A spec with a discriminator that has no `propertyName` (but has `defaultMapping`) is processed without throwing an error +- [ ] The generated TypeScript for such a spec passes `tsc --noEmit` +- [ ] Existing specs with `propertyName` present continue to generate correct types +- [ ] A unit test covers a discriminator schema with no `propertyName` diff --git a/.github/issue-proposals/openapi-32-optional-response-description.md b/.github/issue-proposals/openapi-32-optional-response-description.md new file mode 100644 index 000000000..b97b9a8ea --- /dev/null +++ b/.github/issue-proposals/openapi-32-optional-response-description.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Handle optional response description gracefully" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +In OpenAPI 3.2, the `description` field on the Response Object is now optional (it was previously required). Counterfact should handle specs that omit `description` on one or more responses without errors or unexpected behaviour. + +## Current state + +The generator does not validate or use `description`. Missing descriptions are unlikely to cause an error in the current code, but this has not been explicitly verified with a test. + +## Proposed changes + +- Confirm in the test suite that an operation with responses that have no `description` is handled gracefully at both code-generation time and at runtime +- Add a regression test using a minimal spec that includes a response with no `description` + +## Acceptance criteria + +- [ ] A spec with a response that has no `description` is processed by the code generator without errors or warnings +- [ ] The generated TypeScript for such a spec passes `tsc --noEmit` +- [ ] A request to the mock server returns the expected status code and body even when the matched response has no `description` +- [ ] Existing specs with `description` present are unaffected diff --git a/.github/issue-proposals/openapi-32-query-http-method.md b/.github/issue-proposals/openapi-32-query-http-method.md new file mode 100644 index 000000000..47458cf88 --- /dev/null +++ b/.github/issue-proposals/openapi-32-query-http-method.md @@ -0,0 +1,31 @@ +--- +title: "OpenAPI 3.2: Add native QUERY HTTP method support" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 formally adds `QUERY` as a first-class HTTP method alongside `GET`, `POST`, `PUT`, `DELETE`, `OPTIONS`, `HEAD`, `PATCH`, and `TRACE`. The [QUERY method](https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html) is safe and idempotent but allows a request body, making it useful for complex search and filter operations. + +## Current state + +`HttpMethods` in `src/server/registry.ts` and `HTTP_METHODS` in `src/migrate/update-route-types.ts` do not include `QUERY`. The Koa layer, dispatcher, and migration helper would all need updating. + +## Proposed changes + +- Add `"query"` to `HttpMethods` in `src/server/registry.ts` +- Add `"QUERY"` to `ALL_HTTP_METHODS` (or equivalent) in `src/migrate/update-route-types.ts` +- Ensure the Koa middleware forwards `QUERY` requests to the matching handler +- Ensure the dispatcher routes `QUERY` requests correctly +- The code generator already iterates over all keys in a path definition, so generation should work automatically once the server recognises the method + +## Acceptance criteria + +- [ ] A `query` operation defined in an OpenAPI 3.2 spec generates a corresponding route handler file +- [ ] A `QUERY` HTTP request is routed to the correct handler and returns the expected response +- [ ] The migration helper recognises `QUERY` when updating existing route files +- [ ] Existing routes using other HTTP methods are unaffected +- [ ] Unit tests cover the new `QUERY` method in the registry, dispatcher, and migration helper diff --git a/.github/issue-proposals/openapi-32-querystring-parameter.md b/.github/issue-proposals/openapi-32-querystring-parameter.md new file mode 100644 index 000000000..6d5f9f6e7 --- /dev/null +++ b/.github/issue-proposals/openapi-32-querystring-parameter.md @@ -0,0 +1,29 @@ +--- +title: "OpenAPI 3.2: Support querystring parameter location" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds `querystring` as a new value for the `in` field of a Parameter Object. Unlike the existing `query` (which targets a single named query parameter), `querystring` treats the entire query string as a single field and allows it to be parsed with a schema, similar to how `requestBody` works for request bodies. This simplifies complex query-string APIs such as OData or OpenSearch. + +## Current state + +`src/typescript-generator/parameters-type-coder.ts` generates typed objects for `query`, `path`, `header`, and `cookie` parameters. A `querystring` parameter would currently be silently ignored, and the dispatcher's parameter-extraction logic does not handle it. + +## Proposed changes + +- Handle `in: querystring` in `ParametersTypeCoder` (`src/typescript-generator/parameters-type-coder.ts`) to generate a typed `querystring` property on the `$` argument +- Update the dispatcher's parameter-extraction logic (`src/server/dispatcher.ts`) to parse the raw query string against the schema and populate `$.querystring` +- Ensure the generated TypeScript type for `$.querystring` reflects the schema defined in the parameter object + +## Acceptance criteria + +- [ ] A parameter with `in: querystring` generates a `querystring` property on the typed `$` argument +- [ ] The generated TypeScript passes `tsc --noEmit` without errors +- [ ] At runtime, `$.querystring` contains the parsed query string matching the defined schema +- [ ] Existing `query`, `path`, `header`, and `cookie` parameters are unaffected +- [ ] Unit tests cover type generation and runtime extraction for `querystring` parameters diff --git a/.github/issue-proposals/openapi-32-response-summary-ui.md b/.github/issue-proposals/openapi-32-response-summary-ui.md new file mode 100644 index 000000000..7e86c7540 --- /dev/null +++ b/.github/issue-proposals/openapi-32-response-summary-ui.md @@ -0,0 +1,28 @@ +--- +title: "OpenAPI 3.2: Surface response summary in the API testing UI" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds a `summary` field to the Response Object alongside the existing `description`. This short label can be surfaced in API tooling to help developers quickly identify available response codes. + +## Current state + +The built-in API-testing GUI (`src/client/api-tester.html.hbs`) lists available response codes but does not display any summary or description text. + +## Proposed changes + +- In `src/client/api-tester.html.hbs`, read the `summary` field from each Response Object in the spec +- Display `summary` as a tooltip or inline label next to each response code when it is present +- Fall back gracefully when `summary` is absent + +## Acceptance criteria + +- [ ] A response code with a `summary` field shows the summary text as a tooltip or label in the API testing UI +- [ ] A response code without `summary` displays without error (no regression) +- [ ] The UI remains usable and readable when multiple response codes are listed +- [ ] The change does not affect server behaviour — only the UI rendering diff --git a/.github/issue-proposals/openapi-32-self-document-identity.md b/.github/issue-proposals/openapi-32-self-document-identity.md new file mode 100644 index 000000000..6cb8a2927 --- /dev/null +++ b/.github/issue-proposals/openapi-32-self-document-identity.md @@ -0,0 +1,27 @@ +--- +title: "OpenAPI 3.2: Verify correct $ref resolution with $self document identity" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 introduces a top-level `$self` field that allows an OpenAPI document to declare its own canonical URI. This URI is used as the base when resolving relative `$ref` values, which is especially important for multi-file specs. + +## Current state + +Counterfact uses `@apidevtools/json-schema-ref-parser` for bundling, which already handles base-URI resolution. The `$self` field is likely passed through without issue, but this has not been explicitly verified. + +## Proposed changes + +- Confirm that the spec loader in `src/typescript-generator/specification.ts` and `src/server/openapi-middleware.ts` does not strip or misinterpret `$self` when bundling +- Add a regression test with a spec that declares `$self` and uses relative `$ref` values to verify that references resolve to the correct schemas + +## Acceptance criteria + +- [ ] A spec that declares `$self` is loaded and bundled without errors +- [ ] Relative `$ref` values in a spec with `$self` resolve correctly to the intended schemas +- [ ] Code generation for such a spec produces correct TypeScript output +- [ ] A regression test covers `$ref` resolution in a spec that uses `$self` diff --git a/.github/issue-proposals/openapi-32-server-name-field.md b/.github/issue-proposals/openapi-32-server-name-field.md new file mode 100644 index 000000000..cb9b28627 --- /dev/null +++ b/.github/issue-proposals/openapi-32-server-name-field.md @@ -0,0 +1,26 @@ +--- +title: "OpenAPI 3.2: Set name field on injected Counterfact server entry" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds a `name` field to the Server Object alongside the existing `description`, `url`, and `variables` fields. Tools that display server lists (including OpenAPI 3.2-aware UIs like Swagger UI) may use `name` as the primary label for a server entry. + +## Current state + +`src/server/openapi-middleware.ts` injects a `Counterfact` server entry into the spec with only `description` and `url` fields. The `name` field is not set. + +## Proposed changes + +- Set `name: "Counterfact"` in the injected server entry in `src/server/openapi-middleware.ts` + +## Acceptance criteria + +- [ ] The injected server entry in the served OpenAPI spec includes `name: "Counterfact"` +- [ ] The `description` and `url` fields on the injected entry are unchanged +- [ ] Tools that display the server list (e.g. the built-in Swagger UI) show "Counterfact" as the server name +- [ ] A unit or integration test confirms that the injected server object includes the `name` field diff --git a/.github/issue-proposals/openapi-32-streaming-sse-itemschema.md b/.github/issue-proposals/openapi-32-streaming-sse-itemschema.md new file mode 100644 index 000000000..491dd298b --- /dev/null +++ b/.github/issue-proposals/openapi-32-streaming-sse-itemschema.md @@ -0,0 +1,31 @@ +--- +title: "OpenAPI 3.2: Support streaming responses and SSE via itemSchema" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 introduces first-class support for streaming responses via sequential media types such as `text/event-stream` (Server-Sent Events), `multipart/mixed`, `application/jsonl`, and `application/json-seq`. A new `itemSchema` field in the Media Type Object describes the schema of each individual item in the stream; responses are conceptually treated as arrays of schema instances. + +## Current state + +Counterfact generates typed response builders and can return example data from the spec, but has no concept of streaming or server-sent events. The `text/event-stream` content type is not specially handled in `src/typescript-generator/response-type-coder.ts`, `src/typescript-generator/schema-type-coder.ts`, or the Koa layer. + +## Proposed changes + +- Recognise `itemSchema` in `src/typescript-generator/schema-type-coder.ts` and `src/typescript-generator/response-type-coder.ts` and generate `Array` (or `AsyncIterable`) types for it +- In the server layer (`src/server/koa-middleware.ts`), when a request accepts `text/event-stream`, send an SSE-formatted response using Node.js streams instead of a one-shot JSON body +- Expose a helper on the `$` argument (similar to `$.proxy`) that allows route handlers to push events to a stream +- Handle `application/jsonl` and `application/json-seq` sequential media types in a similar fashion + +## Acceptance criteria + +- [ ] A response with `itemSchema` and content type `text/event-stream` generates an `AsyncIterable` (or equivalent) handler type +- [ ] A route handler returning an async iterable via the SSE helper sends properly formatted `data: ...` SSE events to the client +- [ ] A route handler for `application/jsonl` sends newline-delimited JSON chunks +- [ ] Existing non-streaming routes are unaffected +- [ ] The generated TypeScript for a streaming route passes `tsc --noEmit` without errors +- [ ] Unit and/or integration tests cover SSE response generation diff --git a/.github/issue-proposals/openapi-32-tag-enhancements.md b/.github/issue-proposals/openapi-32-tag-enhancements.md new file mode 100644 index 000000000..cb4eba3ab --- /dev/null +++ b/.github/issue-proposals/openapi-32-tag-enhancements.md @@ -0,0 +1,33 @@ +--- +title: "OpenAPI 3.2: Support tag summary, parent, and kind fields in the dashboard" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds three new fields to the Tag Object: + +- `summary` — a short title for the tag, used in lists. +- `parent` — points to a parent tag to support nested grouping. +- `kind` — classifies the tag (e.g. `nav`, `audience`) per the [public registry](https://spec.openapis.org/registry/tag-kind/index.html). + +## Current state + +Counterfact does not currently process or display tag metadata beyond the tag name. The built-in dashboard and API-testing GUI (`src/client/`) list operations without hierarchical grouping. + +## Proposed changes + +- Update the built-in dashboard / API-testing GUI (`src/client/` Handlebars/Vue templates) to read `summary`, `parent`, and `kind` from each Tag Object in the spec +- Render a hierarchical navigation tree that groups operations by nested tags using the `parent` field +- Use `summary` as the display label for a tag when available, falling back to `name` +- Optionally filter or badge tags by `kind` (e.g. show only `nav` tags in the sidebar) + +## Acceptance criteria + +- [ ] An API with nested tags (using `parent`) renders a hierarchical navigation tree in the dashboard +- [ ] `summary` is shown as the tag label when present; `name` is used as the fallback +- [ ] Tags without `parent`, `summary`, or `kind` display correctly (no regression) +- [ ] A large API with many nested tags remains navigable and readable in the dashboard diff --git a/.github/issue-proposals/openapi-32-xml-nodetype.md b/.github/issue-proposals/openapi-32-xml-nodetype.md new file mode 100644 index 000000000..eecad7ca3 --- /dev/null +++ b/.github/issue-proposals/openapi-32-xml-nodetype.md @@ -0,0 +1,31 @@ +--- +title: "OpenAPI 3.2: Support XML nodeType field in JSON-to-XML serialisation" +parentIssue: 1673 +labels: + - enhancement + - openapi-3.2 +assignees: [] +milestone: +--- + +OpenAPI 3.2 adds a `nodeType` field to the XML Object. This field maps a schema to a specific XML node type: `element`, `attribute`, `text`, `cdata`, or `none`. The existing `attribute: true` is deprecated in favour of `nodeType: attribute`, and `wrapped: true` is deprecated in favour of `nodeType: element`. + +## Current state + +`src/server/json-to-xml.ts` handles XML serialisation based on the XML Object, but it is unclear how fully the existing `attribute` and `wrapped` flags are supported. The new `nodeType` field is not recognised. + +## Proposed changes + +- Update `json-to-xml.ts` to understand the `nodeType` field and map each value (`element`, `attribute`, `text`, `cdata`, `none`) to the correct XML serialisation behaviour +- Treat the deprecated `attribute: true` as a synonym for `nodeType: attribute` during the transition period +- Treat the deprecated `wrapped: true` as a synonym for `nodeType: element` during the transition period + +## Acceptance criteria + +- [ ] A schema with `xml.nodeType: attribute` serialises its value as an XML attribute +- [ ] A schema with `xml.nodeType: text` serialises its value as an XML text node +- [ ] A schema with `xml.nodeType: cdata` serialises its value as a CDATA section +- [ ] A schema with `xml.nodeType: none` is omitted from the XML output +- [ ] The deprecated `xml.attribute: true` continues to produce the same output as `xml.nodeType: attribute` +- [ ] The deprecated `xml.wrapped: true` continues to produce the same output as `xml.nodeType: element` +- [ ] Existing XML serialisation for schemas without `nodeType` is unaffected