Skip to content

Commit

Permalink
Platform: add OpenAPI.fromApi tests + docs refactoring (#4226)
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Jan 11, 2025
1 parent 734af82 commit 212e784
Show file tree
Hide file tree
Showing 10 changed files with 3,928 additions and 337 deletions.
126 changes: 126 additions & 0 deletions .changeset/happy-birds-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
"@effect/platform": patch
---

Ensure the encoding kind of success responses is respected in the OpenAPI spec for GET requests.

Before

When generating an OpenAPI spec for a GET request with a success schema of type `HttpApiSchema.Text()``, the response content type was incorrectly set to "application/json" instead of "text/plain".

```ts
import {
HttpApi,
HttpApiEndpoint,
HttpApiGroup,
HttpApiSchema,
OpenApi
} from "@effect/platform"

const api = HttpApi.make("api").add(
HttpApiGroup.make("group").add(
HttpApiEndpoint.get("get", "/").addSuccess(HttpApiSchema.Text())
)
)

const spec = OpenApi.fromApi(api)

console.log(JSON.stringify(spec.paths, null, 2))
/*
Output:
{
"/": {
"get": {
"tags": [
"group"
],
"operationId": "group.get",
"parameters": [],
"security": [],
"responses": {
"200": {
"description": "a string",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "The request did not match the expected schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HttpApiDecodeError"
}
}
}
}
}
}
}
}
*/
```

After

```diff
import {
HttpApi,
HttpApiEndpoint,
HttpApiGroup,
HttpApiSchema,
OpenApi
} from "@effect/platform"

const api = HttpApi.make("api").add(
HttpApiGroup.make("group").add(
HttpApiEndpoint.get("get", "/").addSuccess(HttpApiSchema.Text())
)
)

const spec = OpenApi.fromApi(api)

console.log(JSON.stringify(spec.paths, null, 2))
/*
Output:
{
"/": {
"get": {
"tags": [
"group"
],
"operationId": "group.get",
"parameters": [],
"security": [],
"responses": {
"200": {
"description": "a string",
"content": {
- "application/json": {
+ "text/plain": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "The request did not match the expected schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HttpApiDecodeError"
}
}
}
}
}
}
}
}
*/
```
5 changes: 5 additions & 0 deletions .changeset/odd-readers-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": patch
---

Add missing `deprecated` key to `OpenApi.annotations` API.
174 changes: 174 additions & 0 deletions .changeset/old-humans-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
"@effect/platform": patch
---

Fix: Prevent request body from being added to the OpenAPI spec for GET methods in `OpenApi.fromApi`.

When creating a `GET` endpoint with a request payload, the `requestBody` was incorrectly added to the OpenAPI specification, which is invalid for `GET` methods.

Before

```ts
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.String)
.setPayload(
Schema.Struct({
a: Schema.String
})
)
)
)

const spec = OpenApi.fromApi(api)

console.log(JSON.stringify(spec.paths, null, 2))
/*
Output:
{
"/": {
"get": {
"tags": [
"group"
],
"operationId": "group.get",
"parameters": [
{
"name": "a",
"in": "query",
"schema": {
"type": "string"
},
"required": true
}
],
"security": [],
"responses": {
"200": {
"description": "a string",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "The request did not match the expected schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HttpApiDecodeError"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "string"
}
},
"additionalProperties": false
}
}
},
"required": true
}
}
}
}
*/
```

After

```ts
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.String)
.setPayload(
Schema.Struct({
a: Schema.String
})
)
)
)

const spec = OpenApi.fromApi(api)

console.log(JSON.stringify(spec.paths, null, 2))
/*
Output:
{
"/": {
"get": {
"tags": [
"group"
],
"operationId": "group.get",
"parameters": [
{
"name": "a",
"in": "query",
"schema": {
"type": "string"
},
"required": true
}
],
"security": [],
"responses": {
"200": {
"description": "a string",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "The request did not match the expected schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HttpApiDecodeError"
}
}
}
}
}
}
}
}
*/
```
90 changes: 90 additions & 0 deletions .changeset/seven-shirts-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
"@effect/platform": patch
---

Add `"application/x-www-form-urlencoded"` to `OpenApiSpecContentType` type as it is generated by the system when using `HttpApiSchema.withEncoding({ kind: "UrlParams" })`

**Example**

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

const api = HttpApi.make("api").add(
HttpApiGroup.make("group").add(
HttpApiEndpoint.post("post", "/")
.addSuccess(Schema.String)
.setPayload(
Schema.Struct({ foo: Schema.String }).pipe(
HttpApiSchema.withEncoding({ kind: "UrlParams" })
)
)
)
)

const spec = OpenApi.fromApi(api)

console.log(JSON.stringify(spec.paths, null, 2))
/*
Output:
{
"/": {
"post": {
"tags": [
"group"
],
"operationId": "group.post",
"parameters": [],
"security": [],
"responses": {
"200": {
"description": "a string",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "The request did not match the expected schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HttpApiDecodeError"
}
}
}
}
},
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"required": [
"foo"
],
"properties": {
"foo": {
"type": "string"
}
},
"additionalProperties": false
}
}
},
"required": true
}
}
}
}
*/
```
Loading

0 comments on commit 212e784

Please sign in to comment.