Skip to content

Commit af2e830

Browse files
authored
Initial implementations for code generation (#13)
* - #1 basic lists implementation - #2 Basic maps implementation - #7 quick implementation of brand typing for value classes * map tests #2 #3 * generate implementations and test improvements - add TOC to all docs - Map generation for complex and enum keys #2 #3 - update test template, for easier comparison after failures - tests for #10 * suppress warning in tests * `export enum` -> valid for .d.ts files * test for ignoring fields with @transient, and if an interface has no properties, don't have a blank line between {} * test for objects, and fix test expectations in polymophic classes, so they extend parent interfaces * try fixing knit gradle task warning * - replace jacoco with kotlinx.kover - clean up root build.gradle.kts - change package name of example code (so the coverage report can be package filtered, if needed) - create a kotlin.multiplatform convention plugin * bump gradle version * set max line length to 100 * mucking about with plugins and compilation processors * tidy up gradle config * refactor kxs generator * update tests, and add some more * major refactor to get things more like a library, and steps towards handing open/closed polymorphism * sealed classes working! - 'export' all TS Declarations - ignore blank lines in knit tests - * some Sealed interfaces and type ref improvements * temp fix for open poly classes * normalize knit code comparisons * update tests after temp fix for open poly classes * update sealed poly tests * rm migrated code * rm unneeded TsTypeRef.Unknown * rename TsType to TsTypeAlias, and update docs in tsElements.kt * code cleanup, documentation * docs, more Maps tests/examples/workarounds * update gitattributes * rename 'knit' subproject to 'code' * prep for jitpack * docs update * improve recursive descriptor extraction * version bum git-versioning plugin * better helper function for mutable maps with default puts * simplify the API * code tidup * formatting, code tidying * kmm gradle config tidy up * bump gradle version * add jitpack button * fix maven publishing * update project name & group * disable reflekt dependency
1 parent 866b9a5 commit af2e830

File tree

97 files changed

+3905
-884
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+3905
-884
lines changed

.editorconfig

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ indent_size = 2
77
indent_style = space
88
insert_final_newline = true
99
trim_trailing_whitespace = true
10+
max_line_length = 100

.gitattributes

+57-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,60 @@
1-
* text eol=lf
1+
# Common settings that generally should always be used with your language specific settings
22

3-
*.java text diff=java
4-
*.kt text diff=java
5-
*.kts text diff=java
3+
# Auto detect text files and perform LF normalization
4+
* text eol=lf
65

6+
# The above will handle all files NOT found below
7+
8+
*.md text
9+
*.tex text diff=tex
10+
*.adoc text
11+
*.textile text
12+
*.mustache text
13+
*.csv text
14+
*.tab text
15+
*.tsv text
16+
*.txt text
17+
*.sql text
18+
19+
# Graphics
20+
*.png binary
21+
*.jpg binary
22+
*.jpeg binary
23+
*.gif binary
24+
*.tif binary
25+
*.tiff binary
26+
*.ico binary
27+
*.eps binary
28+
# SVG treated as an asset (binary) by default.
29+
*.svg text
30+
31+
# Properties
32+
*.json text
33+
*.toml text
34+
*.xml text
35+
*.yaml text
36+
*.yml text
37+
38+
# Scripts
39+
*.bash text eol=lf
40+
*.fish text eol=lf
41+
*.sh text eol=lf
742
# These are explicitly windows files and should use crlf
8-
*.bat text eol=crlf
43+
*.bat text eol=crlf
44+
*.cmd text eol=crlf
45+
*.ps1 text eol=crlf
46+
47+
48+
# JVM sources
49+
*.java text diff=java
50+
*.gradle text diff=java
51+
*.kt text diff=java
52+
*.kts text diff=java
53+
54+
# Text files where line endings should be preserved
55+
*.patch -text
56+
57+
#
58+
# Exclude files from exporting
59+
.gitattributes export-ignore
60+
.gitignore export-ignore

README.md

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
[![](https://jitpack.io/v/adamko-dev/kotlinx-serialization-typescript-generator.svg)](https://jitpack.io/#adamko-dev/kotlinx-serialization-typescript-generator)
2+
13
# Kotlinx Serialization TypeScript Generator
24

3-
Create TypeScript interfaces from Kotlin classes
5+
Create TypeScript interfaces from Kotlinx Serialization classes.
46

57
```kotlin
68
@Serializable
@@ -10,7 +12,7 @@ data class PlayerDetails(
1012
)
1113

1214
println(
13-
KxsTsGenerator().generate(Color.serializer().descriptor)
15+
KxsTsGenerator().generate(Color.serializer())
1416
)
1517
```
1618

@@ -21,4 +23,30 @@ interface PlayerDetails {
2123
}
2224
```
2325

26+
The aim is to create TypeScript interfaces that can accurately produce Kotlinx Serialization
27+
compatible JSON.
28+
29+
The Kotlinx Serialization API should be used to generate TypeScript. The
30+
[`SerialDescriptor`s](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-serial-descriptor/index.html)
31+
are flexible and comprehensive enough to allow for accurate TypeScript code, without any deviation.
32+
2433
See [the docs](./docs) for working examples.
34+
35+
## Status
36+
37+
This is a proof-of-concept.
38+
39+
| | Status | Notes |
40+
|---------------------------------------|----------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
41+
| Kotlin multiplatform || The codebase is multiplatform, but only JVM has been tested |
42+
| `@SerialName` | ✅/⚠ | The serial name is directly converted and might produce invalid TypeScript |
43+
| Basic classes |[example](./docs/basic-classes.md) | |
44+
| Nullable and default-value properties |[example](./docs/default-values.md) | |
45+
| Value classes |[example](./docs/value-classes.md) | |
46+
| Enums |[example](./docs/enums.md) | |
47+
| Lists |[example](./docs/lists.md) | |
48+
| Maps | ✅/⚠ [example](./docs/maps.md) | Maps with complex keys are converted to an ES6 Map, [see](./docs/maps.md#maps-with-complex-keys) |
49+
| Polymorphism - Sealed classes | ✅/⚠ [example](./docs/polymorphism.md#sealed-classes) | Nested sealed classes are ignored, [see](./docs/polymorphism.md#nested-sealed-classes) |
50+
| Polymorphism - Open classes |[example](./docs/abstract-classes.md) | Not implemented. Converted to `type MyClass = any` |
51+
| `@JsonClassDiscriminator` || Not implemented |
52+
| Edge cases - circular dependencies |[example](./docs/edgecases.md) | |

build.gradle.kts

+4-42
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import buildsrc.config.excludeGeneratedGradleDsl
22

33
plugins {
44
base
5-
id("me.qoomon.git-versioning") version "5.1.2"
65
idea
7-
buildsrc.convention.`kotlin-jvm`
8-
kotlin("plugin.serialization")
9-
id("org.jetbrains.kotlinx.knit")
6+
id("me.qoomon.git-versioning") version "5.1.5"
7+
id("org.jetbrains.kotlinx.kover")
108
}
119

1210

13-
project.group = "dev.adamko"
11+
project.group = "dev.adamko.kxtsgen"
1412
project.version = "0.0.0-SNAPSHOT"
1513
gitVersioning.apply {
1614
refs {
@@ -24,7 +22,7 @@ gitVersioning.apply {
2422

2523

2624
tasks.wrapper {
27-
gradleVersion = "7.4"
25+
gradleVersion = "7.4.2"
2826
distributionType = Wrapper.DistributionType.ALL
2927
}
3028

@@ -40,39 +38,3 @@ idea {
4038
)
4139
}
4240
}
43-
44-
45-
val kotlinxSerializationVersion = "1.3.2"
46-
47-
dependencies {
48-
implementation(projects.modules.kxsTsGenCore)
49-
50-
implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:${kotlinxSerializationVersion}"))
51-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core")
52-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json")
53-
54-
testImplementation(kotlin("test"))
55-
56-
testImplementation("org.jetbrains.kotlinx:kotlinx-knit-test:0.3.0")
57-
}
58-
59-
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
60-
kotlinOptions.freeCompilerArgs += listOf(
61-
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
62-
)
63-
}
64-
65-
sourceSets.test {
66-
java.srcDirs("docs/example", "docs/test")
67-
}
68-
69-
//knit {
70-
// rootDir = layout.projectDirectory.asFile
71-
// files = rootProject.fileTree("docs")
72-
//}
73-
74-
tasks.test {
75-
dependsOn(tasks.knit)
76-
}
77-
78-
tasks.compileKotlin { mustRunAfter(tasks.knit) }

buildSrc/build.gradle.kts

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ plugins {
1010

1111
object Versions {
1212
const val jvmTarget = "11"
13-
const val kotlinTarget = "1.6"
1413
const val kotlin = "1.6.10"
15-
const val ksp = "1.6.10-1.0.2"
16-
const val kotlinxSerializationVersion = "1.3.2"
14+
const val kotlinTarget = "1.6"
1715
const val kotlinxKnit = "0.3.0"
16+
const val kotlinxKover = "0.5.0"
17+
const val kotlinxSerialization = "1.3.2"
18+
const val ksp = "1.6.10-1.0.4"
1819

1920
const val kotest = "5.1.0"
2021
}
@@ -28,11 +29,16 @@ dependencies {
2829

2930
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:${Versions.ksp}")
3031

31-
implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:${Versions.kotlinxSerializationVersion}"))
32+
implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:${Versions.kotlinxSerialization}"))
3233

3334
implementation("io.kotest:kotest-framework-multiplatform-plugin-gradle:${Versions.kotest}")
3435

3536
implementation("org.jetbrains.kotlinx:kotlinx-knit:${Versions.kotlinxKnit}")
37+
implementation("org.jetbrains.kotlinx:kover:${Versions.kotlinxKover}")
38+
39+
// implementation("org.jetbrains.reflekt:gradle-plugin:1.6.10-1-SNAPSHOT") {
40+
// isChanging = true
41+
// }
3642
}
3743

3844

buildSrc/repositories.settings.gradle.kts

+15
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,35 @@
22
dependencyResolutionManagement {
33

44
repositories {
5+
myMavenLocal()
56
mavenCentral()
67
jitpack()
78
gradlePluginPortal()
89
}
910

1011
pluginManagement {
1112
repositories {
13+
myMavenLocal()
1214
jitpack()
1315
gradlePluginPortal()
1416
mavenCentral()
1517
}
1618
}
1719
}
1820

21+
1922
fun RepositoryHandler.jitpack() {
2023
maven("https://jitpack.io")
2124
}
25+
26+
27+
fun RepositoryHandler.myMavenLocal(enabled: Boolean = false) {
28+
if (enabled) {
29+
logger.lifecycle("Maven local is enabled")
30+
mavenLocal {
31+
content {
32+
// includeGroup("org.jetbrains.reflekt")
33+
}
34+
}
35+
}
36+
}

buildSrc/src/main/kotlin/buildsrc/config/gradle.kt

+7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package buildsrc.config
22

3+
import org.gradle.api.GradleException
4+
import org.gradle.api.Project
35
import org.gradle.api.file.ProjectLayout
6+
import org.gradle.kotlin.dsl.findByType
47
import org.gradle.plugins.ide.idea.model.IdeaModule
8+
import org.jetbrains.kotlin.gradle.dsl.KotlinTargetContainerWithPresetFunctions
9+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTests
10+
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
11+
512

613
/** exclude generated Gradle code, so it doesn't clog up search results */
714
fun IdeaModule.excludeGeneratedGradleDsl(layout: ProjectLayout) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package buildsrc.config
2+
3+
import org.gradle.api.GradleException
4+
import org.gradle.api.Project
5+
import org.gradle.kotlin.dsl.findByType
6+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
7+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTests
8+
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
9+
10+
11+
/**
12+
* `kotlin-js` adds a directory in the root-dir for the Yarn lock.
13+
* That's a bit annoying. It's a little neater if it's in the
14+
* gradle dir, next to the version-catalog.
15+
*/
16+
fun Project.relocateKotlinJsStore() {
17+
18+
afterEvaluate {
19+
rootProject.extensions.findByType<YarnRootExtension>()?.apply {
20+
lockFileDirectory = project.rootDir.resolve("gradle/kotlin-js-store")
21+
}
22+
}
23+
24+
}
25+
26+
27+
fun KotlinMultiplatformExtension.currentHostTarget(
28+
targetName: String = "native",
29+
configure: KotlinNativeTargetWithHostTests.() -> Unit,
30+
): KotlinNativeTargetWithHostTests {
31+
val hostOs = System.getProperty("os.name")
32+
val hostTarget = when {
33+
hostOs == "Mac OS X" -> macosX64(targetName)
34+
hostOs == "Linux" -> linuxX64(targetName)
35+
hostOs.startsWith("Windows") -> mingwX64(targetName)
36+
else -> throw GradleException("Preset for host OS '$hostOs' is undefined")
37+
}
38+
39+
println("Current host target ${hostTarget.targetName}/${hostTarget.preset?.name}")
40+
hostTarget.configure()
41+
return hostTarget
42+
}
43+
44+
45+
fun KotlinMultiplatformExtension.publicationsFromMainHost(): List<String> {
46+
return listOf(jvm(), js()).map { it.name } + "kotlinMultiplatform"
47+
}

buildSrc/src/main/kotlin/buildsrc/convention/jacoco-aggregation.gradle.kts

-28
This file was deleted.

buildSrc/src/main/kotlin/buildsrc/convention/kotlin-jvm.gradle.kts

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package buildsrc.convention
22

33
import org.gradle.kotlin.dsl.`java-library`
44
import org.gradle.kotlin.dsl.dependencies
5-
import org.gradle.kotlin.dsl.jacoco
65
import org.gradle.kotlin.dsl.kotlin
76
import org.gradle.kotlin.dsl.withType
87
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -11,11 +10,10 @@ plugins {
1110
id("buildsrc.convention.subproject")
1211
kotlin("jvm")
1312
`java-library`
14-
jacoco
1513
}
1614

1715
dependencies {
18-
testImplementation(platform("io.kotest:kotest-bom:5.1.0"))
16+
testImplementation(platform("io.kotest:kotest-bom:5.2.1"))
1917
testImplementation("io.kotest:kotest-runner-junit5")
2018
testImplementation("io.kotest:kotest-assertions-core")
2119
testImplementation("io.kotest:kotest-property")
@@ -33,7 +31,7 @@ java {
3331
withSourcesJar()
3432
}
3533

36-
tasks.withType<KotlinCompile>().configureEach {
34+
tasks.withType<KotlinCompile> {
3735
kotlinOptions {
3836
jvmTarget = "11"
3937
apiVersion = "1.6"
@@ -53,5 +51,4 @@ tasks.compileTestKotlin {
5351

5452
tasks.test {
5553
useJUnitPlatform()
56-
finalizedBy(tasks.jacocoTestReport)
5754
}

0 commit comments

Comments
 (0)