Skip to content

Commit 320557a

Browse files
OpenApi.Transform annotation (#3968)
1 parent 71f7d4e commit 320557a

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

.changeset/chilly-jars-sing.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
"@effect/platform": patch
3+
---
4+
5+
`OpenApi.Transform` annotation has been added
6+
7+
This customization point allows you to transform the generated specification in an arbitrary way
8+
9+
```ts
10+
class Api extends HttpApi.empty
11+
.annotateContext(OpenApi.annotations({
12+
title: "API",
13+
summary: "test api summary",
14+
transform: (openApiSpec) => ({
15+
...openApiSpec,
16+
tags: [...openApiSpec.tags ?? [], {
17+
name: "Tag from OpenApi.Transform annotation"
18+
}]
19+
})
20+
}))
21+
```

packages/platform-node/test/HttpApi.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,16 @@ class Api extends HttpApi.empty
304304
.addHttpApi(AnotherApi)
305305
.add(UsersApi.prefix("/users"))
306306
.addError(GlobalError, { status: 413 })
307-
.annotateContext(OpenApi.annotations({ title: "API", summary: "test api summary" }))
307+
.annotateContext(OpenApi.annotations({
308+
title: "API",
309+
summary: "test api summary",
310+
transform: (openApiSpec) => ({
311+
...openApiSpec,
312+
tags: [...openApiSpec.tags ?? [], {
313+
name: "Tag from OpenApi.Transform annotation"
314+
}]
315+
})
316+
}))
308317
.annotate(
309318
HttpApi.AdditionalSchemas,
310319
[

packages/platform-node/test/fixtures/openapi.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@
422422
},
423423
{
424424
"name": "Users API"
425+
},
426+
{
427+
"name": "Tag from OpenApi.Transform annotation"
425428
}
426429
],
427430
"components": {

packages/platform/src/OpenApi.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ export class Deprecated extends Context.Tag("@effect/platform/OpenApi/Deprecated
8585
*/
8686
export class Override extends Context.Tag("@effect/platform/OpenApi/Override")<Override, Record<string, unknown>>() {}
8787

88+
/**
89+
* Transforms the generated OpenAPI specification
90+
* @since 1.0.0
91+
* @category annotations
92+
*/
93+
export class Transform
94+
extends Context.Tag("@effect/platform/OpenApi/Transform")<Transform, (openApiSpec: OpenAPISpec) => OpenAPISpec>()
95+
{}
96+
8897
const contextPartial = <Tags extends Record<string, Context.Tag<any, any>>>(tags: Tags): (
8998
options: {
9099
readonly [K in keyof Tags]?: Context.Tag.Service<Tags[K]> | undefined
@@ -118,6 +127,10 @@ export const annotations: (
118127
readonly servers?: ReadonlyArray<OpenAPISpecServer> | undefined
119128
readonly format?: string | undefined
120129
readonly override?: Record<string, unknown> | undefined
130+
/**
131+
* Transforms the generated OpenAPI specification
132+
*/
133+
readonly transform?: ((openApiSpec: OpenAPISpec) => OpenAPISpec) | undefined
121134
}
122135
) => Context.Context<never> = contextPartial({
123136
identifier: Identifier,
@@ -129,7 +142,8 @@ export const annotations: (
129142
externalDocs: ExternalDocs,
130143
servers: Servers,
131144
format: Format,
132-
override: Override
145+
override: Override,
146+
transform: Transform
133147
})
134148

135149
const apiCache = globalValue("@effect/platform/OpenApi/apiCache", () => new WeakMap<HttpApi.HttpApi.Any, OpenAPISpec>())
@@ -144,7 +158,7 @@ export const fromApi = <A extends HttpApi.HttpApi.Any>(self: A): OpenAPISpec =>
144158
}
145159
const api = self as unknown as HttpApi.HttpApi.AnyWithProps
146160
const jsonSchemaDefs: Record<string, JsonSchema.JsonSchema> = {}
147-
const spec: DeepMutable<OpenAPISpec> = {
161+
let spec: DeepMutable<OpenAPISpec> = {
148162
openapi: "3.0.3",
149163
info: {
150164
title: Context.getOrElse(api.annotations, Title, () => "Api"),
@@ -359,6 +373,10 @@ export const fromApi = <A extends HttpApi.HttpApi.Any>(self: A): OpenAPISpec =>
359373
}
360374
})
361375

376+
Option.map(Context.getOption(api.annotations, Transform), (transformFn) => {
377+
spec = transformFn(spec)
378+
})
379+
362380
apiCache.set(self, spec)
363381

364382
return spec

0 commit comments

Comments
 (0)