Compare commits

..

136 Commits

Author SHA1 Message Date
bf6d08c2bd chore: prep for 3.14.4 release 2023-06-05 16:13:54 -04:00
68bae4918e fix: References for for protobuf objects (#466) 2023-06-05 16:12:31 -04:00
592c116c3b fix(deps): update dependency io.ktor:ktor-server-core to v2.3.1 (#474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 10:46:44 +00:00
c7fe5c288f fix(deps): update ktor to v2.3.1 (#473)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-31 08:54:22 -04:00
e059633055 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.2 (#472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-26 20:27:33 +00:00
884a50fc83 chore: prep for 3.14.3 release 2023-05-22 09:39:54 -04:00
588e52c9df fix: allow for request bodies to be marked as required=false (#470) 2023-05-22 09:39:04 -04:00
f49fcb2a22 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.1 (#469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-17 23:39:18 +00:00
0a9475a7ab fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.5.1 (#463)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-11 21:54:50 +00:00
f8fbb7ad25 fix(deps): update kotestversion to v5.6.2 (#462)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-11 02:53:10 +00:00
f792fb5d1f fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.0 (#461)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 11:08:22 +00:00
845d1a971d fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.8.21 (#460)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 06:19:56 +00:00
9396b2ecfe chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.8.21 (#459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 03:36:01 +00:00
d74b7b3f28 chore(deps): update plugin org.jetbrains.kotlin.jvm to v1.8.21 (#458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 03:31:13 +00:00
e783630845 chore(deps): update dependency gradle to v8.1.1 (#457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-09 23:17:06 +00:00
d907ba004a chore: prep for 3.14.2 release 2023-05-08 11:50:45 -04:00
5c7ec4fdb4 fix: route with parameter declared via ktor function (#455) 2023-05-08 11:49:29 -04:00
097413067b chore: prep for 3.14.1 release 2023-04-28 10:59:27 -04:00
eb7360b8d2 fix: fixed generic property enrichment (#454) 2023-04-28 10:58:20 -04:00
3ec467c1d8 fix(deps): update ktor to v2.3.0 (#452)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-22 18:14:04 +00:00
152476c26e fix(deps): update dependency io.kotest:kotest-assertions-json-jvm to v5.6.1 (#451)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-18 21:15:51 +00:00
c4df4c7b2c fix(deps): update dependency io.kotest:kotest-runner-junit5-jvm to v5.6.0 (#450)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-17 05:49:54 +00:00
87fa0b5602 chore(deps): update dependency gradle to v8.1 (#449)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-15 17:00:27 +00:00
53c76d6037 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.22.3 (#448)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-13 08:56:13 +00:00
44324ca3a4 chore: rearrange docs (#447) 2023-04-10 19:00:26 +00:00
9364fb19e4 chore: prep for 3.14.0 release 2023-04-06 15:49:07 -04:00
ca1f632665 feat: Introduce Support for Response Headers (#446) 2023-04-06 19:47:48 +00:00
9bb3184735 docs: add showcase link to readme 2023-04-03 19:44:42 -04:00
9a139b5713 chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.8.20 (#440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 10:54:36 -04:00
9861c8e258 chore(deps): update plugin org.jetbrains.kotlin.jvm to v1.8.20 (#439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 13:10:37 +00:00
02f8ed04f2 fix(deps): update dependency dev.forst:ktor-api-key to v2.2.4 (#442)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-03 12:54:06 +00:00
3e23939386 fix(deps): update dependency joda-time:joda-time to v2.12.5 (#441)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 00:21:18 +00:00
d0575944db fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.8.20 (#438)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-30 11:17:39 +00:00
ccc81c2813 fix(deps): update dependency joda-time:joda-time to v2.12.4 (#436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-24 10:20:45 +00:00
e8da52fd75 fix(deps): update dependency joda-time:joda-time to v2.12.3 (#435)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-23 12:49:37 +00:00
34c14e26da fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.7 (#434)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-18 01:17:47 +00:00
209b5e38a3 fix(deps): update dependency org.slf4j:slf4j-api to v2.0.7 (#433)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-17 23:50:21 +00:00
902faa9471 fix(deps): update dependency io.gitlab.arturbosch.detekt:detekt-formatting to v1.22.0 (#388) 2023-03-16 12:53:15 +00:00
c7ef70a844 fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.5.0 (#432)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 12:25:44 +00:00
f83c3d203d fix(deps): update ktor to v2.2.4 (#430)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 10:38:18 +00:00
bd05dbcfcb chore(deps): update plugin io.github.gradle-nexus.publish-plugin to v1.3.0 (#431)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 08:48:23 +00:00
cb5c0e71a3 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.22.2 (#429)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 08:45:44 +00:00
a209cafa74 chore(deps): update dependency gradle to v7.6.1 (#428)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 07:27:45 +00:00
3d27d30a31 feat: support no request body for post, put and patch (#427) 2023-03-15 12:39:35 +00:00
8cc229667e chore: prep for 3.12.0 release 2023-03-14 16:52:16 -04:00
54d12de67a feat: reintroduce swagger compatability (#426) 2023-03-14 20:43:06 +00:00
9b93c887a2 chore(deps): update plugin io.github.gradle-nexus.publish-plugin to v1.2.0 (#424)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-22 06:04:16 +00:00
19d828956b fix(deps): update dependency org.apache.logging.log4j:log4j-core to v2.20.0 (#423)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-21 18:05:45 +00:00
eabe90acfc fix(deps): update dependency org.apache.logging.log4j:log4j-api to v2.20.0 (#422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-21 17:58:41 +00:00
7c2a2a9c9d fix(deps): update dependency com.google.protobuf:protobuf-java to v3.22.0 (#421)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-17 05:27:43 +00:00
15cdfb229d fix(deps): update kotestversion to v5.5.5 (#420)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-05 21:56:57 +00:00
5a40f37f81 fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.8.10 (#418)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-03 05:51:57 +00:00
64f2516f19 chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.8.10 (#416)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-03 00:22:16 +00:00
2e5e39d3b2 chore(deps): update plugin org.jetbrains.kotlin.jvm to v1.8.10 (#415)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-02 19:52:53 +00:00
5342cf00d1 fix(deps): update ktor to v2.2.3 (#414)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-01 04:08:51 +00:00
8c0b658033 fix: drop logback (#413) 2023-01-31 08:37:57 -05:00
b7b1171685 fix(deps): update dependency dev.forst:ktor-api-key to v2.2.2 (#410)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-17 17:26:25 +00:00
1f730869a8 chore: fix incorrect line in documentation 2023-01-07 17:16:05 -05:00
377a60614e feat: constraints (#409) 2023-01-05 14:44:24 +00:00
e34bea1769 fix(deps): update ktor (#397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-04 21:49:06 -05:00
91bf93a866 feat: type enrichment (#408) 2023-01-04 21:32:31 -05:00
73fb8b137f fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.8.0 (#405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-28 22:11:08 +00:00
d3d6e79329 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.21.12 (#402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-15 10:02:49 +00:00
f2b7d924e0 fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.6 (#401)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-13 10:38:53 +00:00
f62010b4e7 fix(deps): update dependency org.slf4j:slf4j-api to v2.0.6 (#400)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-13 07:39:57 +00:00
5bd1534270 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.21.11 (#398)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-08 22:19:05 +00:00
4c151ffeea fix(deps): update dependency joda-time:joda-time to v2.12.2 (#396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 18:21:42 +00:00
08a0d2e47c fix(deps): update dependency com.google.protobuf:protobuf-java to v3.21.10 (#395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 09:58:10 +00:00
f19476d3a3 chore: bump gradle version 2022-11-30 12:48:46 -05:00
8ede53fd5c fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.7.22 (#394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-28 21:50:54 +00:00
31a9f44ec1 chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.7.22 (#393)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-28 15:31:11 +00:00
0eb2f126b3 chore(deps): update plugin org.jetbrains.kotlin.jvm to v1.7.22 (#392)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-28 15:24:18 +00:00
0d658bd6a8 fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.5 (#390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-25 19:01:28 +00:00
e924671c2b fix(deps): update dependency org.slf4j:slf4j-api to v2.0.5 (#389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-25 18:54:39 +00:00
04996631b9 fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.5 (#387)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-19 06:38:07 +00:00
82d80873c8 fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.4 (#386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-18 09:50:16 +00:00
487eaba741 fix(deps): update dependency org.slf4j:slf4j-api to v2.0.4 (#385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-18 06:42:30 +00:00
b935cc1e1d chore: prep for 3.9.0 release 2022-11-15 20:49:58 -05:00
9f2d2dd4e3 fix: do not include rootPath in serialized route path 2022-11-16 01:46:29 +00:00
20f8a4f08f feat: protobuf java converters (#382) 2022-11-15 15:50:26 -05:00
7b39e448bf chore: prep for 3.8.0 release 2022-11-09 08:13:42 -05:00
3c57c8f5e4 feat: NotarizedResource plugin 2022-11-09 08:11:42 -05:00
01b6b59cf5 feat: support partial authentication (#372) (#375) 2022-11-08 19:59:35 +00:00
2c1c8fbcdc chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.7.21 (#377)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ryan Brink <5607577+unredundant@users.noreply.github.com>
2022-11-08 14:56:33 -05:00
0dc2b9538f chore: delete autoupdate action
this thing sucks meant to delete it a while ago
2022-11-08 14:42:30 -05:00
1ca7abaf0d fix(deps): update kotlin monorepo to v1.7.21 (#374)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-08 18:59:49 +00:00
a5376cfa82 feat: allow media type overrides (#369) 2022-11-05 16:45:06 -04:00
2492661f1f chore: prep for release 2022-11-05 16:11:38 -04:00
a7b52ec114 feat: create schema reference for enum types (#368) 2022-11-05 16:09:06 -04:00
8ebab04a83 fix(deps): update kotestversion to v5.5.4 (#363)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-04 06:00:41 +00:00
921f6f9691 fix(deps): update dependency dev.forst:ktor-api-key to v2.1.3 (#361)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-31 22:25:14 +00:00
558b9fea62 fix(deps): update ktor to v2.1.3 (#360)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-31 17:01:30 +00:00
752cb238d3 fix(deps): update dependency joda-time:joda-time to v2.12.1 (#359)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-30 06:12:11 +00:00
92d4760dbc chore: prep for 3.5.0 release 2022-10-29 08:16:03 -04:00
4946a27327 feat: add plugin to support ktor-server-resources (#358) 2022-10-29 08:14:32 -04:00
e4217843b7 fix(deps): update dependency io.ktor:ktor-server-content-negotiation to v2.1.3 (#357)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-28 14:38:54 +00:00
b8f2090a8a fix(deps): update kotestversion to v5.5.3 (#355)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-28 05:47:04 +00:00
178db951a5 chore: prep for 3.4.0 release 2022-10-26 09:50:52 -04:00
fa5ada8f64 feat: add possibility to customize docs path (#352) 2022-10-26 09:48:37 -04:00
4345833b75 fix(deps): update dependency io.kotest:kotest-runner-junit5-jvm to v5.5.2 (#351)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-24 02:34:28 +00:00
3158195bd9 fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.4.1 (#350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-15 01:28:11 +00:00
70586a7cc6 chore: show nested documentation on basic playground 2022-10-14 15:52:45 -04:00
6f4e268b91 fix(deps): update dependency joda-time:joda-time to v2.12.0 (#349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-13 19:42:10 +00:00
a1638f930a fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.4 (#348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-10 21:14:07 +00:00
0120feb168 fix(deps): update dependency io.kotest:kotest-property-jvm to v5.5.1 (#347)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-10 00:56:02 +00:00
1da3ad5db9 chore(deps): update plugin org.jetbrains.kotlinx.kover to v0.6.1 (#344)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-09 08:01:04 -05:00
a8019bc4f8 fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.3 (#342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-03 18:41:08 -05:00
ecf0d42ee1 chore: update to sourdough 0.12.0 2022-10-03 18:40:00 -05:00
d76927ba3c fix(deps): update kotestversion to v5.5.0 (#343)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-03 11:42:18 -05:00
2c43d4d274 fix(deps): update ktor to v2.1.2 (#340) 2022-10-03 06:47:42 -05:00
3111b63916 chore: bumped versions (#341) 2022-10-02 14:38:54 +00:00
1759be5ba3 docs: initial gitbook docs (#336) 2022-09-29 21:36:48 -05:00
622dd6a5e7 chore: migrate to gitbook (#334) 2022-09-29 15:41:35 -05:00
6d6836927f fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.3 (#329)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-29 05:25:28 +00:00
9109a249e4 fix(deps): update dependency org.slf4j:slf4j-api to v2.0.3 (#328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 20:08:24 +00:00
60552b8abb doc: Added Latest Documentation 2022-09-26 13:22:18 +00:00
70345494ab fix: improved error output when an unknown schema is encountered (#327) 2022-09-26 13:15:21 +00:00
b3dcf7dc8b fix(deps): update dependency joda-time:joda-time to v2.11.2 (#326)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-26 05:11:40 +00:00
b1aa2e497a fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.2 (#324)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-21 15:16:33 +00:00
d6b852d297 fix(deps): update dependency org.slf4j:slf4j-api to v2.0.2 (#323)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-21 11:12:18 +00:00
42ea128aa3 fix(deps): update dependency dev.forst:ktor-api-key to v2.1.1-1 (#322)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 18:28:23 +00:00
8df32d7af6 fix(deps): update dependency org.apache.logging.log4j:log4j-core to v2.19.0 (#321)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-17 09:45:53 +00:00
3f21879417 fix(deps): update dependency org.apache.logging.log4j:log4j-api to v2.19.0 (#320)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-17 09:32:57 +00:00
cf238beccb fix(deps): update dependency org.slf4j:slf4j-api to v2.0.1 (#317)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-15 17:19:51 +00:00
3b5324ded1 doc: Added Latest Documentation 2022-09-15 13:34:05 +00:00
95ae274f1d chore: prep for 3.3.0 (#319) 2022-09-15 13:27:17 +00:00
fdcc64d29c fix: Remove print statements for examples (#318) 2022-09-15 13:07:06 +00:00
4daf6e000e fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.1 (#316)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-15 10:09:11 +00:00
ba19389f16 fix(deps): update dependency org.slf4j:slf4j-simple to v2.0.1 (#314)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-15 04:07:58 +00:00
e43627fa09 chore: enable recursion test (#315) 2022-09-14 21:45:10 +00:00
f1d252954b fix(deps): update dependency dev.forst:ktor-api-key to v2.1.1 (#313)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-07 17:29:04 +00:00
39d5c8b258 fix(deps): update ktor to v2.1.1 (#312)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-07 02:41:00 +00:00
28b844da6c fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.0 (#311)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-29 11:32:46 +00:00
76e6b0a278 chore: bump kover version (#308) 2022-08-26 22:59:33 +00:00
8ea6a001c2 fix(deps): update dependency joda-time:joda-time to v2.11.1 (#307)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-25 20:33:23 +00:00
190b3c4abe doc: Added Latest Documentation 2022-08-23 12:19:26 +00:00
71846 changed files with 15667 additions and 5012340 deletions

1
.gitbook.yaml Normal file
View File

@ -0,0 +1 @@
root: ./docs/

View File

@ -28,4 +28,4 @@ jobs:
uses: burrunan/gradle-cache-action@v1
with:
gradle-version: wrapper
arguments: test koverCollectReports
arguments: test koverMergedReport

View File

@ -16,7 +16,7 @@ jobs:
with:
distribution: 'adopt'
java-version: '17'
- name: Publlish to Maven Central
- name: Publish to Maven Central
uses: burrunan/gradle-cache-action@v1
with:
gradle-version: wrapper
@ -26,28 +26,3 @@ jobs:
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USER }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
build-documentation:
runs-on: ubuntu-latest
needs:
- publish-to-nexus
steps:
- uses: actions/checkout@v3
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '17'
- name: Build New Documentation
uses: burrunan/gradle-cache-action@v1
with:
gradle-version: wrapper
arguments: dokkaHtmlMultiModule
properties: |
release=true
- name: Push New Documentation
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
new_branch: main
message: 'doc: Added Latest Documentation ✨'

View File

@ -2,10 +2,6 @@
## Unreleased
- Support for @Transient annotation
- Support for @SerialName annotation on fields
- Supports for un-backed fields, by excluding them from the generated schema.
### Added
### Changed
@ -16,6 +12,124 @@
## Released
## [3.14.4] - June 5th, 2023
### Changed
- Components definitions were not in the proper schema section. Prefixed the path with component slug in `protobuf java converter`.
## [3.14.3] - May 22nd, 2023
### Added
- Added `required` parameter in request info builder.
## [3.14.2] - May 8rd, 2023
### Changed
- Fixed bug where routes were not resolving when a parameter was declared via the ktor SDK
## [3.14.1] - April 28th, 2023
### Changed
- Generating enrichments for generic classes no longer throws the `Slugs should not be generated for field enrichments` error.
## [3.14.0] - April 6th, 2023
### Added
- Add support for response headers
## [3.13.0] - March 15th, 2023
### Changed
- Post, Put, and Patch now support not providing request info
## [3.12.0] - March 14th, 2023
### Added
- Add support for swagger documentation
## [3.11.0] - January 5th, 2023
### Added
- Support for type constraints.
## [3.10.0] - January 4th, 2023
### Added
- Support for type enrichments! `deprecated` and `description` to start
## [3.9.0] - November 15th, 2022
### Added
- `protobuf-java-converter` module for converting generated protobuf objects to `JsonSchema` representations
### Changed
- Application `rootPath` is no longer prefixed to serialized route path when `NotarizedRoute` is resolved
## [3.8.0] - November 9th, 2022
### Added
- Add support for NotarizedResource plugin scoped to route
### Changed
- Support registering same path with different authentication and methods
## [3.7.0] - November 5th, 2022
### Added
- Allow users to override media type in request and response
## [3.6.0] - November 5th, 2022
### Changed
- Schemas for types in nullable properties are no longer nullable themselves
- Enums are now generated as references, which makes it possible to generate types for them
## [3.5.0] - October 29th, 2022
### Added
- New `kompendium-resources` plugin to support Ktor Resources API
## [3.4.0] - October 26th, 2022
### Added
- Support for custom docs path
## [3.3.1] - September 26th, 2022
### Added
- Better exception thrown when unidentified type is encountered
## [3.3.0] - September 15th, 2022
### Added
- Support for @Transient annotation
- Support for @SerialName annotation on fields
- Supports for un-backed fields, by excluding them from the generated schema.
### Changed
- Actually turned on detekt formatting 🤦
- Removed some rouge print statements
## Released
## [3.2.0] - August 23rd, 2022
### Added

View File

@ -20,9 +20,7 @@ To get an overview of the project, read the [README](README.md). Here are some r
## Getting started
The best way to get started with Kompendium is to read the [docs](https://bkbnio.github.io/kompendium). Kompendium generates
our documentation using [Dokka](https://github.com/Kotlin/dokka). This means that the docs live side-by-side with the source
code itself, and leverage the KDoc format to provide syntax highlighting, dynamic linking and more!
The best way to get started with Kompendium is to read the [docs](https://bkbn.gitbook.io/kompendium).
If live examples are more your thing, inside the `kompendium-playground` module, you will find a collection of starter
examples ranging from simple CRUD and authentication examples, to more advanced topics like polymorphic serialization

View File

@ -1,94 +0,0 @@
# Kompendium
Welcome to Kompendium, the straight-forward, non-invasive OpenAPI generator for Ktor.
## How to install
Kompendium publishes all releases to Maven Central. As such, using the release versions of `Kompendium` is as simple as
declaring it as an implementation dependency in your `build.gradle.kts`
```kotlin
repositories {
mavenCentral()
}
dependencies {
implementation("io.bkbn:kompendium-core:latest.release")
}
```
In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge
to `main`. These can be consumed by adding the repository to your gradle build file. Instructions can be
found [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package)
## Setting up Kompendium
Kompendium's core features are comprised of a singular application level plugin and a collection of route level plugins.
The former sets up your OpenApi spec along with various cross-route metadata and overrides such as custom types (useful
for things like datetime libraries)
### `NotarizedApplication` plugin
The notarized application plugin is installed at (surprise!) the app level
```kotlin
private fun Application.mainModule() {
install(NotarizedApplication()) {
spec = OpenApiSpec(
// spec details go here ...
)
}
}
```
### `NotarizedRoute` plugin
Notarized routes take advantage of Ktor 2's [route specific plugin](https://ktor.io/docs/plugins.html#install-route)
feature. This allows us to take individual routes, document them, and feed them back in to the application level plugin.
This also allows you to adopt Kompendium incrementally. Individual routes can be documented at your leisure, and is
purely
additive, meaning that you do not need to modify existing code to get documentation working, you just need new code!
Non-invasive FTW 🚀
Documenting a simple `GET` endpoint would look something like this
```kotlin
private fun Route.documentation() {
install(NotarizedRoute()) {
parameters = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
get = GetInfo.builder {
summary("Get user by id")
description("A very neat endpoint!")
response {
responseCode(HttpStatusCode.OK)
responseType<ExampleResponse>()
description("Will return whether or not the user is real 😱")
}
}
}
}
route("/{id}") {
documentation()
get {
call.respond(HttpStatusCode.OK, ExampleResponse(true))
}
}
```
Full details on application and route notarization can be found in the `core` module
## The Playground
In addition to the documentation available here, Kompendium has a number of out-of-the-box examples available in the
playground module. Go ahead and fork the repo and run them directly on your machine to get a sense of what Kompendium
can do!

View File

@ -2,60 +2,8 @@
[![version](https://img.shields.io/maven-central/v/io.bkbn/kompendium-core?style=flat-square)](https://search.maven.org/search?q=io.bkbn%20kompendium)
## Table of Contents
Documentation is stored in the `docs` folder and is hosted [here](https://bkbn.gitbook.io/kompendium)
- [What Is Kompendium](#what-is-kompendium)
- [How to Install](#how-to-install)
- [Library Details](#library-details)
- [Local Development](#local-development)
- [The Playground](#the-playground)
## Showcase
## What is Kompendium
Kompendium is intended to be a minimally invasive OpenApi Specification generator for Ktor. Minimally invasive meaning
that users will use only Ktor native functions when implementing their API, and will supplement with Kompendium code in
order to generate the appropriate spec.
### Compatability
| Kompendium | Ktor | OpenAPI |
|---|---| --- |
| 1.X | 1 | 3.0 |
| 2.X | 1 | 3.0 |
| 3.X | 2 | 3.1 |
## How to install
Kompendium publishes all releases to Maven Central. As such, using the release versions of `Kompendium` is as simple as
declaring it as an implementation dependency in your `build.gradle.kts`
```kotlin
repositories {
mavenCentral()
}
dependencies {
implementation("io.bkbn:kompendium-core:latest.release")
}
```
In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge
to `main`. These can be consumed by adding the repository to your gradle build file. Instructions can be
found [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package)
# Library Details
Library documentation lives alongside the source code, and is generated into a static site via Dokka. Can be viewed [here](https://bkbnio.github.io/kompendium)
## Local Development
Kompendium should run locally right out of the box, no configuration necessary (assuming you have JDK 11+ installed).
New features can be built locally and published to your local maven repository with the `./gradlew publishToMavenLocal`
command!
## The Playground
This repo contains a `playground` module that contains a number of working examples showcasing the capabilities of
Kompendium.
Feel free to check it out, or even create your own example!
If you would like to showcase docs that you build using Kompendium, add them to [the showcase discussion](https://github.com/bkbnio/kompendium/discussions/444)

View File

@ -1,13 +1,12 @@
plugins {
kotlin("jvm") version "1.7.10" apply false
kotlin("plugin.serialization") version "1.7.10" apply false
id("io.bkbn.sourdough.library.jvm") version "0.9.1" apply false
id("io.bkbn.sourdough.application.jvm") version "0.9.1" apply false
id("io.bkbn.sourdough.root") version "0.9.1"
kotlin("jvm") version "1.8.21" apply false
kotlin("plugin.serialization") version "1.8.21" apply false
id("io.bkbn.sourdough.library.jvm") version "0.12.0" apply false
id("io.bkbn.sourdough.application.jvm") version "0.12.0" apply false
id("io.bkbn.sourdough.root") version "0.12.0"
id("com.github.jakemarsden.git-hooks") version "0.0.2"
id("org.jetbrains.dokka") version "1.7.10"
id("org.jetbrains.kotlinx.kover") version "0.5.1"
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
id("org.jetbrains.kotlinx.kover") version "0.6.1"
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
}
gitHooks {

View File

@ -1,52 +0,0 @@
# Module kompendium-core
This is where the magic happens. This module houses all the reflective goodness that powers Kompendium.
It is also the only mandatory client-facing module for a basic setup.
# Package io.bkbn.kompendium.core
## Plugins
As mentioned in the root documentation, there are two core Kompendium plugins.
1. The application level plugin that handles app level metadata, configuring up your OpenAPI spec, managing custom data
types, etc.
2. The route level plugin, which is how users declare the documentation for the given route. It _must_ be installed on
every route you wish to document
### Serialization
Kompendium relies on your API to provide a properly-configured `ContentNegotiator` in order to convert the `OpenApiSpec`
into JSON. The advantage to this approach is that all of your data classes will be serialized precisely how you define.
The downside is that issues could exist in serialization frameworks that have not been tested. At the moment, Jackson,
Gson and KotlinX serialization have all been tested. If you run into any serialization issues, particularly with a
serializer not listed above, please open an issue on GitHub 🙏
Note for Kotlinx ⚠️
You will need to include the `SerializersModule` provided in `KompendiumSerializersModule` in order to serialize
any provided defaults. This comes down to how Kotlinx expects users to handle serializing `Any`. Essentially, this
serializer module will convert any `Any` serialization to be `Contextual`. This is pretty hacky, but seemed to be the
only way to get Kotlinx to play nice with serializing `Any`. If you come up with a better solution, definitely go ahead
and open up a PR!
## NotarizedApplication
TODO
## NotarizedRoute
TODO
# Package io.bkbn.kompendium.core.metadata
Houses all interfaces and types related to describing route metadata.
# Package io.bkbn.kompendium.core.routes
Houses any routes provided by the core module. At the moment the only supported route is to enable ReDoc support.
# Package io.bkbn.kompendium.core.util
Collection of utility functions used by Kompendium

View File

@ -4,11 +4,11 @@ plugins {
id("io.bkbn.sourdough.library.jvm")
id("io.gitlab.arturbosch.detekt")
id("com.adarshr.test-logger")
id("org.jetbrains.dokka")
id("maven-publish")
id("java-library")
id("signing")
id("java-test-fixtures")
id("org.jetbrains.kotlinx.kover")
}
sourdoughLibrary {
@ -21,6 +21,7 @@ dependencies {
// VERSIONS
val kotestVersion: String by project
val ktorVersion: String by project
val detektVersion: String by project
// IMPLEMENTATION
@ -32,7 +33,9 @@ dependencies {
implementation("io.ktor:ktor-server-html-builder:$ktorVersion")
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("ch.qos.logback:logback-classic:1.2.11")
// Formatting
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion")
// TEST FIXTURES
@ -54,9 +57,9 @@ dependencies {
testFixturesApi("io.ktor:ktor-client:$ktorVersion")
testFixturesApi("io.ktor:ktor-client-cio:$ktorVersion")
testFixturesApi("dev.forst:ktor-api-key:2.1.0")
testFixturesApi("dev.forst:ktor-api-key:2.2.4")
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
}
testing {

View File

@ -13,7 +13,7 @@ class DeleteInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfo {
) : MethodInfo {
companion object {
fun builder(init: Builder.() -> Unit): DeleteInfo {
@ -36,5 +36,4 @@ class DeleteInfo private constructor(
parameters = parameters
)
}
}

View File

@ -13,7 +13,7 @@ class GetInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfo {
) : MethodInfo {
companion object {
fun builder(init: Builder.() -> Unit): GetInfo {
@ -36,5 +36,4 @@ class GetInfo private constructor(
parameters = parameters
)
}
}

View File

@ -13,7 +13,7 @@ class HeadInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfo {
) : MethodInfo {
companion object {
fun builder(init: Builder.() -> Unit): HeadInfo {
@ -36,5 +36,4 @@ class HeadInfo private constructor(
parameters = parameters
)
}
}

View File

@ -1,9 +1,9 @@
package io.bkbn.kompendium.core.metadata
sealed interface MethodInfoWithRequest : MethodInfo {
val request: RequestInfo
val request: RequestInfo?
abstract class Builder<T: MethodInfoWithRequest> : MethodInfo.Builder<T>() {
abstract class Builder<T : MethodInfoWithRequest> : MethodInfo.Builder<T>() {
internal var request: RequestInfo? = null
fun request(init: RequestInfo.Builder.() -> Unit) = apply {

View File

@ -13,7 +13,7 @@ class OptionsInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfo {
) : MethodInfo {
companion object {
fun builder(init: Builder.() -> Unit): OptionsInfo {
@ -36,5 +36,4 @@ class OptionsInfo private constructor(
parameters = parameters
)
}
}

View File

@ -4,7 +4,7 @@ import io.bkbn.kompendium.oas.common.ExternalDocumentation
import io.bkbn.kompendium.oas.payload.Parameter
class PatchInfo private constructor(
override val request: RequestInfo,
override val request: RequestInfo?,
override val errors: MutableList<ResponseInfo>,
override val response: ResponseInfo,
override val tags: Set<String>,
@ -14,7 +14,7 @@ class PatchInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfoWithRequest {
) : MethodInfoWithRequest {
companion object {
fun builder(init: Builder.() -> Unit): PatchInfo {
@ -26,7 +26,7 @@ class PatchInfo private constructor(
class Builder : MethodInfoWithRequest.Builder<PatchInfo>() {
override fun build() = PatchInfo(
request = request ?: error("request info must be present"),
request = request,
errors = errors,
response = response ?: error("response info must be present"),
tags = tags,
@ -38,5 +38,4 @@ class PatchInfo private constructor(
parameters = parameters
)
}
}

View File

@ -4,7 +4,7 @@ import io.bkbn.kompendium.oas.common.ExternalDocumentation
import io.bkbn.kompendium.oas.payload.Parameter
class PostInfo private constructor(
override val request: RequestInfo,
override val request: RequestInfo?,
override val errors: MutableList<ResponseInfo>,
override val response: ResponseInfo,
override val tags: Set<String>,
@ -14,7 +14,7 @@ class PostInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfoWithRequest {
) : MethodInfoWithRequest {
companion object {
fun builder(init: Builder.() -> Unit): PostInfo {
@ -26,7 +26,7 @@ class PostInfo private constructor(
class Builder : MethodInfoWithRequest.Builder<PostInfo>() {
override fun build() = PostInfo(
request = request ?: error("request info must be present"),
request = request,
errors = errors,
response = response ?: error("response info must be present"),
tags = tags,
@ -38,5 +38,4 @@ class PostInfo private constructor(
parameters = parameters
)
}
}

View File

@ -4,7 +4,7 @@ import io.bkbn.kompendium.oas.common.ExternalDocumentation
import io.bkbn.kompendium.oas.payload.Parameter
class PutInfo private constructor(
override val request: RequestInfo,
override val request: RequestInfo?,
override val errors: MutableList<ResponseInfo>,
override val response: ResponseInfo,
override val tags: Set<String>,
@ -14,7 +14,7 @@ class PutInfo private constructor(
override val operationId: String?,
override val deprecated: Boolean,
override val parameters: List<Parameter>
): MethodInfoWithRequest {
) : MethodInfoWithRequest {
companion object {
fun builder(init: Builder.() -> Unit): PutInfo {
@ -26,7 +26,7 @@ class PutInfo private constructor(
class Builder : MethodInfoWithRequest.Builder<PutInfo>() {
override fun build() = PutInfo(
request = request ?: error("request info must be present"),
request = request,
errors = errors,
response = response ?: error("response info must be present"),
tags = tags,
@ -38,5 +38,4 @@ class PutInfo private constructor(
parameters = parameters
)
}
}

View File

@ -1,13 +1,17 @@
package io.bkbn.kompendium.core.metadata
import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.bkbn.kompendium.oas.payload.MediaType
import kotlin.reflect.KType
import kotlin.reflect.typeOf
class RequestInfo private constructor(
val requestType: KType,
val typeEnrichment: TypeEnrichment<*>?,
val description: String,
val examples: Map<String, MediaType.Example>?
val examples: Map<String, MediaType.Example>?,
val mediaTypes: Set<String>,
val required: Boolean
) {
companion object {
@ -20,27 +24,46 @@ class RequestInfo private constructor(
class Builder {
private var requestType: KType? = null
private var typeEnrichment: TypeEnrichment<*>? = null
private var description: String? = null
private var examples: Map<String, MediaType.Example>? = null
private var mediaTypes: Set<String>? = null
private var required: Boolean? = null
fun required(r: Boolean) = apply {
this.required = r
}
fun requestType(t: KType) = apply {
this.requestType = t
}
inline fun <reified T> requestType() = apply { requestType(typeOf<T>()) }
fun enrichment(t: TypeEnrichment<*>) = apply {
this.typeEnrichment = t
}
inline fun <reified T> requestType(enrichment: TypeEnrichment<T>? = null) = apply {
requestType(typeOf<T>())
enrichment?.let { enrichment(it) }
}
fun description(s: String) = apply { this.description = s }
fun examples(vararg e: Pair<String, Any>) = apply {
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
println(this.examples)
}
fun mediaTypes(vararg m: String) = apply {
this.mediaTypes = m.toSet()
}
fun build() = RequestInfo(
requestType = requestType ?: error("Request type must be present"),
description = description ?: error("Description must be present"),
examples = examples
typeEnrichment = typeEnrichment,
examples = examples,
mediaTypes = mediaTypes ?: setOf("application/json"),
required = required ?: true
)
}
}

View File

@ -1,5 +1,7 @@
package io.bkbn.kompendium.core.metadata
import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.bkbn.kompendium.oas.payload.Header
import io.bkbn.kompendium.oas.payload.MediaType
import io.ktor.http.HttpStatusCode
import kotlin.reflect.KType
@ -8,8 +10,11 @@ import kotlin.reflect.typeOf
class ResponseInfo private constructor(
val responseCode: HttpStatusCode,
val responseType: KType,
val typeEnrichment: TypeEnrichment<*>?,
val description: String,
val examples: Map<String, MediaType.Example>?
val examples: Map<String, MediaType.Example>?,
val mediaTypes: Set<String>,
val responseHeaders: Map<String, Header>?
) {
companion object {
@ -23,8 +28,15 @@ class ResponseInfo private constructor(
class Builder {
private var responseCode: HttpStatusCode? = null
private var responseType: KType? = null
private var typeEnrichment: TypeEnrichment<*>? = null
private var description: String? = null
private var examples: Map<String, MediaType.Example>? = null
private var mediaTypes: Set<String>? = null
private var responseHeaders: Map<String, Header>? = null
fun responseHeaders(headers: Map<String, Header>) = apply {
this.responseHeaders = headers
}
fun responseCode(code: HttpStatusCode) = apply {
this.responseCode = code
@ -34,20 +46,33 @@ class ResponseInfo private constructor(
this.responseType = t
}
inline fun <reified T> responseType() = apply { responseType(typeOf<T>()) }
fun enrichment(t: TypeEnrichment<*>) = apply {
this.typeEnrichment = t
}
inline fun <reified T> responseType(enrichment: TypeEnrichment<T>? = null) = apply {
responseType(typeOf<T>())
enrichment?.let { enrichment(it) }
}
fun description(s: String) = apply { this.description = s }
fun examples(vararg e: Pair<String, Any>) = apply {
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
println(this.examples)
}
fun mediaTypes(vararg m: String) = apply {
this.mediaTypes = m.toSet()
}
fun build() = ResponseInfo(
responseCode = responseCode ?: error("You must provide a response code in order to build a Response!"),
responseType = responseType ?: error("You must provide a response type in order to build a Response!"),
description = description ?: error("You must provide a description in order to build a Response!"),
examples = examples
typeEnrichment = typeEnrichment,
examples = examples,
mediaTypes = mediaTypes ?: setOf("application/json"),
responseHeaders = responseHeaders
)
}
}

View File

@ -10,16 +10,17 @@ import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.util.Helpers.addToSpec
import io.bkbn.kompendium.core.util.SpecConfig
import io.bkbn.kompendium.oas.OpenApiSpec
import io.bkbn.kompendium.oas.path.Path
import io.bkbn.kompendium.oas.path.PathOperation
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.server.application.ApplicationCallPipeline
import io.ktor.server.application.Hook
import io.ktor.server.application.PluginBuilder
import io.ktor.server.application.createRouteScopedPlugin
import io.ktor.server.routing.Route
import io.ktor.server.routing.application
object NotarizedRoute {
class Config : SpecConfig {
override var tags: Set<String> = emptySet()
override var parameters: List<Parameter> = emptyList()
@ -31,7 +32,6 @@ object NotarizedRoute {
override var head: HeadInfo? = null
override var options: OptionsInfo? = null
override var security: Map<String, List<String>>? = null
internal var path: Path? = null
}
private object InstallHook : Hook<(ApplicationCallPipeline) -> Unit> {
@ -44,69 +44,54 @@ object NotarizedRoute {
name = "NotarizedRoute",
createConfiguration = ::Config
) {
// This is required in order to introspect the route path and authentication
on(InstallHook) {
val route = it as? Route ?: return@on
val spec = application.attributes[KompendiumAttributes.openApiSpec]
val routePath = route.calculateRoutePath()
val authMethods = route.collectAuthMethods()
pluginConfig.path?.addDefaultAuthMethods(authMethods)
require(spec.paths[routePath] == null) {
"""
The specified path ${Parameter.Location.path} has already been documented!
Please make sure that all notarized paths are unique
""".trimIndent()
}
spec.paths[routePath] = pluginConfig.path
?: error("This indicates a bug in Kompendium. Please file a GitHub issue!")
addToSpec(spec, routePath, authMethods)
}
val spec = application.attributes[KompendiumAttributes.openApiSpec]
val serializableReader = application.attributes[KompendiumAttributes.schemaConfigurator]
val path = Path()
path.parameters = pluginConfig.parameters
pluginConfig.get?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.delete?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.head?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.options?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.post?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.put?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.patch?.addToSpec(path, spec, pluginConfig, serializableReader)
pluginConfig.path = path
}
private fun Route.calculateRoutePath() = toString().replace(Regex("/\\(.+\\)"), "")
private fun Route.collectAuthMethods() = toString()
fun <T : SpecConfig> PluginBuilder<T>.addToSpec(
spec: OpenApiSpec,
fullPath: String,
authMethods: List<String>
) {
val path = spec.paths[fullPath] ?: Path()
path.parameters = path.parameters?.plus(pluginConfig.parameters) ?: pluginConfig.parameters
val serializableReader = application.attributes[KompendiumAttributes.schemaConfigurator]
pluginConfig.get?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.delete?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.head?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.options?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.post?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.put?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
pluginConfig.patch?.addToSpec(path, spec, pluginConfig, serializableReader, fullPath, authMethods)
spec.paths[fullPath] = path
}
fun Route.calculateRoutePath() = toString()
.let {
application.environment.rootPath.takeIf { root -> root.isNotEmpty() }
?.let { root ->
val sanitizedRoute = if (root.startsWith("/")) root else "/$root"
it.replace(sanitizedRoute, "")
}
?: it
}
.replace(Regex("/\\(.+\\)"), "")
.replace(Regex("/\\[.+\\]"), "")
fun Route.collectAuthMethods() = toString()
.split("/")
.filter { it.contains(Regex("\\(authenticate .*\\)")) }
.map { it.replace("(authenticate ", "").replace(")", "") }
.map { it.split(", ") }
.flatten()
private fun Path.addDefaultAuthMethods(methods: List<String>) {
get?.addDefaultAuthMethods(methods)
put?.addDefaultAuthMethods(methods)
post?.addDefaultAuthMethods(methods)
delete?.addDefaultAuthMethods(methods)
options?.addDefaultAuthMethods(methods)
head?.addDefaultAuthMethods(methods)
patch?.addDefaultAuthMethods(methods)
trace?.addDefaultAuthMethods(methods)
}
private fun PathOperation.addDefaultAuthMethods(methods: List<String>) {
methods.forEach { m ->
if (security == null || security?.all { s -> !s.containsKey(m) } == true) {
if (security == null) {
security = mutableListOf(mapOf(m to emptyList()))
} else {
security?.add(mapOf(m to emptyList()))
}
}
}
}
}

View File

@ -16,12 +16,13 @@ import kotlinx.html.title
import kotlinx.html.unsafe
/**
* Provides an out-of-the-box route to view docs using ReDoc
* Provides an out-of-the-box route to view docs using ReDoc on the specified [path].
* @param pageTitle Webpage title you wish to be displayed on your docs
* @param path path to docs resource
* @param specUrl url to point ReDoc to the OpenAPI json document
*/
fun Route.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
route("/docs") {
fun Route.redoc(pageTitle: String = "Docs", path: String = "/docs", specUrl: String = "/openapi.json") {
route(path) {
get {
call.respondHtml(HttpStatusCode.OK) {
head {
@ -46,7 +47,7 @@ fun Route.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
}
}
body {
unsafe { +"<redoc spec-url='${specUrl}'></redoc>" }
unsafe { +"<redoc spec-url='$specUrl'></redoc>" }
script {
src = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"
}

View File

@ -0,0 +1,91 @@
package io.bkbn.kompendium.core.routes
import io.ktor.server.application.call
import io.ktor.server.html.respondHtml
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import kotlinx.html.body
import kotlinx.html.div
import kotlinx.html.head
import kotlinx.html.id
import kotlinx.html.link
import kotlinx.html.meta
import kotlinx.html.script
import kotlinx.html.title
import kotlinx.html.unsafe
/**
* Provides an out-of-the-box route to view docs using Swagger
* @see <a href="https://swagger.io/specification/">Swagger OpenApi Specification</a>
* for the latest supported open api version.
* @param pageTitle Webpage title you wish to be displayed on your docs
* @param path path to docs resource
* @param specUrl url to point Swagger to the OpenAPI json document
* @param swaggerVersion version of swagger-ui distribution
*/
fun Route.swagger(
pageTitle: String = "Docs",
path: String = "/swagger-ui",
specUrl: String = "/openapi.json",
swaggerVersion: String? = null
) {
val swaggerVersionSuffix = if (swaggerVersion == null) "" else "@$swaggerVersion"
route(path) {
get {
call.respondHtml {
head {
title {
+pageTitle
}
meta {
charset = "utf-8"
}
meta {
name = "viewport"
content = "width=device-width, initial-scale=1"
}
link {
href = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui.css"
rel = "stylesheet"
}
}
body {
div {
id = "swagger-ui"
}
script {
src = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui-standalone-preset.js"
}
script {
src = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui-bundle.js"
}
unsafe {
+"""
<script>
window.onload = function () {
// Build a system
const ui = SwaggerUIBundle({
url: "$specUrl",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
})
window.ui = ui
}
</script>
""".trimIndent()
}
}
}
}
}
}

View File

@ -10,11 +10,14 @@ import io.bkbn.kompendium.core.metadata.PatchInfo
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.metadata.ResponseInfo
import io.bkbn.kompendium.json.schema.SchemaGenerator
import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.bkbn.kompendium.json.schema.SchemaConfigurator
import io.bkbn.kompendium.json.schema.SchemaGenerator
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
import io.bkbn.kompendium.json.schema.util.Helpers.getSlug
import io.bkbn.kompendium.oas.OpenApiSpec
import io.bkbn.kompendium.oas.path.Path
import io.bkbn.kompendium.oas.path.PathOperation
@ -22,32 +25,62 @@ import io.bkbn.kompendium.oas.payload.MediaType
import io.bkbn.kompendium.oas.payload.Request
import io.bkbn.kompendium.oas.payload.Response
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KType
object Helpers {
fun MethodInfo.addToSpec(path: Path, spec: OpenApiSpec, config: SpecConfig, schemaConfigurator: SchemaConfigurator) {
private fun PathOperation.addDefaultAuthMethods(methods: List<String>) {
methods.forEach { m ->
if (security == null || security?.all { s -> !s.containsKey(m) } == true) {
if (security == null) {
security = mutableListOf(mapOf(m to emptyList()))
} else {
security?.add(mapOf(m to emptyList()))
}
}
}
}
fun MethodInfo.addToSpec(
path: Path,
spec: OpenApiSpec,
config: SpecConfig,
schemaConfigurator: SchemaConfigurator,
routePath: String,
authMethods: List<String> = emptyList()
) {
SchemaGenerator.fromTypeOrUnit(
this.response.responseType,
spec.components.schemas, schemaConfigurator
type = this.response.responseType,
cache = spec.components.schemas,
schemaConfigurator = schemaConfigurator,
enrichment = this.response.typeEnrichment,
)?.let { schema ->
spec.components.schemas[this.response.responseType.getSimpleSlug()] = schema
spec.components.schemas[this.response.responseType.getSlug(this.response.typeEnrichment)] = schema
}
errors.forEach { error ->
SchemaGenerator.fromTypeOrUnit(error.responseType, spec.components.schemas, schemaConfigurator)?.let { schema ->
spec.components.schemas[error.responseType.getSimpleSlug()] = schema
SchemaGenerator.fromTypeOrUnit(
type = error.responseType,
cache = spec.components.schemas,
schemaConfigurator = schemaConfigurator,
enrichment = error.typeEnrichment,
)?.let { schema ->
spec.components.schemas[error.responseType.getSlug(error.typeEnrichment)] = schema
}
}
when (this) {
is MethodInfoWithRequest -> {
SchemaGenerator.fromTypeOrUnit(
this.request.requestType,
spec.components.schemas,
schemaConfigurator
)?.let { schema ->
spec.components.schemas[this.request.requestType.getSimpleSlug()] = schema
this.request?.let { reqInfo ->
SchemaGenerator.fromTypeOrUnit(
type = reqInfo.requestType,
cache = spec.components.schemas,
schemaConfigurator = schemaConfigurator,
enrichment = reqInfo.typeEnrichment,
)?.let { schema ->
spec.components.schemas[reqInfo.requestType.getSlug(reqInfo.typeEnrichment)] = schema
}
}
}
@ -55,15 +88,25 @@ object Helpers {
}
val operations = this.toPathOperation(config)
operations.addDefaultAuthMethods(authMethods)
when (this) {
is DeleteInfo -> path.delete = operations
is GetInfo -> path.get = operations
is HeadInfo -> path.head = operations
is PatchInfo -> path.patch = operations
is PostInfo -> path.post = operations
is PutInfo -> path.put = operations
is OptionsInfo -> path.options = operations
fun setOperation(
property: KMutableProperty1<Path, PathOperation?>
) {
require(property.get(path) == null) {
"A route has already been registered for path: $routePath and method: ${property.name.uppercase()}"
}
property.set(path, operations)
}
return when (this) {
is DeleteInfo -> setOperation(Path::delete)
is GetInfo -> setOperation(Path::get)
is HeadInfo -> setOperation(Path::head)
is PatchInfo -> setOperation(Path::patch)
is PostInfo -> setOperation(Path::post)
is PutInfo -> setOperation(Path::put)
is OptionsInfo -> setOperation(Path::options)
}
}
@ -80,18 +123,29 @@ object Helpers {
?.map { listOf(it).toMap() }
?.toMutableList(),
requestBody = when (this) {
is MethodInfoWithRequest -> Request(
description = this.request.description,
content = this.request.requestType.toReferenceContent(this.request.examples),
required = true
)
is MethodInfoWithRequest -> this.request?.let { reqInfo ->
Request(
description = reqInfo.description,
content = reqInfo.requestType.toReferenceContent(
examples = reqInfo.examples,
mediaTypes = reqInfo.mediaTypes,
enrichment = reqInfo.typeEnrichment
),
required = reqInfo.required
)
}
else -> null
},
responses = mapOf(
this.response.responseCode.value to Response(
description = this.response.description,
content = this.response.responseType.toReferenceContent(this.response.examples)
headers = this.response.responseHeaders,
content = this.response.responseType.toReferenceContent(
examples = this.response.examples,
mediaTypes = this.response.mediaTypes,
enrichment = this.response.typeEnrichment
)
)
).plus(this.errors.toResponseMap())
)
@ -99,18 +153,34 @@ object Helpers {
private fun List<ResponseInfo>.toResponseMap(): Map<Int, Response> = associate { error ->
error.responseCode.value to Response(
description = error.description,
content = error.responseType.toReferenceContent(error.examples)
headers = error.responseHeaders,
content = error.responseType.toReferenceContent(
examples = error.examples,
mediaTypes = error.mediaTypes,
enrichment = error.typeEnrichment
)
)
}
private fun KType.toReferenceContent(examples: Map<String, MediaType.Example>?): Map<String, MediaType>? =
private fun KType.toReferenceContent(
examples: Map<String, MediaType.Example>?,
mediaTypes: Set<String>,
enrichment: TypeEnrichment<*>?
): Map<String, MediaType>? =
when (this.classifier as KClass<*>) {
Unit::class -> null
else -> mapOf(
"application/json" to MediaType(
schema = ReferenceDefinition(this.getReferenceSlug()),
else -> mediaTypes.associateWith {
MediaType(
schema = if (this.isMarkedNullable) {
OneOfDefinition(
NullableDefinition(),
ReferenceDefinition(this.getReferenceSlug(enrichment))
)
} else {
ReferenceDefinition(this.getReferenceSlug(enrichment))
},
examples = examples
)
)
}
}
}

View File

@ -2,63 +2,86 @@ package io.bkbn.kompendium.core
import dev.forst.ktor.apikey.apiKey
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
import io.bkbn.kompendium.core.util.TestModules.complexRequest
import io.bkbn.kompendium.core.util.TestModules.customAuthConfig
import io.bkbn.kompendium.core.util.TestModules.customFieldNameResponse
import io.bkbn.kompendium.core.util.TestModules.dateTimeString
import io.bkbn.kompendium.core.util.TestModules.defaultAuthConfig
import io.bkbn.kompendium.core.util.TestModules.defaultField
import io.bkbn.kompendium.core.util.TestModules.defaultParameter
import io.bkbn.kompendium.core.util.TestModules.exampleParams
import io.bkbn.kompendium.core.util.TestModules.nestedUnderRoot
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParams
import io.bkbn.kompendium.core.util.TestModules.notarizedDelete
import io.bkbn.kompendium.core.util.TestModules.notarizedGet
import io.bkbn.kompendium.core.util.TestModules.singleException
import io.bkbn.kompendium.core.util.TestModules.genericException
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponse
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponseMultipleImpls
import io.bkbn.kompendium.core.util.TestModules.gnarlyGenericResponse
import io.bkbn.kompendium.core.util.TestModules.headerParameter
import io.bkbn.kompendium.core.util.TestModules.ignoredFieldsResponse
import io.bkbn.kompendium.core.util.TestModules.multipleAuthStrategies
import io.bkbn.kompendium.core.util.TestModules.multipleExceptions
import io.bkbn.kompendium.core.util.TestModules.nestedGenericCollection
import io.bkbn.kompendium.core.util.TestModules.nestedGenericMultipleParamsCollection
import io.bkbn.kompendium.core.util.TestModules.nestedGenericResponse
import io.bkbn.kompendium.core.util.TestModules.nestedTypeName
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParam
import io.bkbn.kompendium.core.util.TestModules.polymorphicException
import io.bkbn.kompendium.core.util.TestModules.notarizedHead
import io.bkbn.kompendium.core.util.TestModules.notarizedOptions
import io.bkbn.kompendium.core.util.TestModules.notarizedPatch
import io.bkbn.kompendium.core.util.TestModules.notarizedPost
import io.bkbn.kompendium.core.util.TestModules.notarizedPut
import io.bkbn.kompendium.core.util.TestModules.nullableEnumField
import io.bkbn.kompendium.core.util.TestModules.nullableField
import io.bkbn.kompendium.core.util.TestModules.nullableNestedObject
import io.bkbn.kompendium.core.util.TestModules.nullableReference
import io.bkbn.kompendium.core.util.TestModules.polymorphicCollectionResponse
import io.bkbn.kompendium.core.util.TestModules.polymorphicMapResponse
import io.bkbn.kompendium.core.util.TestModules.polymorphicResponse
import io.bkbn.kompendium.core.util.TestModules.primitives
import io.bkbn.kompendium.core.util.TestModules.reqRespExamples
import io.bkbn.kompendium.core.util.TestModules.requiredParams
import io.bkbn.kompendium.core.util.TestModules.returnsList
import io.bkbn.kompendium.core.util.TestModules.rootRoute
import io.bkbn.kompendium.core.util.TestModules.simpleGenericResponse
import io.bkbn.kompendium.core.util.TestModules.simplePathParsing
import io.bkbn.kompendium.core.util.TestModules.simpleRecursive
import io.bkbn.kompendium.core.util.TestModules.trailingSlash
import io.bkbn.kompendium.core.util.TestModules.unbackedFieldsResponse
import io.bkbn.kompendium.core.util.TestModules.withOperationId
import io.bkbn.kompendium.core.util.arrayConstraints
import io.bkbn.kompendium.core.util.complexRequest
import io.bkbn.kompendium.core.util.customAuthConfig
import io.bkbn.kompendium.core.util.customFieldNameResponse
import io.bkbn.kompendium.core.util.dateTimeString
import io.bkbn.kompendium.core.util.defaultAuthConfig
import io.bkbn.kompendium.core.util.defaultField
import io.bkbn.kompendium.core.util.defaultParameter
import io.bkbn.kompendium.core.util.doubleConstraints
import io.bkbn.kompendium.core.util.enrichedGenericResponse
import io.bkbn.kompendium.core.util.enrichedComplexGenericType
import io.bkbn.kompendium.core.util.enrichedNestedCollection
import io.bkbn.kompendium.core.util.enrichedSimpleRequest
import io.bkbn.kompendium.core.util.enrichedSimpleResponse
import io.bkbn.kompendium.core.util.exampleParams
import io.bkbn.kompendium.core.util.genericException
import io.bkbn.kompendium.core.util.genericPolymorphicResponse
import io.bkbn.kompendium.core.util.genericPolymorphicResponseMultipleImpls
import io.bkbn.kompendium.core.util.gnarlyGenericResponse
import io.bkbn.kompendium.core.util.headerParameter
import io.bkbn.kompendium.core.util.ignoredFieldsResponse
import io.bkbn.kompendium.core.util.intConstraints
import io.bkbn.kompendium.core.util.multipleAuthStrategies
import io.bkbn.kompendium.core.util.multipleExceptions
import io.bkbn.kompendium.core.util.nestedGenericCollection
import io.bkbn.kompendium.core.util.nestedGenericMultipleParamsCollection
import io.bkbn.kompendium.core.util.nestedGenericResponse
import io.bkbn.kompendium.core.util.nestedTypeName
import io.bkbn.kompendium.core.util.nestedUnderRoot
import io.bkbn.kompendium.core.util.nonRequiredParam
import io.bkbn.kompendium.core.util.nonRequiredParams
import io.bkbn.kompendium.core.util.notarizedDelete
import io.bkbn.kompendium.core.util.notarizedGet
import io.bkbn.kompendium.core.util.notarizedHead
import io.bkbn.kompendium.core.util.notarizedOptions
import io.bkbn.kompendium.core.util.notarizedPatch
import io.bkbn.kompendium.core.util.notarizedPost
import io.bkbn.kompendium.core.util.notarizedPut
import io.bkbn.kompendium.core.util.nullableEnumField
import io.bkbn.kompendium.core.util.nullableField
import io.bkbn.kompendium.core.util.nullableNestedObject
import io.bkbn.kompendium.core.util.nullableReference
import io.bkbn.kompendium.core.util.overrideMediaTypes
import io.bkbn.kompendium.core.util.polymorphicCollectionResponse
import io.bkbn.kompendium.core.util.polymorphicException
import io.bkbn.kompendium.core.util.polymorphicMapResponse
import io.bkbn.kompendium.core.util.polymorphicResponse
import io.bkbn.kompendium.core.util.postNoReqBody
import io.bkbn.kompendium.core.util.primitives
import io.bkbn.kompendium.core.util.reqRespExamples
import io.bkbn.kompendium.core.util.optionalReqExample
import io.bkbn.kompendium.core.util.requiredParams
import io.bkbn.kompendium.core.util.responseHeaders
import io.bkbn.kompendium.core.util.returnsList
import io.bkbn.kompendium.core.util.rootRoute
import io.bkbn.kompendium.core.util.samePathDifferentMethodsAndAuth
import io.bkbn.kompendium.core.util.samePathSameMethod
import io.bkbn.kompendium.core.util.simpleGenericResponse
import io.bkbn.kompendium.core.util.simplePathParsing
import io.bkbn.kompendium.core.util.simpleRecursive
import io.bkbn.kompendium.core.util.singleException
import io.bkbn.kompendium.core.util.stringConstraints
import io.bkbn.kompendium.core.util.stringContentEncodingConstraints
import io.bkbn.kompendium.core.util.stringPatternConstraints
import io.bkbn.kompendium.core.util.topLevelNullable
import io.bkbn.kompendium.core.util.trailingSlash
import io.bkbn.kompendium.core.util.paramWrapper
import io.bkbn.kompendium.core.util.unbackedFieldsResponse
import io.bkbn.kompendium.core.util.withOperationId
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.json.schema.exception.UnknownSchemaException
import io.bkbn.kompendium.oas.component.Components
import io.bkbn.kompendium.oas.security.ApiKeyAuth
import io.bkbn.kompendium.oas.security.BasicAuth
import io.bkbn.kompendium.oas.security.BearerAuth
import io.bkbn.kompendium.oas.security.OAuth
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.should
import io.kotest.matchers.string.startWith
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.http.HttpMethod
@ -69,8 +92,9 @@ import io.ktor.server.auth.UserIdPrincipal
import io.ktor.server.auth.basic
import io.ktor.server.auth.jwt.jwt
import io.ktor.server.auth.oauth
import kotlin.reflect.typeOf
import java.net.URI
import java.time.Instant
import kotlin.reflect.typeOf
class KompendiumTest : DescribeSpec({
describe("Notarized Open API Metadata Tests") {
@ -107,6 +131,15 @@ class KompendiumTest : DescribeSpec({
it("Can notarize a route with non-required params") {
openApiTestAllSerializers("T0011__non_required_params.json") { nonRequiredParams() }
}
it("Can override media types") {
openApiTestAllSerializers("T0052__override_media_types.json") { overrideMediaTypes() }
}
it("Can support a post request with no request body") {
openApiTestAllSerializers("T0065__post_no_req_body.json") { postNoReqBody() }
}
it("Can notarize a route with response headers") {
openApiTestAllSerializers("T0066__notarized_get_with_response_headers.json") { responseHeaders() }
}
}
describe("Route Parsing") {
it("Can parse a simple path and store it under the expected route") {
@ -121,6 +154,9 @@ class KompendiumTest : DescribeSpec({
it("Can notarize a route with a trailing slash") {
openApiTestAllSerializers("T0015__trailing_slash.json") { trailingSlash() }
}
it("Can notarize a route with a parameter") {
openApiTestAllSerializers("T0068__param_wrapper.json") { paramWrapper() }
}
}
describe("Exceptions") {
it("Can add an exception status code to a response") {
@ -143,6 +179,9 @@ class KompendiumTest : DescribeSpec({
it("Can describe example parameters") {
openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() }
}
it("Can generate example optional request body") {
openApiTestAllSerializers("T0069__example_optional_req.json") { optionalReqExample() }
}
}
describe("Defaults") {
it("Can generate a default parameter value") {
@ -189,7 +228,9 @@ class KompendiumTest : DescribeSpec({
openApiTestAllSerializers("T0039__nested_generic_collection.json") { nestedGenericCollection() }
}
it("Can support nested generics with multiple type parameters") {
openApiTestAllSerializers("T0040__nested_generic_multiple_type_params.json") { nestedGenericMultipleParamsCollection() }
openApiTestAllSerializers("T0040__nested_generic_multiple_type_params.json") {
nestedGenericMultipleParamsCollection()
}
}
it("Can handle a really gnarly generic example") {
openApiTestAllSerializers("T0043__gnarly_generic_example.json") { gnarlyGenericResponse() }
@ -237,9 +278,68 @@ class KompendiumTest : DescribeSpec({
it("Can handle nested type names") {
openApiTestAllSerializers("T0044__nested_type_name.json") { nestedTypeName() }
}
it("Can handle top level nullable types") {
openApiTestAllSerializers("T0051__top_level_nullable.json") { topLevelNullable() }
}
it("Can handle multiple registrations for different methods with the same path and different auth") {
openApiTestAllSerializers(
"T0053__same_path_different_methods_and_auth.json",
applicationSetup = {
install(Authentication) {
basic("basic") {
realm = "Ktor Server"
validate { UserIdPrincipal("Placeholder") }
}
}
},
specOverrides = {
this.copy(
components = Components(
securitySchemes = mutableMapOf(
"basic" to BasicAuth()
)
)
)
}
) { samePathDifferentMethodsAndAuth() }
}
it("Can generate paths without application root-path") {
openApiTestAllSerializers(
"T0054__app_with_rootpath.json",
applicationEnvironmentBuilder = {
rootPath = "/example"
},
specOverrides = {
copy(
servers = servers.map { it.copy(url = URI("${it.url}/example")) }.toMutableList()
)
}
) { notarizedGet() }
}
}
describe("Constraints") {
// TODO Assess strategies here
describe("Error Handling") {
it("Throws a clear exception when an unidentified type is encountered") {
val exception = shouldThrow<UnknownSchemaException> { openApiTestAllSerializers("") { dateTimeString() } }
exception.message should startWith("An unknown type was encountered: class java.time.Instant")
}
it("Throws an exception when same method for same path has been previously registered") {
val exception = shouldThrow<IllegalArgumentException> {
openApiTestAllSerializers(
snapshotName = "",
applicationSetup = {
install(Authentication) {
basic("basic") {
realm = "Ktor Server"
validate { UserIdPrincipal("Placeholder") }
}
}
},
) {
samePathSameMethod()
}
}
exception.message should startWith("A route has already been registered for path: /test/{a} and method: GET")
}
}
describe("Formats") {
it("Can set a format for a simple type schema") {
@ -348,4 +448,43 @@ class KompendiumTest : DescribeSpec({
) { multipleAuthStrategies() }
}
}
describe("Enrichment") {
it("Can enrich a simple request") {
openApiTestAllSerializers("T0055__enriched_simple_request.json") { enrichedSimpleRequest() }
}
it("Can enrich a simple response") {
openApiTestAllSerializers("T0058__enriched_simple_response.json") { enrichedSimpleResponse() }
}
it("Can enrich a nested collection") {
openApiTestAllSerializers("T0056__enriched_nested_collection.json") { enrichedNestedCollection() }
}
it("Can enrich a complex generic type") {
openApiTestAllSerializers("T0057__enriched_complex_generic_type.json") { enrichedComplexGenericType() }
}
it("Can enrich a generic object") {
openApiTestAllSerializers("T0067__enriched_generic_object.json") { enrichedGenericResponse() }
}
}
describe("Constraints") {
it("Can apply constraints to an int field") {
openApiTestAllSerializers("T0059__int_constraints.json") { intConstraints() }
}
it("Can apply constraints to a double field") {
openApiTestAllSerializers("T0060__double_constraints.json") { doubleConstraints() }
}
it("Can apply a min and max length to a string field") {
openApiTestAllSerializers("T0061__string_min_max_constraints.json") { stringConstraints() }
}
it("Can apply a pattern to a string field") {
openApiTestAllSerializers("T0062__string_pattern_constraints.json") { stringPatternConstraints() }
}
it("Can apply a content encoding and media type to a string field") {
openApiTestAllSerializers("T0063__string_content_encoding_constraints.json") {
stringContentEncodingConstraints()
}
}
it("Can apply constraints to an array field") {
openApiTestAllSerializers("T0064__array_constraints.json") { arrayConstraints() }
}
}
})

View File

@ -0,0 +1,51 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.auth.authenticate
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.defaultAuthConfig() {
authenticate("basic") {
route(rootPath) {
basicGetGenerator<TestResponse>()
}
}
}
fun Routing.customAuthConfig() {
authenticate("auth-oauth-google") {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
security = mapOf(
"auth-oauth-google" to listOf("read:pets")
)
}
}
}
}
}
fun Routing.multipleAuthStrategies() {
authenticate("jwt", "api-key") {
route(rootPath) {
basicGetGenerator<TestResponse>()
}
}
}

View File

@ -0,0 +1,160 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.DoubleResponse
import io.bkbn.kompendium.core.fixtures.Page
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
import io.bkbn.kompendium.core.fixtures.TestNested
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultPath
import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.intConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get an int")
description("Get an int")
response {
responseCode(HttpStatusCode.OK)
description("An int")
responseType(
enrichment = TypeEnrichment("example") {
TestCreatedResponse::id {
minimum = 2
maximum = 100
multipleOf = 2
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}
fun Routing.doubleConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get a double")
description("Get a double")
response {
responseCode(HttpStatusCode.OK)
description("A double")
responseType(
enrichment = TypeEnrichment("example") {
DoubleResponse::payload {
minimum = 2.0
maximum = 100.0
multipleOf = 2.0
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}
fun Routing.stringConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get a string")
description("Get a string with constraints")
response {
responseCode(HttpStatusCode.OK)
description("A string")
responseType(
enrichment = TypeEnrichment("example") {
TestNested::nesty {
maxLength = 10
minLength = 2
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}
fun Routing.stringPatternConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get a string")
description("This is a description")
response {
responseCode(HttpStatusCode.OK)
description("A string")
responseType(
enrichment = TypeEnrichment("example") {
TestNested::nesty {
pattern = "[a-z]+"
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}
fun Routing.stringContentEncodingConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get a string")
description("This is a description")
response {
responseCode(HttpStatusCode.OK)
description("A string")
responseType(
enrichment = TypeEnrichment("example") {
TestNested::nesty {
contentEncoding = "base64"
contentMediaType = "image/png"
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}
fun Routing.arrayConstraints() {
route(defaultPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary("Get an array")
description("Get an array of strings")
response {
responseCode(HttpStatusCode.OK)
description("An array")
responseType(
enrichment = TypeEnrichment("example") {
Page<String>::content {
minItems = 2
maxItems = 10
uniqueItems = true
}
}
)
responseCode(HttpStatusCode.OK)
}
}
}
}
}

View File

@ -0,0 +1,10 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.SerialNameObject
import io.bkbn.kompendium.core.fixtures.TransientObject
import io.bkbn.kompendium.core.fixtures.UnbackedObject
import io.ktor.server.routing.Routing
fun Routing.ignoredFieldsResponse() = basicGetGenerator<TransientObject>()
fun Routing.unbackedFieldsResponse() = basicGetGenerator<UnbackedObject>()
fun Routing.customFieldNameResponse() = basicGetGenerator<SerialNameObject>()

View File

@ -0,0 +1,16 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.server.routing.Routing
fun Routing.defaultParameter() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING.withDefault("IDK")
)
)
)

View File

@ -0,0 +1,168 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.ComplexRequest
import io.bkbn.kompendium.core.fixtures.MultiNestedGenerics
import io.bkbn.kompendium.core.fixtures.NestedComplexItem
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
import io.bkbn.kompendium.core.fixtures.GenericObject
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.enrichedSimpleResponse() {
route("/enriched") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
response {
responseType(
enrichment = TypeEnrichment("simple") {
TestResponse::c {
description = "A simple description"
}
}
)
description("A good response")
responseCode(HttpStatusCode.Created)
}
}
}
}
}
fun Routing.enrichedSimpleRequest() {
route("/example") {
install(NotarizedRoute()) {
parameters = TestModules.defaultParams
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType(
enrichment = TypeEnrichment("simple") {
TestSimpleRequest::a {
description = "A simple description"
}
TestSimpleRequest::b {
deprecated = true
}
}
)
description("A test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
}
}
}
}
}
fun Routing.enrichedNestedCollection() {
route("/example") {
install(NotarizedRoute()) {
parameters = TestModules.defaultParams
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType(
enrichment = TypeEnrichment("simple") {
ComplexRequest::tables {
description = "A nested item"
typeEnrichment = TypeEnrichment("nested") {
NestedComplexItem::name {
description = "A nested description"
}
}
}
}
)
description("A test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
}
}
}
}
}
fun Routing.enrichedComplexGenericType() {
route("/example") {
install(NotarizedRoute()) {
parameters = TestModules.defaultParams
post = PostInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
request {
requestType(
enrichment = TypeEnrichment("simple") {
MultiNestedGenerics<String, ComplexRequest>::content {
description = "Getting pretty crazy"
typeEnrichment = TypeEnrichment("nested") {
ComplexRequest::tables {
description = "A nested item"
typeEnrichment = TypeEnrichment("nested") {
NestedComplexItem::name {
description = "A nested description"
}
}
}
}
}
}
)
description("A test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(TestModules.defaultResponseDescription)
}
}
}
}
}
fun Routing.enrichedGenericResponse() {
route("/example") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(TestModules.defaultPathSummary)
description(TestModules.defaultPathDescription)
response {
responseType(
enrichment = TypeEnrichment("generic") {
GenericObject<TestSimpleRequest>::data {
description = "A simple description"
typeEnrichment = TypeEnrichment("simple") {
TestSimpleRequest::a {
description = "A simple description"
}
TestSimpleRequest::b {
deprecated = true
}
}
}
}
)
description("A good response")
responseCode(HttpStatusCode.Created)
}
}
}
}
}

View File

@ -0,0 +1,16 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.util.TestModules.defaultPath
import io.ktor.server.auth.authenticate
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.samePathSameMethod() {
route(defaultPath) {
basicGetGenerator<TestResponse>()
authenticate("basic") {
basicGetGenerator<TestResponse>()
}
}
}

View File

@ -0,0 +1,84 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.TestNested
import io.bkbn.kompendium.core.fixtures.TestRequest
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultRequestDescription
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.reqRespExamples() {
route(rootPath) {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestRequest>()
examples(
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
)
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
examples(
"Testerino" to TestResponse("Heya")
)
}
}
}
}
}
fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING,
examples = mapOf(
"foo" to Parameter.Example("testing")
)
)
)
)
fun Routing.optionalReqExample() {
route(rootPath) {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestRequest>()
examples(
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
)
required(false)
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
examples(
"Testerino" to TestResponse("Heya")
)
}
}
}
}
}

View File

@ -0,0 +1,105 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.ExceptionResponse
import io.bkbn.kompendium.core.fixtures.Flibbity
import io.bkbn.kompendium.core.fixtures.FlibbityGibbit
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.singleException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<ExceptionResponse>()
}
}
}
}
}
fun Routing.multipleExceptions() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<ExceptionResponse>()
}
canRespond {
description("Access Denied")
responseCode(HttpStatusCode.Forbidden)
responseType<ExceptionResponse>()
}
}
}
}
}
fun Routing.polymorphicException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.InternalServerError)
responseType<FlibbityGibbit>()
}
}
}
}
}
fun Routing.genericException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<Flibbity<String>>()
}
}
}
}
}

View File

@ -0,0 +1,80 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.ColumnSchema
import io.bkbn.kompendium.core.fixtures.DateTimeString
import io.bkbn.kompendium.core.fixtures.ManyThings
import io.bkbn.kompendium.core.fixtures.Nested
import io.bkbn.kompendium.core.fixtures.NullableEnum
import io.bkbn.kompendium.core.fixtures.ProfileUpdateRequest
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultParams
import io.bkbn.kompendium.core.util.TestModules.defaultPath
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultRequestDescription
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.auth.authenticate
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
fun Routing.withOperationId() = basicGetGenerator<TestResponse>(operationId = "getThisDude")
fun Routing.nullableNestedObject() = basicGetGenerator<ProfileUpdateRequest>()
fun Routing.nullableEnumField() = basicGetGenerator<NullableEnum>()
fun Routing.nullableReference() = basicGetGenerator<ManyThings>()
fun Routing.dateTimeString() = basicGetGenerator<DateTimeString>()
fun Routing.headerParameter() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "X-User-Email",
`in` = Parameter.Location.header,
schema = TypeDefinition.STRING,
required = true
)
)
)
fun Routing.nestedTypeName() = basicGetGenerator<Nested.Response>()
fun Routing.topLevelNullable() = basicGetGenerator<TestResponse?>()
fun Routing.simpleRecursive() = basicGetGenerator<ColumnSchema>()
fun Routing.samePathDifferentMethodsAndAuth() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
authenticate("basic") {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestSimpleRequest>()
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
}
}
}
}
}
}

View File

@ -0,0 +1,351 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.ComplexRequest
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
import io.bkbn.kompendium.core.fixtures.TestRequest
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
import io.bkbn.kompendium.core.metadata.DeleteInfo
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.metadata.HeadInfo
import io.bkbn.kompendium.core.metadata.OptionsInfo
import io.bkbn.kompendium.core.metadata.PatchInfo
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultParams
import io.bkbn.kompendium.core.util.TestModules.defaultPath
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Header
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing
import io.ktor.server.routing.delete
import io.ktor.server.routing.get
import io.ktor.server.routing.head
import io.ktor.server.routing.options
import io.ktor.server.routing.patch
import io.ktor.server.routing.post
import io.ktor.server.routing.put
import io.ktor.server.routing.route
fun Routing.notarizedGet() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description(defaultResponseDescription)
}
summary(defaultPathSummary)
description(defaultPathDescription)
}
}
get {
call.respondText { "hey dude ‼️ congrats on the get request" }
}
}
}
fun Routing.responseHeaders() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description(defaultResponseDescription)
responseHeaders(
mapOf(
HttpHeaders.ETag to Header(
TypeDefinition.STRING,
"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag"
),
HttpHeaders.LastModified to Header(
TypeDefinition.STRING,
"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified"
),
)
)
}
summary(defaultPathSummary)
description(defaultPathDescription)
}
}
get {
call.respondText { "hey dude ‼️ congrats on the get request" }
}
}
}
fun Routing.notarizedPost() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<TestSimpleRequest>()
description("A Test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
post {
call.respondText { "hey dude ‼️ congrats on the post request" }
}
}
}
fun Routing.notarizedPut() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<TestSimpleRequest>()
description("A Test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
put {
call.respondText { "hey dude ‼️ congrats on the post request" }
}
}
}
fun Routing.notarizedDelete() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
delete = DeleteInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseCode(HttpStatusCode.NoContent)
responseType<Unit>()
description(defaultResponseDescription)
}
}
}
}
delete {
call.respond(HttpStatusCode.NoContent)
}
}
fun Routing.notarizedPatch() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
patch = PatchInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description("A Test request")
requestType<TestSimpleRequest>()
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
patch {
call.respond(HttpStatusCode.Created) { TestCreatedResponse(123, "Nice!") }
}
}
}
fun Routing.notarizedHead() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
head = HeadInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description("great!")
responseCode(HttpStatusCode.Created)
responseType<Unit>()
}
}
}
head {
call.respond(HttpStatusCode.OK)
}
}
}
fun Routing.notarizedOptions() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
options = OptionsInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description("nice")
}
}
}
options {
call.respond(HttpStatusCode.NoContent)
}
}
}
fun Routing.complexRequest() {
route(rootPath) {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<ComplexRequest>()
description("A Complex request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
patch {
call.respond(HttpStatusCode.Created, TestCreatedResponse(123, "nice!"))
}
}
}
fun Routing.primitives() {
route(rootPath) {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<Int>()
description("A Test Request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<Boolean>()
description(defaultResponseDescription)
}
}
}
}
}
fun Routing.returnsList() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description("A Successful List-y Endeavor")
responseCode(HttpStatusCode.OK)
responseType<List<TestResponse>>()
}
}
}
}
}
fun Routing.nonRequiredParams() {
route("/optional") {
install(NotarizedRoute()) {
parameters = listOf(
Parameter(
name = "notRequired",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
required = false,
),
Parameter(
name = "required",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING
)
)
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseType<Unit>()
description("Empty")
responseCode(HttpStatusCode.NoContent)
}
}
}
}
}
fun Routing.overrideMediaTypes() {
route("/media_types") {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
mediaTypes("multipart/form-data", "application/json")
requestType<TestRequest>()
description("A cool request")
}
response {
mediaTypes("application/xml")
responseType<TestResponse>()
description("A good response")
responseCode(HttpStatusCode.Created)
}
}
}
}
}
fun Routing.postNoReqBody() {
route("/no_req_body") {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseType<TestResponse>()
description("Cool response")
responseCode(HttpStatusCode.Created)
}
}
}
}
}

View File

@ -0,0 +1,22 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.Barzo
import io.bkbn.kompendium.core.fixtures.ComplexRequest
import io.bkbn.kompendium.core.fixtures.Flibbity
import io.bkbn.kompendium.core.fixtures.FlibbityGibbit
import io.bkbn.kompendium.core.fixtures.Foosy
import io.bkbn.kompendium.core.fixtures.Gibbity
import io.bkbn.kompendium.core.fixtures.MultiNestedGenerics
import io.bkbn.kompendium.core.fixtures.Page
import io.ktor.server.routing.Routing
fun Routing.polymorphicResponse() = basicGetGenerator<FlibbityGibbit>()
fun Routing.polymorphicCollectionResponse() = basicGetGenerator<List<FlibbityGibbit>>()
fun Routing.polymorphicMapResponse() = basicGetGenerator<Map<String, FlibbityGibbit>>()
fun Routing.simpleGenericResponse() = basicGetGenerator<Gibbity<String>>()
fun Routing.gnarlyGenericResponse() = basicGetGenerator<Foosy<Barzo<Int>, String>>()
fun Routing.nestedGenericResponse() = basicGetGenerator<Gibbity<Map<String, String>>>()
fun Routing.genericPolymorphicResponse() = basicGetGenerator<Flibbity<Double>>()
fun Routing.genericPolymorphicResponseMultipleImpls() = basicGetGenerator<Flibbity<FlibbityGibbit>>()
fun Routing.nestedGenericCollection() = basicGetGenerator<Page<Int>>()
fun Routing.nestedGenericMultipleParamsCollection() = basicGetGenerator<MultiNestedGenerics<String, ComplexRequest>>()

View File

@ -0,0 +1,32 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.DefaultField
import io.bkbn.kompendium.core.fixtures.NullableField
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.server.routing.Routing
fun Routing.requiredParams() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
)
fun Routing.nonRequiredParam() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
required = false
)
)
)
fun Routing.defaultField() = basicGetGenerator<DefaultField>()
fun Routing.nullableField() = basicGetGenerator<NullableField>()

View File

@ -0,0 +1,132 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultParams
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Routing
import io.ktor.server.routing.route
import io.ktor.server.routing.param
fun Routing.simplePathParsing() {
route("/this") {
route("/is") {
route("/a") {
route("/complex") {
route("path") {
route("with/an/{id}") {
install(NotarizedRoute()) {
get = GetInfo.builder {
parameters = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
}
}
}
}
fun Routing.rootRoute() {
route(rootPath) {
install(NotarizedRoute()) {
parameters = listOf(defaultParams.last())
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
fun Routing.nestedUnderRoot() {
route("/") {
route("/testerino") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
fun Routing.trailingSlash() {
route("/test") {
route("/") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
fun Routing.paramWrapper() {
route("/test") {
param("a") {
param("b") {
param("c") {
install(NotarizedRoute()) {
parameters = listOf(
Parameter(
name = "test",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING
)
)
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
}
}

View File

@ -1,42 +1,29 @@
package io.bkbn.kompendium.core.util
import io.bkbn.kompendium.core.fixtures.*
import io.bkbn.kompendium.core.metadata.DeleteInfo
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.metadata.HeadInfo
import io.bkbn.kompendium.core.metadata.OptionsInfo
import io.bkbn.kompendium.core.metadata.PatchInfo
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.util.TestModules.defaultPathDescription
import io.bkbn.kompendium.core.util.TestModules.defaultPathSummary
import io.bkbn.kompendium.core.util.TestModules.defaultResponseDescription
import io.bkbn.kompendium.core.util.TestModules.rootPath
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.auth.authenticate
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
import io.ktor.server.routing.Route
import io.ktor.server.routing.Routing
import io.ktor.server.routing.delete
import io.ktor.server.routing.get
import io.ktor.server.routing.head
import io.ktor.server.routing.options
import io.ktor.server.routing.patch
import io.ktor.server.routing.post
import io.ktor.server.routing.put
import io.ktor.server.routing.route
object TestModules {
private const val defaultPath = "/test/{a}"
private const val rootPath = "/"
private const val defaultResponseDescription = "A Successful Endeavor"
private const val defaultRequestDescription = "You gotta send it"
private const val defaultPathSummary = "Great Summary!"
private const val defaultPathDescription = "testing more"
private val defaultParams = listOf(
const val defaultPath = "/test/{a}"
const val rootPath = "/"
const val defaultResponseDescription = "A Successful Endeavor"
const val defaultRequestDescription = "You gotta send it"
const val defaultPathSummary = "Great Summary!"
const val defaultPathDescription = "testing more"
val defaultParams = listOf(
Parameter(
name = "a",
`in` = Parameter.Location.path,
@ -48,610 +35,31 @@ object TestModules {
schema = TypeDefinition.INT
)
)
}
fun Routing.notarizedGet() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description(defaultResponseDescription)
}
summary(defaultPathSummary)
description(defaultPathDescription)
}
}
get {
call.respondText { "hey dude ‼️ congrats on the get request" }
}
}
internal inline fun <reified T> Routing.basicGetGenerator(
params: List<Parameter> = emptyList(),
operationId: String? = null
) {
route(rootPath) {
basicGetGenerator<T>(params, operationId)
}
}
fun Routing.notarizedPost() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<TestSimpleRequest>()
description("A Test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
post {
call.respondText { "hey dude ‼️ congrats on the post request" }
}
}
}
fun Routing.notarizedPut() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<TestSimpleRequest>()
description("A Test request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
put {
call.respondText { "hey dude ‼️ congrats on the post request" }
}
}
}
fun Routing.notarizedDelete() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
delete = DeleteInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseCode(HttpStatusCode.NoContent)
responseType<Unit>()
description(defaultResponseDescription)
}
}
}
}
delete {
call.respond(HttpStatusCode.NoContent)
}
}
fun Routing.notarizedPatch() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
patch = PatchInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description("A Test request")
requestType<TestSimpleRequest>()
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
patch {
call.respond(HttpStatusCode.Created) { TestCreatedResponse(123, "Nice!") }
}
}
}
fun Routing.notarizedHead() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
head = HeadInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description("great!")
responseCode(HttpStatusCode.Created)
responseType<Unit>()
}
}
}
head {
call.respond(HttpStatusCode.OK)
}
}
}
fun Routing.notarizedOptions() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
options = OptionsInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description("nice")
}
}
}
options {
call.respond(HttpStatusCode.NoContent)
}
}
}
fun Routing.complexRequest() {
route(rootPath) {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<ComplexRequest>()
description("A Complex request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<TestCreatedResponse>()
description(defaultResponseDescription)
}
}
}
patch {
call.respond(HttpStatusCode.Created, TestCreatedResponse(123, "nice!"))
}
}
}
fun Routing.primitives() {
route(rootPath) {
install(NotarizedRoute()) {
put = PutInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
requestType<Int>()
description("A Test Request")
}
response {
responseCode(HttpStatusCode.Created)
responseType<Boolean>()
description(defaultResponseDescription)
}
}
}
}
}
fun Routing.returnsList() {
route(defaultPath) {
install(NotarizedRoute()) {
parameters = defaultParams
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description("A Successful List-y Endeavor")
responseCode(HttpStatusCode.OK)
responseType<List<TestResponse>>()
}
}
}
}
}
fun Routing.nonRequiredParams() {
route("/optional") {
install(NotarizedRoute()) {
parameters = listOf(
Parameter(
name = "notRequired",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
required = false,
),
Parameter(
name = "required",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING
)
)
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
responseType<Unit>()
description("Empty")
responseCode(HttpStatusCode.NoContent)
}
}
}
}
}
fun Routing.simplePathParsing() {
route("/this") {
route("/is") {
route("/a") {
route("/complex") {
route("path") {
route("with/an/{id}") {
install(NotarizedRoute()) {
get = GetInfo.builder {
parameters = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
}
}
}
}
fun Routing.rootRoute() {
route(rootPath) {
install(NotarizedRoute()) {
parameters = listOf(defaultParams.last())
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
fun Routing.nestedUnderRoot() {
route("/") {
route("/testerino") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
fun Routing.trailingSlash() {
route("/test") {
route("/") {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
}
}
}
}
}
fun Routing.singleException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<ExceptionResponse>()
}
}
}
}
}
fun Routing.multipleExceptions() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<ExceptionResponse>()
}
canRespond {
description("Access Denied")
responseCode(HttpStatusCode.Forbidden)
responseType<ExceptionResponse>()
}
}
}
}
}
fun Routing.polymorphicException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.InternalServerError)
responseType<FlibbityGibbit>()
}
}
}
}
}
fun Routing.genericException() {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
canRespond {
description("Bad Things Happened")
responseCode(HttpStatusCode.BadRequest)
responseType<Flibbity<String>>()
}
}
}
}
}
fun Routing.reqRespExamples() {
route(rootPath) {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestRequest>()
examples(
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
)
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
examples(
"Testerino" to TestResponse("Heya")
)
}
}
}
}
}
fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING,
examples = mapOf(
"foo" to Parameter.Example("testing")
)
)
)
)
fun Routing.defaultParameter() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING.withDefault("IDK")
)
)
)
fun Routing.requiredParams() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
)
fun Routing.nonRequiredParam() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
required = false
)
)
)
fun Routing.defaultField() = basicGetGenerator<DefaultField>()
fun Routing.nullableField() = basicGetGenerator<NullableField>()
fun Routing.polymorphicResponse() = basicGetGenerator<FlibbityGibbit>()
fun Routing.ignoredFieldsResponse() = basicGetGenerator<TransientObject>()
fun Routing.unbackedFieldsResponse() = basicGetGenerator<UnbakcedObject>()
fun Routing.customFieldNameResponse() = basicGetGenerator<SerialNameObject>()
fun Routing.polymorphicCollectionResponse() = basicGetGenerator<List<FlibbityGibbit>>()
fun Routing.polymorphicMapResponse() = basicGetGenerator<Map<String, FlibbityGibbit>>()
fun Routing.simpleGenericResponse() = basicGetGenerator<Gibbity<String>>()
fun Routing.gnarlyGenericResponse() = basicGetGenerator<Foosy<Barzo<Int>, String>>()
fun Routing.nestedGenericResponse() = basicGetGenerator<Gibbity<Map<String, String>>>()
fun Routing.genericPolymorphicResponse() = basicGetGenerator<Flibbity<Double>>()
fun Routing.genericPolymorphicResponseMultipleImpls() = basicGetGenerator<Flibbity<FlibbityGibbit>>()
fun Routing.nestedGenericCollection() = basicGetGenerator<Page<Int>>()
fun Routing.nestedGenericMultipleParamsCollection() = basicGetGenerator<MultiNestedGenerics<String, ComplexRequest>>()
fun Routing.withOperationId() = basicGetGenerator<TestResponse>(operationId = "getThisDude")
fun Routing.nullableNestedObject() = basicGetGenerator<ProfileUpdateRequest>()
fun Routing.nullableEnumField() = basicGetGenerator<NullableEnum>()
fun Routing.nullableReference() = basicGetGenerator<ManyThings>()
fun Routing.dateTimeString() = basicGetGenerator<DateTimeString>()
fun Routing.headerParameter() = basicGetGenerator<TestResponse>(
params = listOf(
Parameter(
name = "X-User-Email",
`in` = Parameter.Location.header,
schema = TypeDefinition.STRING,
required = true
)
)
)
fun Routing.nestedTypeName() = basicGetGenerator<Nested.Response>()
fun Routing.simpleRecursive() = basicGetGenerator<ColumnSchema>()
fun Routing.defaultAuthConfig() {
authenticate("basic") {
route(rootPath) {
basicGetGenerator<TestResponse>()
}
}
}
fun Routing.customAuthConfig() {
authenticate("auth-oauth-google") {
route(rootPath) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
}
security = mapOf(
"auth-oauth-google" to listOf("read:pets")
)
}
}
}
}
}
fun Routing.multipleAuthStrategies() {
authenticate("jwt", "api-key") {
route(rootPath) {
basicGetGenerator<TestResponse>()
}
}
}
private inline fun <reified T> Routing.basicGetGenerator(
params: List<Parameter> = emptyList(),
operationId: String? = null
) {
route(rootPath) {
basicGetGenerator<T>(params, operationId)
}
}
private inline fun <reified T> Route.basicGetGenerator(
params: List<Parameter> = emptyList(),
operationId: String? = null
) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
operationId?.let { operationId(it) }
parameters = params
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<T>()
}
internal inline fun <reified T> Route.basicGetGenerator(
params: List<Parameter> = emptyList(),
operationId: String? = null
) {
install(NotarizedRoute()) {
get = GetInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
operationId?.let { operationId(it) }
parameters = params
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<T>()
}
}
}

View File

@ -124,15 +124,19 @@
"type": "object",
"properties": {
"enumeration": {
"enum": [
"ONE",
"TWO"
]
"$ref": "#/components/schemas/SimpleEnum"
}
},
"required": [
"enumeration"
]
},
"SimpleEnum": {
"type": "string",
"enum": [
"ONE",
"TWO"
]
}
},
"securitySchemes": {}

View File

@ -91,37 +91,30 @@
"required": []
},
"ProfileMetadataUpdateRequest": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"isPrivate": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
}
]
"type": "object",
"properties": {
"isPrivate": {
"oneOf": [
{
"type": "null"
},
"otherThing": {
"oneOf": [
{
"type": "null"
},
{
"type": "string"
}
]
{
"type": "boolean"
}
},
"required": []
]
},
"otherThing": {
"oneOf": [
{
"type": "null"
},
{
"type": "string"
}
]
}
]
},
"required": []
}
},
"securitySchemes": {}

View File

@ -62,16 +62,21 @@
"type": "null"
},
{
"enum": [
"YES",
"NO"
]
"$ref": "#/components/schemas/TestEnum"
}
]
}
},
"required": []
}
},
"TestEnum":
{
"type": "string",
"enum": [
"YES",
"NO"
]
}
},
"securitySchemes": {}
},

View File

@ -57,10 +57,7 @@
"type": "object",
"properties": {
"enumeration": {
"enum": [
"ONE",
"TWO"
]
"$ref": "#/components/schemas/SimpleEnum"
}
},
"required": [
@ -120,6 +117,13 @@
"required": [
"content"
]
},
"SimpleEnum": {
"type": "string",
"enum": [
"ONE",
"TWO"
]
}
},
"securitySchemes": {}

View File

@ -53,6 +53,14 @@
"webhooks": {},
"components": {
"schemas": {
"ColumnMode": {
"type": "string",
"enum": [
"NULLABLE",
"REQUIRED",
"REPEATED"
]
},
"ColumnSchema": {
"type": "object",
"properties": {
@ -60,11 +68,7 @@
"type": "string"
},
"mode": {
"enum": [
"NULLABLE",
"REQUIRED",
"REPEATED"
]
"$ref": "#/components/schemas/ColumnMode"
},
"name": {
"type": "string"

View File

@ -39,7 +39,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UnbakcedObject"
"$ref": "#/components/schemas/UnbackedObject"
}
}
}
@ -53,7 +53,7 @@
"webhooks": {},
"components": {
"schemas": {
"UnbakcedObject": {
"UnbackedObject": {
"type": "object",
"properties": {
"backed": {

View File

@ -0,0 +1,79 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/TestResponse"
}
]
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,123 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/media_types": {
"put": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "A cool request",
"content": {
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/TestRequest"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestRequest"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "A good response",
"content": {
"application/xml": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
},
"TestRequest": {
"type": "object",
"properties": {
"aaa": {
"items": {
"type": "number",
"format": "int64"
},
"type": "array"
},
"b": {
"type": "number",
"format": "double"
},
"fieldName": {
"$ref": "#/components/schemas/TestNested"
}
},
"required": [
"aaa",
"b",
"fieldName"
]
},
"TestNested": {
"type": "object",
"properties": {
"nesty": {
"type": "string"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,164 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"put": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestSimpleRequest"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestCreatedResponse"
}
}
}
}
},
"deprecated": false,
"security": [
{
"basic": []
}
]
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
},
"TestCreatedResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
},
"id": {
"type": "number",
"format": "int32"
}
},
"required": [
"c",
"id"
]
},
"TestSimpleRequest": {
"type": "object",
"properties": {
"a": {
"type": "string"
},
"b": {
"type": "number",
"format": "int32"
}
},
"required": [
"a",
"b"
]
}
},
"securitySchemes": {
"basic": {
"type": "http",
"scheme": "basic"
}
}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,92 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com/example",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com/example",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,126 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/example": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "A test request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestSimpleRequest-simple"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestCreatedResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestCreatedResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
},
"id": {
"type": "number",
"format": "int32"
}
},
"required": [
"c",
"id"
]
},
"TestSimpleRequest-simple": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "A simple description"
},
"b": {
"type": "number",
"format": "int32",
"deprecated": true
}
},
"required": [
"a",
"b"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,168 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/example": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "A test request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ComplexRequest-simple"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestCreatedResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestCreatedResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
},
"id": {
"type": "number",
"format": "int32"
}
},
"required": [
"c",
"id"
]
},
"ComplexRequest-simple": {
"type": "object",
"properties": {
"amazingField": {
"type": "string"
},
"org": {
"type": "string"
},
"tables": {
"items": {
"$ref": "#/components/schemas/NestedComplexItem-nested"
},
"description": "A nested item",
"type": "array"
}
},
"required": [
"amazingField",
"org",
"tables"
]
},
"NestedComplexItem-nested": {
"type": "object",
"properties": {
"alias": {
"additionalProperties": {
"$ref": "#/components/schemas/CrazyItem"
},
"type": "object"
},
"name": {
"type": "string",
"description": "A nested description"
}
},
"required": [
"alias",
"name"
]
},
"CrazyItem": {
"type": "object",
"properties": {
"enumeration": {
"$ref": "#/components/schemas/SimpleEnum"
}
},
"required": [
"enumeration"
]
},
"SimpleEnum": {
"type": "string",
"enum": [
"ONE",
"TWO"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,183 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/example": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "A test request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MultiNestedGenerics-String-ComplexRequest-simple"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestCreatedResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestCreatedResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
},
"id": {
"type": "number",
"format": "int32"
}
},
"required": [
"c",
"id"
]
},
"MultiNestedGenerics-String-ComplexRequest-simple": {
"type": "object",
"properties": {
"content": {
"additionalProperties": {
"$ref": "#/components/schemas/ComplexRequest-nested"
},
"description": "Getting pretty crazy",
"type": "object"
}
},
"required": [
"content"
]
},
"ComplexRequest-nested": {
"type": "object",
"properties": {
"amazingField": {
"type": "string"
},
"org": {
"type": "string"
},
"tables": {
"items": {
"$ref": "#/components/schemas/NestedComplexItem-nested"
},
"description": "A nested item",
"type": "array"
}
},
"required": [
"amazingField",
"org",
"tables"
]
},
"NestedComplexItem-nested": {
"type": "object",
"properties": {
"alias": {
"additionalProperties": {
"$ref": "#/components/schemas/CrazyItem"
},
"type": "object"
},
"name": {
"type": "string",
"description": "A nested description"
}
},
"required": [
"alias",
"name"
]
},
"CrazyItem": {
"type": "object",
"properties": {
"enumeration": {
"$ref": "#/components/schemas/SimpleEnum"
}
},
"required": [
"enumeration"
]
},
"SimpleEnum": {
"type": "string",
"enum": [
"ONE",
"TWO"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,73 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/enriched": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"201": {
"description": "A good response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse-simple"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse-simple": {
"type": "object",
"properties": {
"c": {
"type": "string",
"description": "A simple description"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,80 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get an int",
"description": "Get an int",
"parameters": [],
"responses": {
"200": {
"description": "An int",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestCreatedResponse-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestCreatedResponse-example": {
"type": "object",
"properties": {
"c": {
"type": "string"
},
"id": {
"type": "number",
"format": "int32",
"multipleOf": 2,
"maximum": 100,
"minimum": 2
}
},
"required": [
"c",
"id"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,76 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get a double",
"description": "Get a double",
"parameters": [],
"responses": {
"200": {
"description": "A double",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DoubleResponse-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"DoubleResponse-example": {
"type": "object",
"properties": {
"payload": {
"type": "number",
"format": "double",
"multipleOf": 2.0,
"maximum": 100.0,
"minimum": 2.0
}
},
"required": [
"payload"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,74 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get a string",
"description": "Get a string with constraints",
"parameters": [],
"responses": {
"200": {
"description": "A string",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestNested-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestNested-example": {
"type": "object",
"properties": {
"nesty": {
"type": "string",
"maxLength": 10,
"minLength": 2
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,73 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get a string",
"description": "This is a description",
"parameters": [],
"responses": {
"200": {
"description": "A string",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestNested-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestNested-example": {
"type": "object",
"properties": {
"nesty": {
"type": "string",
"pattern": "[a-z]+"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,74 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get a string",
"description": "This is a description",
"parameters": [],
"responses": {
"200": {
"description": "A string",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestNested-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestNested-example": {
"type": "object",
"properties": {
"nesty": {
"type": "string",
"contentEncoding": "base64",
"contentMediaType": "image/png"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,103 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Get an array",
"description": "Get an array of strings",
"parameters": [],
"responses": {
"200": {
"description": "An array",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Page-String-example"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"Page-String-example": {
"type": "object",
"properties": {
"content": {
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 2,
"uniqueItems": true,
"type": "array"
},
"number": {
"type": "number",
"format": "int32"
},
"numberOfElements": {
"type": "number",
"format": "int32"
},
"size": {
"type": "number",
"format": "int32"
},
"totalElements": {
"type": "number",
"format": "int64"
},
"totalPages": {
"type": "number",
"format": "int32"
}
},
"required": [
"content",
"number",
"numberOfElements",
"size",
"totalElements",
"totalPages"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,72 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/no_req_body": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"201": {
"description": "Cool response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,110 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test/{a}": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"200": {
"description": "A Successful Endeavor",
"headers": {
"ETag": {
"schema": {
"type": "string"
},
"description": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag",
"required": true,
"deprecated": false
},
"Last-Modified": {
"schema": {
"type": "string"
},
"description": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified",
"required": true,
"deprecated": false
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,91 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/example": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"201": {
"description": "A good response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericObject-TestSimpleRequest-generic"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"GenericObject-TestSimpleRequest-generic": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/TestSimpleRequest-simple",
"description": "A simple description"
}
},
"required": [
"data"
]
},
"TestSimpleRequest-simple": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "A simple description"
},
"b": {
"type": "number",
"format": "int32",
"deprecated": true
}
},
"required": [
"a",
"b"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,82 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test": {
"get": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "test",
"in": "query",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,136 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestRequest"
},
"examples": {
"Testerina": {
"value": {
"fieldName": {
"nesty": "asdf"
},
"b": 1.5,
"aaa": []
}
}
}
}
},
"required": false
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
},
"examples": {
"Testerino": {
"value": {
"c": "Heya"
}
}
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
},
"TestRequest": {
"type": "object",
"properties": {
"aaa": {
"items": {
"type": "number",
"format": "int64"
},
"type": "array"
},
"b": {
"type": "number",
"format": "double"
},
"fieldName": {
"$ref": "#/components/schemas/TestNested"
}
},
"required": [
"aaa",
"b",
"fieldName"
]
},
"TestNested": {
"type": "object",
"properties": {
"nesty": {
"type": "string"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
import io.bkbn.kompendium.core.fixtures.TestSpecs.defaultSpec
import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.JsonSchema
import io.bkbn.kompendium.oas.OpenApiSpec
@ -21,13 +22,14 @@ import io.ktor.serialization.gson.gson
import io.ktor.serialization.jackson.jackson
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.Application
import io.ktor.server.engine.ApplicationEngineEnvironmentBuilder
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.routing.Routing
import io.ktor.server.testing.ApplicationTestBuilder
import io.ktor.server.testing.testApplication
import kotlin.reflect.KType
import kotlinx.serialization.json.Json
import java.io.File
import kotlinx.serialization.json.Json
import kotlin.reflect.KType
object TestHelpers {
private const val OPEN_API_ENDPOINT = "/openapi.json"
@ -43,8 +45,8 @@ object TestHelpers {
* exists as expected, and that the content matches the expected blob found in the specified file
* @param snapshotName The snapshot file to retrieve from the resources folder
*/
private suspend fun ApplicationTestBuilder.compareOpenAPISpec(snapshotName: String) {
val response = client.get(OPEN_API_ENDPOINT)
private suspend fun ApplicationTestBuilder.compareOpenAPISpec(rootPath: String, snapshotName: String) {
val response = client.get("$rootPath$OPEN_API_ENDPOINT")
response shouldHaveStatus HttpStatusCode.OK
response.bodyAsText() shouldNot beBlank()
response.bodyAsText() shouldEqualJson getFileSnapshot(snapshotName)
@ -61,11 +63,36 @@ object TestHelpers {
customTypes: Map<KType, JsonSchema> = emptyMap(),
applicationSetup: Application.() -> Unit = { },
specOverrides: OpenApiSpec.() -> OpenApiSpec = { this },
applicationEnvironmentBuilder: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
routeUnderTest: Routing.() -> Unit
) {
openApiTest(snapshotName, SupportedSerializer.KOTLINX, routeUnderTest, applicationSetup, specOverrides, customTypes)
openApiTest(snapshotName, SupportedSerializer.JACKSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
openApiTest(snapshotName, SupportedSerializer.GSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
openApiTest(
snapshotName,
SupportedSerializer.KOTLINX,
routeUnderTest,
applicationSetup,
specOverrides,
customTypes,
applicationEnvironmentBuilder
)
openApiTest(
snapshotName,
SupportedSerializer.JACKSON,
routeUnderTest,
applicationSetup,
specOverrides,
customTypes,
applicationEnvironmentBuilder
)
openApiTest(
snapshotName,
SupportedSerializer.GSON,
routeUnderTest,
applicationSetup,
specOverrides,
customTypes,
applicationEnvironmentBuilder
)
}
private fun openApiTest(
@ -74,8 +101,10 @@ object TestHelpers {
routeUnderTest: Routing.() -> Unit,
applicationSetup: Application.() -> Unit,
specOverrides: OpenApiSpec.() -> OpenApiSpec,
typeOverrides: Map<KType, JsonSchema> = emptyMap()
typeOverrides: Map<KType, JsonSchema> = emptyMap(),
applicationBuilder: ApplicationEngineEnvironmentBuilder.() -> Unit = {}
) = testApplication {
environment(applicationBuilder)
install(NotarizedApplication()) {
customTypes = typeOverrides
spec = defaultSpec().specOverrides()
@ -102,9 +131,11 @@ object TestHelpers {
}
application(applicationSetup)
routing {
swagger()
redoc()
routeUnderTest()
}
compareOpenAPISpec(snapshotName)
val root = ApplicationEngineEnvironmentBuilder().apply(applicationBuilder).rootPath
compareOpenAPISpec(root, snapshotName)
}
}

View File

@ -12,6 +12,9 @@ import java.time.Instant
@Serializable
data class TestNested(val nesty: String)
@Serializable
data class DoubleResponse(val payload: Double)
@Serializable
data class TestRequest(
val fieldName: TestNested,
@ -163,7 +166,7 @@ data class TransientObject(
)
@Serializable
data class UnbakcedObject(
data class UnbackedObject(
val backed: String
) {
val unbacked: String get() = "unbacked"
@ -176,3 +179,18 @@ data class SerialNameObject(
@SerialName("snake_case_name")
val camelCaseName: String
)
data class GenericObject<T>(
val data: T
)
enum class Color {
RED,
GREEN,
BLUE
}
@Serializable
data class ObjectWithEnum(
val color: Color
)

View File

@ -15,6 +15,15 @@ style:
excludeCommentStatements: true
MagicNumber:
excludes: ['**/kompendium-playground/**/*', '**/test/**/*']
ForbiddenMethodCall:
active: true
formatting:
Indentation:
indentSize: 2
ImportOrdering:
active: false
EnumEntryNameCase:
active: false
naming:
ConstructorParameterNaming:
active: false

View File

@ -1,4 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.2496 5.3C20.3496 4.5 19.2496 4 18.0496 4C16.8496 4 15.6496 4.5 14.8496 5.3L10.3496 9.8L11.7496 11.2L16.2496 6.7C17.2496 5.7 18.8496 5.7 19.8496 6.7C20.8496 7.7 20.8496 9.3 19.8496 10.3L15.3496 14.8L16.7496 16.2L21.2496 11.7C22.1496 10.8 22.5496 9.7 22.5496 8.5C22.5496 7.3 22.1496 6.2 21.2496 5.3Z" fill="#637282"/>
<path d="M8.35 16.7998C7.35 17.7998 5.75 17.7998 4.75 16.7998C3.75 15.7998 3.75 14.1998 4.75 13.1998L9.25 8.6998L7.85 7.2998L3.35 11.7998C1.55 13.5998 1.55 16.3998 3.35 18.1998C4.25 19.0998 5.35 19.4998 6.55 19.4998C7.75 19.4998 8.85 19.0998 9.75 18.1998L14.25 13.6998L12.85 12.2998L8.35 16.7998Z" fill="#637282"/>
</svg>

Before

Width:  |  Height:  |  Size: 754 B

View File

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="-5 -3 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 9l-6 5.25V3.75z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 160 B

View File

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 4H15V16H5V4ZM17 7H19V18V20H17H8V18H17V7Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 215 B

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 9C18 14 14 18 9 18C4 18 0 14 0 9C0 4 4 0 9 0C14 0 18 4 18 9ZM14.2 6.2L12.8 4.8L7.5 10.1L5.3 7.8L3.8 9.2L7.5 13L14.2 6.2Z" fill="#4DBB5F"/>
</svg>

Before

Width:  |  Height:  |  Size: 258 B

View File

@ -1,3 +0,0 @@
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0H2.3949L4.84076 2.44586L0 7.28662L0.713376 8L5.55414 3.15924L8 5.6051V0Z" fill="#637282"/>
</svg>

Before

Width:  |  Height:  |  Size: 206 B

View File

@ -1,4 +0,0 @@
<svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.3337 9.66683H0.666992L6.00033 3.66683L11.3337 9.66683Z" fill="#637282"/>
<path d="M0.666992 0.333496H11.3337V1.66683H0.666992V0.333496Z" fill="#637282"/>
</svg>

Before

Width:  |  Height:  |  Size: 277 B

View File

@ -1,10 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M64 64H0V0H64L31.3373 31.5369L64 64Z" fill="url(#paint0_radial)"/>
<defs>
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(61.8732 2.63097) scale(73.3111)">
<stop offset="0.00343514" stop-color="#EF4857"/>
<stop offset="0.4689" stop-color="#D211EC"/>
<stop offset="1" stop-color="#7F52FF"/>
</radialGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 558 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<path fill="white" fill-rule="evenodd" clip-rule="evenodd"
d="M0 9a9 9 0 1018 0A9 9 0 000 9zm16 0a7 7 0 01-7 7V2a7 7 0 017 7z" transform="translate(3, 3)"></path>
</svg>

Before

Width:  |  Height:  |  Size: 247 B

View File

@ -1,136 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>All modules</title>
<link href="images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "";</script> <script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<script type="text/javascript" src="scripts/sourceset_dependencies.js" async="async"></script><link href="styles/style.css" rel="Stylesheet"><link href="styles/jetbrains-mono.css" rel="Stylesheet"><link href="styles/main.css" rel="Stylesheet"><link href="styles/prism.css" rel="Stylesheet"><link href="styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="scripts/clipboard.js" async="async"></script><script type="text/javascript" src="scripts/navigation-loader.js" async="async"></script><script type="text/javascript" src="scripts/platform-content-handler.js" async="async"></script><script type="text/javascript" src="scripts/main.js" defer="defer"></script><script type="text/javascript" src="scripts/prism.js" async="async"></script><link href="styles/multimodule.css" rel="Stylesheet"> </head>
<body>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="index.html">kompendium</a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageIds="kompendium::.ext/allModules///PointingToDeclaration//0">
<div class="breadcrumbs"></div>
<div class="cover ">
<div class="cover ">
<h1 class="">Kompendium</h1>
<p class="paragraph">Welcome to Kompendium, the straight-forward, minimally-invasive OpenAPI generator for Ktor. </p>
<h2 class=""> How to install</h2>
<p class="paragraph">Kompendium publishes all releases to Maven Central. As such, using the release versions of <code class="lang-kotlin">Kompendium</code> is as simple as declaring it as an implementation dependency in your <code class="lang-kotlin">build.gradle.kts</code></p>
<div class="sample-container">
<pre><code class="block lang-kotlin" theme="idea">repositories {<br> mavenCentral()<br>}<br><br>dependencies {<br> implementation(&quot;io.bkbn:kompendium-core:latest.release&quot;)<br>}</code></pre>
<span class="top-right-position"><span class="copy-icon"></span>
<div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div>
</span></div>
<p class="paragraph">In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge to <code class="lang-kotlin">main</code>. These can be consumed by adding the repository to your gradle build file. Instructions can be found <a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package">here</a></p>
<h2 class=""> Setting up the Kompendium Plugin</h2>
<p class="paragraph">Kompendium is instantiated as a Ktor Feature/Plugin. It can be added to your API as follows</p>
<div class="sample-container">
<pre><code class="block lang-kotlin" theme="idea">private fun Application.mainModule() {<br> // Installs the Kompendium Plugin and sets up baseline server metadata<br> install(Kompendium) {<br> spec = OpenApiSpec(/*..*/)<br> }<br> // ...<br>}</code></pre>
<span class="top-right-position"><span class="copy-icon"></span>
<div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div>
</span></div>
<h2 class=""> Notarization</h2>
<p class="paragraph">The concept of notarizing routes / exceptions / etc. is central to Kompendium. More details on <i>how</i> to notarize your API can be found in the kompendium-core module.</p>
</div>
<h2 class="">All modules:</h2>
<div class="table"><a data-name="1162350513%2FMain%2F0" anchor-label="kompendium-annotations" id="1162350513%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-annotations/index.html">kompendium-annotations</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1162350513%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">This module houses all annotations that Kompendium uses to provide key metadata when performing reflective analysis. </p>
</span></div>
</div>
</div>
<a data-name="1574642149%2FMain%2F0" anchor-label="kompendium-auth" id="1574642149%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-auth/index.html">kompendium-auth</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1574642149%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">This module is responsible for providing wrappers around ktor-auth configuration blocks, allowing users to document their API authentication with minimal modifications to their existing configuration.</p>
</span></div>
</div>
</div>
<a data-name="-1821989938%2FMain%2F0" anchor-label="kompendium-core" id="-1821989938%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-core/index.html">kompendium-core</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1821989938%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">This is where the magic happens. This module houses all the reflective goodness that powers Kompendium.</p>
</span></div>
</div>
</div>
<a data-name="-960478793%2FMain%2F0" anchor-label="kompendium-locations" id="-960478793%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-locations/index.html">kompendium-locations</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-960478793%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">Adds support for Ktor <a href="https://ktor.io/docs/locations.html">Locations</a> API. Any notarized location <i>must</i> be provided with a <code class="lang-kotlin">TParam</code> annotated with <code class="lang-kotlin">@Location</code>. Nested Locations are supported</p>
</span></div>
</div>
</div>
<a data-name="926400660%2FMain%2F0" anchor-label="kompendium-oas" id="926400660%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-oas/index.html">kompendium-oas</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="926400660%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">This module contains the models that represent the Open Api Specification 3.0 (OAS).</p>
</span></div>
</div>
</div>
<a data-name="-1622380618%2FMain%2F0" anchor-label="kompendium-swagger-ui" id="-1622380618%2FMain%2F0" data-filterable-set=""></a>
<div class="table-row">
<div class="main-subrow ">
<div class="w-100"><span class="inline-flex">
<div><a href="kompendium-swagger-ui/index.html">kompendium-swagger-ui</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1622380618%2FMain%2F0"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div><span class="brief-comment">
<p class="paragraph">Contains the code necessary to launch <code class="lang-kotlin">swagger</code> as your documentation frontend.</p>
</span></div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body>
</html>

View File

@ -1,73 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>kompendium-annotations</title>
</head><body><link href="../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../";</script>
<script type="text/javascript" src="../scripts/sourceset_dependencies.js" async></script><link href="../styles/style.css" rel="Stylesheet"><link href="../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../styles/main.css" rel="Stylesheet"><link href="../styles/prism.css" rel="Stylesheet"><link href="../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../scripts/clipboard.js" async></script><script type="text/javascript" src="../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../scripts/main.js" defer></script><script type="text/javascript" src="../scripts/prism.js" async></script><link href="../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::////PointingToDeclaration//-1155457116">
<div class="breadcrumbs"></div>
<div class="cover ">
<h1 class="cover"><span><span>kompendium-annotations</span></span></h1>
<div class="platform-hinted UnderCoverText" data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><p class="paragraph">This module houses all annotations that Kompendium uses to provide key metadata when performing reflective analysis. </p><p class="paragraph">It is separated from core predominantly to allow for potential future integrations with <a href="https://github.com/google/ksp">Kotlin Symbol Processing</a></p></div></div>
</div>
<h2 class="">Packages</h2>
<div class="table"><a data-name="-1446117290%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations" id="-1446117290%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div>
<div class="main-subrow ">
<div class=""><span class="inline-flex">
<div><a href="io.bkbn.kompendium.annotations/index.html">io.bkbn.kompendium.annotations</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1446117290%2FPackages%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div class="pull-right"></div>
</div>
<div><span class="brief-comment"><a data-name="-1446117290%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations" id="-1446117290%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<p class="paragraph">Contains all annotations used by Kompendium</p>
</span></div>
</div>
</div>
<a data-name="1495666105%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations.constraint" id="1495666105%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div>
<div class="main-subrow ">
<div class=""><span class="inline-flex">
<div><a href="io.bkbn.kompendium.annotations.constraint/index.html">io.bkbn.kompendium.annotations.constraint</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1495666105%2FPackages%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div class="pull-right"></div>
</div>
<div><span class="brief-comment"><a data-name="1495666105%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations.constraint" id="1495666105%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<p class="paragraph">Annotations that place bespoke constraints on individual fields of your API schemas.</p>
</span></div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>Format</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-format/-format.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format/Format/#kotlin.String/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a>/<a href="-format.html">Format</a></div>
<div class="cover ">
<h1 class="cover"><span><span>Format</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-format.html"><span class="token function">Format</span></a><span class="token punctuation">(</span>format<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>format</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-format/format.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format/format/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a>/<a href="format.html">format</a></div>
<div class="cover ">
<h1 class="cover"><span><span>format</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="format.html">format</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>Format</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-format/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a></div>
<div class="cover ">
<h1 class="cover"><span><span>Format</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">Format</a><span class="token punctuation">(</span>format<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-1740241114%2FProperties%2F-1155457116" anchor-label="format" id="-1740241114%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="format.html">format</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1740241114%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-1740241114%2FProperties%2F-1155457116" anchor-label="format" id="-1740241114%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="format.html">format</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxItems</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-items/-max-items.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxItems/MaxItems/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxItems</a>/<a href="-max-items.html">MaxItems</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Items</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-max-items.html"><span class="token function">MaxItems</span></a><span class="token punctuation">(</span>items<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxItems</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-items/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxItems///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxItems</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Items</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">MaxItems</a><span class="token punctuation">(</span>items<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-1673031400%2FProperties%2F-1155457116" anchor-label="items" id="-1673031400%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="items.html">items</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1673031400%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-1673031400%2FProperties%2F-1155457116" anchor-label="items" id="-1673031400%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="items.html">items</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>items</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-items/items.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxItems/items/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxItems</a>/<a href="items.html">items</a></div>
<div class="cover ">
<h1 class="cover"><span><span>items</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="items.html">items</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxLength</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-length/-max-length.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxLength/MaxLength/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxLength</a>/<a href="-max-length.html">MaxLength</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Length</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-max-length.html"><span class="token function">MaxLength</span></a><span class="token punctuation">(</span>length<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxLength</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-length/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxLength///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxLength</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Length</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">MaxLength</a><span class="token punctuation">(</span>length<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-1027251622%2FProperties%2F-1155457116" anchor-label="length" id="-1027251622%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="length.html">length</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1027251622%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-1027251622%2FProperties%2F-1155457116" anchor-label="length" id="-1027251622%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="length.html">length</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>length</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-length/length.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxLength/length/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxLength</a>/<a href="length.html">length</a></div>
<div class="cover ">
<h1 class="cover"><span><span>length</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="length.html">length</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxProperties</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-properties/-max-properties.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxProperties/MaxProperties/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxProperties</a>/<a href="-max-properties.html">MaxProperties</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Properties</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-max-properties.html"><span class="token function">MaxProperties</span></a><span class="token punctuation">(</span>properties<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MaxProperties</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-properties/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxProperties///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxProperties</a></div>
<div class="cover ">
<h1 class="cover"><span>Max</span><wbr><span><span>Properties</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">MaxProperties</a><span class="token punctuation">(</span>properties<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="1576947962%2FProperties%2F-1155457116" anchor-label="properties" id="1576947962%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="properties.html">properties</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1576947962%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="1576947962%2FProperties%2F-1155457116" anchor-label="properties" id="1576947962%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="properties.html">properties</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>properties</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-max-properties/properties.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MaxProperties/properties/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MaxProperties</a>/<a href="properties.html">properties</a></div>
<div class="cover ">
<h1 class="cover"><span><span>properties</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="properties.html">properties</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>Maximum</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-maximum/-maximum.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Maximum/Maximum/#kotlin.String#kotlin.Boolean/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Maximum</a>/<a href="-maximum.html">Maximum</a></div>
<div class="cover ">
<h1 class="cover"><span><span>Maximum</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-maximum.html"><span class="token function">Maximum</span></a><span class="token punctuation">(</span>max<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">, </span>exclusive<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a><span class="token operator"> = </span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>exclusive</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-maximum/exclusive.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Maximum/exclusive/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Maximum</a>/<a href="exclusive.html">exclusive</a></div>
<div class="cover ">
<h1 class="cover"><span><span>exclusive</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="exclusive.html">exclusive</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a><span class="token operator"> = </span><span class="token boolean">false</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,76 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>Maximum</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-maximum/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Maximum///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Maximum</a></div>
<div class="cover ">
<h1 class="cover"><span><span>Maximum</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">Maximum</a><span class="token punctuation">(</span>max<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">, </span>exclusive<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-445488442%2FProperties%2F-1155457116" anchor-label="exclusive" id="-445488442%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="exclusive.html">exclusive</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-445488442%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-445488442%2FProperties%2F-1155457116" anchor-label="exclusive" id="-445488442%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="exclusive.html">exclusive</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html">Boolean</a><span class="token operator"> = </span><span class="token boolean">false</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
<a data-name="-947044352%2FProperties%2F-1155457116" anchor-label="max" id="-947044352%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="max.html">max</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-947044352%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-947044352%2FProperties%2F-1155457116" anchor-label="max" id="-947044352%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="max.html">max</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>max</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-maximum/max.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Maximum/max/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Maximum</a>/<a href="max.html">max</a></div>
<div class="cover ">
<h1 class="cover"><span><span>max</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="max.html">max</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MinItems</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-items/-min-items.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinItems/MinItems/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinItems</a>/<a href="-min-items.html">MinItems</a></div>
<div class="cover ">
<h1 class="cover"><span>Min</span><wbr><span><span>Items</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-min-items.html"><span class="token function">MinItems</span></a><span class="token punctuation">(</span>items<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MinItems</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-items/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinItems///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinItems</a></div>
<div class="cover ">
<h1 class="cover"><span>Min</span><wbr><span><span>Items</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">MinItems</a><span class="token punctuation">(</span>items<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-498191610%2FProperties%2F-1155457116" anchor-label="items" id="-498191610%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="items.html">items</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-498191610%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-498191610%2FProperties%2F-1155457116" anchor-label="items" id="-498191610%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="items.html">items</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>items</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-items/items.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinItems/items/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinItems</a>/<a href="items.html">items</a></div>
<div class="cover ">
<h1 class="cover"><span><span>items</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="items.html">items</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MinLength</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-length/-min-length.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinLength/MinLength/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinLength</a>/<a href="-min-length.html">MinLength</a></div>
<div class="cover ">
<h1 class="cover"><span>Min</span><wbr><span><span>Length</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-min-length.html"><span class="token function">MinLength</span></a><span class="token punctuation">(</span>length<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,61 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MinLength</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-length/index.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinLength///PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinLength</a></div>
<div class="cover ">
<h1 class="cover"><span>Min</span><wbr><span><span>Length</span></span></h1>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">MinLength</a><span class="token punctuation">(</span>length<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="tabbedcontent">
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
<div class="tabs-section-body">
<h2 class="">Properties</h2>
<div class="table" data-togglable="Properties"><a data-name="-1582612280%2FProperties%2F-1155457116" anchor-label="length" id="-1582612280%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
<div class="main-subrow keyValue ">
<div class=""><span class="inline-flex">
<div><a href="length.html">length</a></div>
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1582612280%2FProperties%2F-1155457116"></span>
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
</span></span></div>
<div>
<div class="title">
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-1582612280%2FProperties%2F-1155457116" anchor-label="length" id="-1582612280%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="length.html">length</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>length</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-length/length.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinLength/length/#/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinLength</a>/<a href="length.html">length</a></div>
<div class="cover ">
<h1 class="cover"><span><span>length</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="length.html">length</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

View File

@ -1,39 +0,0 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
<title>MinProperties</title>
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
const savedDarkMode = storage ? JSON.parse(storage) : false
if(savedDarkMode === true){
document.getElementsByTagName("html")[0].classList.add("theme-dark")
}</script>
<div class="navigation-wrapper" id="navigation-wrapper">
<div id="leftToggler"><span class="icon-toggler"></span></div>
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
<div><dokka-template-command data="{&quot;@class&quot;:&quot;org.jetbrains.dokka.base.templating.ReplaceVersionsCommand&quot;,&quot;location&quot;:&quot;io.bkbn.kompendium.annotations.constraint/-min-properties/-min-properties.html&quot;}">2.0.1</dokka-template-command></div>
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
<div id="searchBar"></div>
</div>
</div>
<div id="container">
<div id="leftColumn">
<div id="sideMenu"></div>
</div>
<div id="main">
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/MinProperties/MinProperties/#kotlin.Int/PointingToDeclaration//-1155457116">
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">MinProperties</a>/<a href="-min-properties.html">MinProperties</a></div>
<div class="cover ">
<h1 class="cover"><span>Min</span><wbr><span><span>Properties</span></span></h1>
</div>
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-min-properties.html"><span class="token function">MinProperties</span></a><span class="token punctuation">(</span>properties<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html">Int</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
</div>
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
</div>
</div>
</body></html>

Some files were not shown because too many files have changed in this diff Show More