Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add additionalPropertiesStrategy option to OpenApi.fromApi, close… #4540

Merged
merged 1 commit into from
Mar 5, 2025

Conversation

gcanti
Copy link
Contributor

@gcanti gcanti commented Mar 1, 2025

…s #4531

This update introduces the additionalPropertiesStrategy option in OpenApi.fromApi, allowing control over how additional properties are handled in the generated OpenAPI schema.

  • When "strict" (default), additional properties are disallowed ("additionalProperties": false).
  • When "allow", additional properties are allowed ("additionalProperties": true), making APIs more flexible.

The additionalPropertiesStrategy option has also been added to:

  • JSONSchema.fromAST
  • OpenApiJsonSchema.makeWithDefs

Example

import {
  HttpApi,
  HttpApiEndpoint,
  HttpApiGroup,
  OpenApi
} from "@effect/platform"
import { Schema } from "effect"

const api = HttpApi.make("api").add(
  HttpApiGroup.make("group").add(
    HttpApiEndpoint.get("get", "/").addSuccess(
      Schema.Struct({ a: Schema.String })
    )
  )
)

const schema = OpenApi.fromApi(api, {
  additionalPropertiesStrategy: "allow"
})

console.log(JSON.stringify(schema, null, 2))
/*
{
  "openapi": "3.1.0",
  "info": {
    "title": "Api",
    "version": "0.0.1"
  },
  "paths": {
    "/": {
      "get": {
        "tags": [
          "group"
        ],
        "operationId": "group.get",
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "a"
                  ],
                  "properties": {
                    "a": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the expected schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpApiDecodeError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HttpApiDecodeError": {
        "type": "object",
        "required": [
          "issues",
          "message",
          "_tag"
        ],
        "properties": {
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            }
          },
          "message": {
            "type": "string"
          },
          "_tag": {
            "type": "string",
            "enum": [
              "HttpApiDecodeError"
            ]
          }
        },
        "additionalProperties": true,
        "description": "The request did not match the expected schema"
      },
      "Issue": {
        "type": "object",
        "required": [
          "_tag",
          "path",
          "message"
        ],
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "Pointer",
              "Unexpected",
              "Missing",
              "Composite",
              "Refinement",
              "Transformation",
              "Type",
              "Forbidden"
            ],
            "description": "The tag identifying the type of parse issue"
          },
          "path": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PropertyKey"
            },
            "description": "The path to the property where the issue occurred"
          },
          "message": {
            "type": "string",
            "description": "A descriptive message explaining the issue"
          }
        },
        "additionalProperties": true,
        "description": "Represents an error encountered while parsing a value to match the schema"
      },
      "PropertyKey": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "number"
          },
          {
            "type": "object",
            "required": [
              "_tag",
              "key"
            ],
            "properties": {
              "_tag": {
                "type": "string",
                "enum": [
                  "symbol"
                ]
              },
              "key": {
                "type": "string"
              }
            },
            "additionalProperties": true,
            "description": "an object to be decoded into a globally shared symbol"
          }
        ]
      }
    },
    "securitySchemes": {}
  },
  "security": [],
  "tags": [
    {
      "name": "group"
    }
  ]
}
*/

@gcanti gcanti added the schema label Mar 1, 2025
@gcanti gcanti requested a review from tim-smart as a code owner March 1, 2025 09:57
Copy link

changeset-bot bot commented Mar 1, 2025

🦋 Changeset detected

Latest commit: 8b13035

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 36 packages
Name Type
@effect/platform Patch
effect Patch
@effect/cli Patch
@effect/cluster-node Patch
@effect/cluster-workflow Patch
@effect/cluster Patch
@effect/experimental Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/rpc-http Patch
@effect/rpc Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-node Patch
@effect/sql Patch
@effect/ai Patch
@effect/ai-anthropic Patch
@effect/ai-openai Patch
@effect/cluster-browser Patch
@effect/opentelemetry Patch
@effect/printer-ansi Patch
@effect/printer Patch
@effect/sql-drizzle Patch
@effect/sql-kysely Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/typeclass Patch
@effect/vitest Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gcanti gcanti merged commit 840cc73 into main Mar 5, 2025
11 checks passed
@gcanti gcanti deleted the fix-4531 branch March 5, 2025 16:06
@github-actions github-actions bot mentioned this pull request Mar 5, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

From Discord: Issue with additionalProperties: false in OpenAPI Schema Generation
1 participant