Skip to content

Initial implementations for code generation #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Apr 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a651496
- #1 basic lists implementation
aSemy Mar 4, 2022
63ec8d0
map tests #2 #3
aSemy Mar 4, 2022
239c1b8
generate implementations and test improvements
aSemy Mar 4, 2022
dbdca26
suppress warning in tests
aSemy Mar 4, 2022
ec52c3f
`export enum` -> valid for .d.ts files
aSemy Mar 4, 2022
220ba8e
test for ignoring fields with @Transient, and if an interface has no …
aSemy Mar 4, 2022
301cf88
test for objects, and fix test expectations in polymophic classes, so…
aSemy Mar 4, 2022
5155ffe
try fixing knit gradle task warning
aSemy Mar 4, 2022
d23c4e1
- replace jacoco with kotlinx.kover
aSemy Mar 4, 2022
29f40b0
bump gradle version
aSemy Mar 26, 2022
995179f
set max line length to 100
aSemy Mar 26, 2022
3c47a24
mucking about with plugins and compilation processors
aSemy Mar 26, 2022
1ae7c9a
tidy up gradle config
aSemy Mar 26, 2022
4e3a6f6
refactor kxs generator
aSemy Mar 26, 2022
7924e2a
update tests, and add some more
aSemy Mar 26, 2022
71bde73
major refactor to get things more like a library, and steps towards h…
aSemy Apr 1, 2022
439c075
sealed classes working!
aSemy Apr 2, 2022
9faff4a
some Sealed interfaces and type ref improvements
aSemy Apr 2, 2022
52e0e25
temp fix for open poly classes
aSemy Apr 3, 2022
ed28d6d
normalize knit code comparisons
aSemy Apr 3, 2022
44d01c1
update tests after temp fix for open poly classes
aSemy Apr 3, 2022
053ff3e
update sealed poly tests
aSemy Apr 3, 2022
ac2cafa
rm migrated code
aSemy Apr 3, 2022
ee2f3d1
rm unneeded TsTypeRef.Unknown
aSemy Apr 3, 2022
5331cd4
rename TsType to TsTypeAlias, and update docs in tsElements.kt
aSemy Apr 3, 2022
dc1fd81
code cleanup, documentation
aSemy Apr 3, 2022
48f5d24
docs, more Maps tests/examples/workarounds
aSemy Apr 3, 2022
fa883b1
update gitattributes
aSemy Apr 3, 2022
6f3ad4e
rename 'knit' subproject to 'code'
aSemy Apr 3, 2022
aa13efa
prep for jitpack
aSemy Apr 3, 2022
e0583a3
docs update
aSemy Apr 3, 2022
ffd1a72
improve recursive descriptor extraction
aSemy Apr 3, 2022
83cacea
version bum git-versioning plugin
aSemy Apr 3, 2022
b093dac
better helper function for mutable maps with default puts
aSemy Apr 3, 2022
674b6df
simplify the API
aSemy Apr 3, 2022
cac1dcb
code tidup
aSemy Apr 3, 2022
c78b77a
formatting, code tidying
aSemy Apr 3, 2022
0889352
kmm gradle config tidy up
aSemy Apr 3, 2022
759740b
bump gradle version
aSemy Apr 3, 2022
43cfb94
add jitpack button
aSemy Apr 3, 2022
9e5cac5
fix maven publishing
aSemy Apr 3, 2022
d7f6686
update project name & group
aSemy Apr 3, 2022
bcb3c0a
disable reflekt dependency
aSemy Apr 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 100
62 changes: 57 additions & 5 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,8 +1,60 @@
* text eol=lf
# Common settings that generally should always be used with your language specific settings

*.java text diff=java
*.kt text diff=java
*.kts text diff=java
# Auto detect text files and perform LF normalization
* text eol=lf

# The above will handle all files NOT found below

*.md text
*.tex text diff=tex
*.adoc text
*.textile text
*.mustache text
*.csv text
*.tab text
*.tsv text
*.txt text
*.sql text

# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
*.eps binary
# SVG treated as an asset (binary) by default.
*.svg text

# Properties
*.json text
*.toml text
*.xml text
*.yaml text
*.yml text

# Scripts
*.bash text eol=lf
*.fish text eol=lf
*.sh text eol=lf
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf


# JVM sources
*.java text diff=java
*.gradle text diff=java
*.kt text diff=java
*.kts text diff=java

# Text files where line endings should be preserved
*.patch -text

