Skip to content

Commit

Permalink
chore: rollback docs due to sonatype disaster (#581)
Browse files Browse the repository at this point in the history
  • Loading branch information
brizzbuzz authored Mar 6, 2024
1 parent 889fdb4 commit dcde50d
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 129 deletions.
185 changes: 83 additions & 102 deletions docs/concepts/enrichment.md
Original file line number Diff line number Diff line change
@@ -1,125 +1,106 @@
Kompendium enables users to enrich their payloads with additional metadata
such as field description, deprecation, and more.
Kompendium allows users to enrich their data types with additional information. This can be done by defining a
`TypeEnrichment` object and passing it to the `enrichment` parameter of the relevant `requestType` or `responseType`.

Enrichments, unlike annotations, are fully decoupled from the implementation of the class
itself. As such, we can not only enable different metadata on the same class in different
areas of the application, we can also reuse the same metadata in different areas, and even
support enrichment of types that you do not own, or types that are not easily annotated,
such as collections and maps.
```kotlin
data class SimpleData(val a: String, val b: Int? = null)

A simple enrichment example looks like the following:
val myEnrichment = TypeEnrichment<SimpleData>(id = "simple-enrichment") {
SimpleData::a {
description = "This will update the field description"
}
SimpleData::b {
// Will indicate in the UI that the field will be removed soon
deprecated = true
}
}

```kotlin
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType(
enrichment = ObjectEnrichment("simple") {
TestSimpleRequest::a {
StringEnrichment(id = "simple-enrichment") {
description = "A simple description"
}
// In your route documentation
fun Routing.enrichedSimpleRequest() {
route("/example") {
install(NotarizedRoute()) {
parameters = TestModules.defaultParams
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType<SimpleData>(enrichment = myEnrichment) // Simply attach the enrichment to the request
description("A test request")
}
TestSimpleRequest::b {
NumberEnrichment(id = "blah-blah-blah") {
deprecated = true
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
}
}
)
description("A test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
}
}
}
```

For more information on the various enrichment types, please see the following sections.

## Scalar Enrichment
{% hint style="warning" %}
An enrichment must provide an `id` field that is unique to the data class that is being enriched. This is because
under the hood, Kompendium appends this id to the data class identifier in order to support multiple different
enrichments
on the same data class.

Currently, Kompendium supports enrichment of the following scalar types:
If you provide duplicate ids, all but the first enrichment will be ignored, as Kompendium will view that as a cache hit,
and skip analyzing the new enrichment.
{% endhint %}

- Boolean
- String
- Number
### Nested Enrichments

At the moment, all of these types extend a sealed interface `Enrichment`... as such you cannot provide
enrichments for custom scalars like dates and times. This is a known limitation, and will be addressed
in a future release.
Enrichments are portable and composable, meaning that we can take an enrichment for a child data class
and apply it inside a parent data class using the `typeEnrichment` property.

## Object Enrichment

Object enrichment is the most common form of enrichment, and is used to enrich a complex type, and
the fields of a class.

## Collection Enrichment
```kotlin
data class ParentData(val a: String, val b: ChildData)
data class ChildData(val c: String, val d: Int? = null)

Collection enrichment is used to enrich a collection type, and the elements of that collection.
val childEnrichment = TypeEnrichment<ChildData>(id = "child-enrichment") {
ChildData::c {
description = "This will update the field description of field c on child data"
}
ChildData::d {
description = "This will update the field description of field d on child data"
}
}

```kotlin
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType(
enrichment = ObjectEnrichment("simple") {
ComplexRequest::tables {
CollectionEnrichment<NestedComplexItem>("blah-blah") {
description = "A nested description"
itemEnrichment = ObjectEnrichment("nested") {
NestedComplexItem::name {
StringEnrichment("beleheh") {
description = "A nested description"
}
}
}
}
}
}
)
description("A test request")
val parentEnrichment = TypeEnrichment<ParentData>(id = "parent-enrichment") {
ParentData::a {
description = "This will update the field description"
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
ParentData::b {
description = "This will update the field description of field b on parent data"
typeEnrichment = childEnrichment // Will apply the child enrichment to the internals of field b
}
}
```

## Map Enrichment
## Available Enrichments

Map enrichment is used to enrich a map type, and the keys and values of that map.
All enrichments support the following properties:

```kotlin
get = GetInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
response {
responseType<Map<String, TestSimpleRequest>>(
enrichment = MapEnrichment("blah") {
description = "A nested description"
valueEnrichment = ObjectEnrichment("nested") {
TestSimpleRequest::a {
StringEnrichment("blah-blah-blah") {
description = "A simple description"
}
}
TestSimpleRequest::b {
NumberEnrichment("blah-blah-blah") {
deprecated = true
}
}
}
}
)
description("A good response")
responseCode(HttpStatusCode.Created)
}
}
```
- description -> Provides a reader friendly description of the field in the object
- deprecated -> Indicates that the field is deprecated and should not be used

### String

- minLength -> The minimum length of the string
- maxLength -> The maximum length of the string
- pattern -> A regex pattern that the string must match
- contentEncoding -> The encoding of the string
- contentMediaType -> The media type of the string

### Numbers

- minimum -> The minimum value of the number
- maximum -> The maximum value of the number
- exclusiveMinimum -> Indicates that the minimum value is exclusive
- exclusiveMaximum -> Indicates that the maximum value is exclusive
- multipleOf -> Indicates that the number must be a multiple of the provided value

### Arrays

- minItems -> The minimum number of items in the array
- maxItems -> The maximum number of items in the array
- uniqueItems -> Indicates that the array must contain unique items
11 changes: 4 additions & 7 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ you to rip out and replace the amazing code you have already written.
| 1.X | 1 | 3.0 |
| 2.X | 1 | 3.0 |
| 3.X | 2 | 3.1 |
| 4.X | 2 | 3.1 |

> These docs are focused solely on Kompendium 4, previous versions should be considered deprecated and no longer
> These docs are focused solely on Kompendium 3, previous versions should be considered deprecated and no longer
> maintained
# Getting Started
Expand All @@ -37,11 +36,9 @@ custom type overrides (typically useful for custom scalars such as dates and tim
```kotlin
private fun Application.mainModule() {
install(NotarizedApplication()) {
spec = {
OpenApiSpec(
// ...
)
}
spec = OpenApiSpec(
// ...
)
}
}
```
Expand Down
16 changes: 15 additions & 1 deletion docs/playground.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
The Playground is a module inside the Kompendium repository that provides out of the box examples for a variety of
Kompendium features.

You can find all the playground
At the moment, the following playground applications are

| Example | Description |
|--------------|------------------------------------------------------------|
| Basic | A minimally viable Kompendium application |
| Auth | Documenting authenticated routes |
| Custom Types | Documenting custom scalars to be used by Kompendium |
| Exceptions | Documenting exception responses |
| Gson | Serialization using Gson instead of the default Kotlinx |
| Hidden Docs | Place your generated documentation behind authorization |
| Jackson | Serialization using Jackson instead of the default KotlinX |
| Locations | Using the Ktor Locations API to define routes |
| Resources | Using the Ktor Resources API to define routes |

You can find all of the playground
examples [here](https://github.com/bkbnio/kompendium/tree/main/playground/src/main/kotlin/io/bkbn/kompendium/playground)
in the Kompendium repository
51 changes: 34 additions & 17 deletions docs/plugins/notarized_application.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,21 @@ reference [OpenAPI spec](https://spec.openapis.org/oas/v3.1.0) itself.
For public facing APIs, having the default endpoint exposed at `/openapi.json` is totally fine. However, if you need
more granular control over the route that exposes the generated schema, you can modify the `openApiJson` config value.

For example, if we want to hide our schema behind a basic auth check with a custom json encoder, we could do the
following
For example, if we want to hide our schema behind a basic auth check, we could do the following

```kotlin
private fun Application.mainModule() {
// Install content negotiation, auth, etc...
install(NotarizedApplication()) {
// ...
specRoute = { spec, routing ->
routing {
authenticate("basic") {
route("/openapi.json") {
get {
call.response.headers.append("Content-Type", "application/json")
call.respondText { CustomJsonEncoder.encodeToString(spec) }
}
openApiJson = {
authenticate("basic") {
route("/openapi.json") {
get {
call.respond(
HttpStatusCode.OK,
this@route.application.attributes[KompendiumAttributes.openApiSpec]
)
}
}
}
Expand Down Expand Up @@ -75,14 +74,32 @@ This means that we only need to define our custom type once, and then Kompendium
application.

> While intended for custom scalars, there is nothing stopping you from leveraging custom types to circumvent type
> analysis on any class you choose. If you have an alternative method of generating JsonSchema definitions, you could
> put them all in this map and effectively prevent Kompendium from having to do any reflection
> analysis
> on any class you choose. If you have an alternative method of generating JsonSchema definitions, you could put them
> all
> in this map and effectively prevent Kompendium from having to do any reflection
## Schema Configurator

Out of the box, Kompendium supports KotlinX serialization... however, in order to allow for users of other
serialization libraries to use Kompendium, we have provided a `SchemaConfigurator` interface that allows you to
configure how Kompendium will generate schema definitions.
The `SchemaConfigurator` is an interface that allows users to bridge the gap between Kompendium serialization and custom
serialization strategies that the serializer they are using for their API. For example, if you are using KotlinX
serialization in order to convert kotlin fields from camel case to snake case, you could leverage
the `KotlinXSchemaConfigurator` in order to instruct Kompendium on how to serialize values properly.

For an example of the `SchemaConfigurator` in action, please see the `KotlinxSchemaConfigurator`. This will give you
a good idea of the additional functionality it can add based on your own serialization needs.
```kotlin
private fun Application.mainModule() {
install(ContentNegotiation) {
json(Json {
serializersModule = KompendiumSerializersModule.module
encodeDefaults = true
explicitNulls = false
})
}
install(NotarizedApplication()) {
spec = baseSpec
// Adds support for @Transient and @SerialName
// If you are not using them this is not required.
schemaConfigurator = KotlinXSchemaConfigurator()
}
}
```
2 changes: 1 addition & 1 deletion docs/plugins/notarized_locations.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ level plugin, and **must** be install after both the `NotarizedApplication` plug
private fun Application.mainModule() {
install(Locations)
install(NotarizedApplication()) {
spec = { baseSpec }
spec = baseSpec
}
install(NotarizedLocations()) {
locations = mapOf(
Expand Down
2 changes: 1 addition & 1 deletion docs/plugins/notarized_resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ application in a single block.
private fun Application.mainModule() {
install(Resources)
install(NotarizedApplication()) {
spec = { baseSpec }
spec = baseSpec
}
install(NotarizedResources()) {
resources = mapOf(
Expand Down

0 comments on commit dcde50d

Please sign in to comment.