#
# Exclude files from exporting
.gitattributes export-ignore
.gitignore export-ignore
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[![](https://jitpack.io/v/adamko-dev/kotlinx-serialization-typescript-generator.svg)](https://jitpack.io/#adamko-dev/kotlinx-serialization-typescript-generator)

# Kotlinx Serialization TypeScript Generator

Create TypeScript interfaces from Kotlin classes
Create TypeScript interfaces from Kotlinx Serialization classes.

```kotlin
@Serializable
Expand All @@ -10,7 +12,7 @@ data class PlayerDetails(
)

println(
KxsTsGenerator().generate(Color.serializer().descriptor)
KxsTsGenerator().generate(Color.serializer())
)
```

Expand All @@ -21,4 +23,30 @@ interface PlayerDetails {
}
```

The aim is to create TypeScript interfaces that can accurately produce Kotlinx Serialization
compatible JSON.

The Kotlinx Serialization API should be used to generate TypeScript. The
[`SerialDescriptor`s](https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization.descriptors/-serial-descriptor/index.html)
are flexible and comprehensive enough to allow for accurate TypeScript code, without any deviation.

See [the docs](./docs) for working examples.

## Status

This is a proof-of-concept.

| | Status | Notes |
|---------------------------------------|----------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
| Kotlin multiplatform | ❓ | The codebase is multiplatform, but only JVM has been tested |
| `@SerialName` | ✅/⚠ | The serial name is directly converted and might produce invalid TypeScript |
| Basic classes | ✅ [example](./docs/basic-classes.md) | |
| Nullable and default-value properties | ✅ [example](./docs/default-values.md) | |
| Value classes | ✅ [example](./docs/value-classes.md) | |
| Enums | ✅ [example](./docs/enums.md) | |
| Lists | ✅ [example](./docs/lists.md) | |
| Maps | ✅/⚠ [example](./docs/maps.md) | Maps with complex keys are converted to an ES6 Map, [see](./docs/maps.md#maps-with-complex-keys) |
| Polymorphism - Sealed classes | ✅/⚠ [example](./docs/polymorphism.md#sealed-classes) | Nested sealed classes are ignored, [see](./docs/polymorphism.md#nested-sealed-classes) |
| Polymorphism - Open classes | ❌ [example](./docs/abstract-classes.md) | Not implemented. Converted to `type MyClass = any` |
| `@JsonClassDiscriminator` | ❌ | Not implemented |
| Edge cases - circular dependencies | ✅ [example](./docs/edgecases.md) | |
46 changes: 4 additions & 42 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import buildsrc.config.excludeGeneratedGradleDsl

plugins {
base
id("me.qoomon.git-versioning") version "5.1.2"
idea
buildsrc.convention.`kotlin-jvm`
kotlin("plugin.serialization")
id("org.jetbrains.kotlinx.knit")
id("me.qoomon.git-versioning") version "5.1.5"
id("org.jetbrains.kotlinx.kover")
}


project.group = "dev.adamko"
project.group = "dev.adamko.kxtsgen"
project.version = "0.0.0-SNAPSHOT"
gitVersioning.apply {
refs {
Expand All @@ -24,7 +22,7 @@ gitVersioning.apply {


tasks.wrapper {
gradleVersion = "7.4"
gradleVersion = "7.4.2"
distributionType = Wrapper.DistributionType.ALL
}

Expand All @@ -40,39 +38,3 @@ idea {
)
}
}


val kotlinxSerializationVersion = "1.3.2"

dependencies {
implementation(projects.modules.kxsTsGenCore)

implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:${kotlinxSerializationVersion}"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json")

testImplementation(kotlin("test"))

testImplementation("org.jetbrains.kotlinx:kotlinx-knit-test:0.3.0")
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf(
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
)
}

sourceSets.test {
java.srcDirs("docs/example", "docs/test")
}

//knit {
// rootDir = layout.projectDirectory.asFile
// files = rootProject.fileTree("docs")
//}

tasks.test {
dependsOn(tasks.knit)
}

tasks.compileKotlin { mustRunAfter(tasks.knit) }
14 changes: 10 additions & 4 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ plugins {

object Versions {
const val jvmTarget = "11"
const val kotlinTarget = "1.6"
const val kotlin = "1.6.10"
const val ksp = "1.6.10-1.0.2"
const val kotlinxSerializationVersion = "1.3.2"
const val kotlinTarget = "1.6"
const val kotlinxKnit = "0.3.0"
const val kotlinxKover = "0.5.0"
const val kotlinxSerialization = "1.3.2"
const val ksp = "1.6.10-1.0.4"

const val kotest = "5.1.0"
}
Expand All @@ -28,11 +29,16 @@ dependencies {

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

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

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

implementation("org.jetbrains.kotlinx:kotlinx-knit:${Versions.kotlinxKnit}")
implementation("org.jetbrains.kotlinx:kover:${Versions.kotlinxKover}")

// implementation("org.jetbrains.reflekt:gradle-plugin:1.6.10-1-SNAPSHOT") {
// isChanging = true
// }
}


Expand Down
15 changes: 15 additions & 0 deletions buildSrc/repositories.settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,35 @@
dependencyResolutionManagement {

repositories {
myMavenLocal()
mavenCentral()
jitpack()
gradlePluginPortal()
}

pluginManagement {
repositories {
myMavenLocal()
jitpack()
gradlePluginPortal()
mavenCentral()
}
}
}


fun RepositoryHandler.jitpack() {
maven("https://jitpack.io")
}


fun RepositoryHandler.myMavenLocal(enabled: Boolean = false) {
if (enabled) {
logger.lifecycle("Maven local is enabled")
mavenLocal {
content {
// includeGroup("org.jetbrains.reflekt")
}
}
}
}
7 changes: 7 additions & 0 deletions buildSrc/src/main/kotlin/buildsrc/config/gradle.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package buildsrc.config

import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.file.ProjectLayout
import org.gradle.kotlin.dsl.findByType
import org.gradle.plugins.ide.idea.model.IdeaModule
import org.jetbrains.kotlin.gradle.dsl.KotlinTargetContainerWithPresetFunctions
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTests
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension


/** exclude generated Gradle code, so it doesn't clog up search results */
fun IdeaModule.excludeGeneratedGradleDsl(layout: ProjectLayout) {
Expand Down
47 changes: 47 additions & 0 deletions buildSrc/src/main/kotlin/buildsrc/config/kmm.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package buildsrc.config

import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.kotlin.dsl.findByType
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTests
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension


/**
* `kotlin-js` adds a directory in the root-dir for the Yarn lock.
* That's a bit annoying. It's a little neater if it's in the
* gradle dir, next to the version-catalog.
*/
fun Project.relocateKotlinJsStore() {

afterEvaluate {
rootProject.extensions.findByType<YarnRootExtension>()?.apply {
lockFileDirectory = project.rootDir.resolve("gradle/kotlin-js-store")
}
}

}


fun KotlinMultiplatformExtension.currentHostTarget(
targetName: String = "native",
configure: KotlinNativeTargetWithHostTests.() -> Unit,
): KotlinNativeTargetWithHostTests {
val hostOs = System.getProperty("os.name")
val hostTarget = when {
hostOs == "Mac OS X" -> macosX64(targetName)
hostOs == "Linux" -> linuxX64(targetName)
hostOs.startsWith("Windows") -> mingwX64(targetName)
else -> throw GradleException("Preset for host OS '$hostOs' is undefined")
}

println("Current host target ${hostTarget.targetName}/${hostTarget.preset?.name}")
hostTarget.configure()
return hostTarget
}


fun KotlinMultiplatformExtension.publicationsFromMainHost(): List<String> {
return listOf(jvm(), js()).map { it.name } + "kotlinMultiplatform"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package buildsrc.convention

import org.gradle.kotlin.dsl.`java-library`
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.jacoco
import org.gradle.kotlin.dsl.kotlin
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
Expand All @@ -11,11 +10,10 @@ plugins {
id("buildsrc.convention.subproject")
kotlin("jvm")
`java-library`
jacoco
}

dependencies {
testImplementation(platform("io.kotest:kotest-bom:5.1.0"))
testImplementation(platform("io.kotest:kotest-bom:5.2.1"))
testImplementation("io.kotest:kotest-runner-junit5")
testImplementation("io.kotest:kotest-assertions-core")
testImplementation("io.kotest:kotest-property")
Expand All @@ -33,7 +31,7 @@ java {
withSourcesJar()
}

tasks.withType<KotlinCompile>().configureEach {
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "11"
apiVersion = "1.6"
Expand All @@ -53,5 +51,4 @@ tasks.compileTestKotlin {

tasks.test {
useJUnitPlatform()
finalizedBy(tasks.jacocoTestReport)
}
Loading