get a shared kotlin-typescript data model working

This commit is contained in:
Adam 2021-11-27 17:57:50 +01:00
parent d6a9a58dc9
commit 0d85bfca60
10 changed files with 173 additions and 178 deletions

View file

@ -0,0 +1,15 @@
package dev.adamko.factoriowebmap.configurations
import org.gradle.api.artifacts.Configuration
fun Configuration.asProvider() {
isVisible = false
isCanBeResolved = false
isCanBeConsumed = true
}
fun Configuration.asConsumer() {
isVisible = false
isCanBeResolved = true
isCanBeConsumed = false
}

View file

@ -0,0 +1,20 @@
package dev.adamko.factoriowebmap.configurations
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.model.ObjectFactory
import org.gradle.kotlin.dsl.named
fun Configuration.typescriptAttributes(objects: ObjectFactory) =
attributes { typescript(objects) }
fun AttributeContainer.typescript(objects: ObjectFactory) {
attribute(Usage.USAGE_ATTRIBUTE, objects.named("typescript"))
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.OBJECTS))
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
}

View file

@ -1,120 +1,46 @@
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import dev.adamko.factoriowebmap.configurations.asProvider
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import dev.adamko.factoriowebmap.configurations.typescriptAttributes
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
plugins { plugins {
id("dev.adamko.factoriowebmap.archetype.kotlin-multiplatform") id("dev.adamko.factoriowebmap.archetype.kotlin-jvm")
kotlin("plugin.serialization") kotlin("plugin.serialization")
} }
val projectId: String by project.extra val projectId: String by project.extra
val buildDir: Directory = layout.buildDirectory.dir(projectId).get() val buildDir: Directory = layout.buildDirectory.dir(projectId).get()
kotlin { dependencies {
val kotlinXSerializationVersion = "1.3.0"
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinXSerializationVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinXSerializationVersion")
//<editor-fold desc="Java"> implementation("com.github.ntrrgc:ts-generator:1.1.2")
jvm { implementation("org.jetbrains.kotlin:kotlin-reflect")
compilations.configureEach { }
kotlinOptions {
jvmTarget = "11"
apiVersion = "1.6"
languageVersion = "1.6"
}
}
}
sourceSets { val generateTypescript by tasks.registering(JavaExec::class) {
val jvmMain by getting { group = project.name
dependencies {
implementation("com.github.ntrrgc:ts-generator:1.1.1")
implementation("org.jetbrains.kotlin:kotlin-reflect")
val kotlinXSerializationVersion = "1.3.0" val generatedFileName = "$temporaryDir/data-model.ts"
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinXSerializationVersion") inputs.property("generatedFileName", generatedFileName)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinXSerializationVersion") outputs.file(generatedFileName)
}
}
val jvmTest by getting {
}
}
//</editor-fold> classpath(sourceSets.main.map { it.runtimeClasspath })
mainClass.set("dev.adamko.factorioevents.model.Kt2tsKt")
args(generatedFileName)
//<editor-fold desc="JS"> doFirst {
js(IR) { delete(temporaryDir)
moduleName = "data-model" mkdir(temporaryDir)
browser { }
binaries.executable()
}
sourceSets {
val jsMain: KotlinSourceSet by getting {
dependencies {
implementation(npm("lua-types", "^2.11.0"))
implementation(npm("@types/node", "^12.0.8"))
implementation(npm("typescript-to-lua", "1.1.1"))
implementation(npm("typescript", "4.4.4"))
implementation(npm("typed-factorio", "0.11.0-packagetypes-1", false))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
//</editor-fold>
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
// enableLanguageFeature("InlineClasses") // language feature name
optIn("kotlin.OptIn")
optIn("kotlin.RequiresOptIn")
optIn("kotlin.ExperimentalStdlibApi")
optIn("kotlin.time.ExperimentalTime")
optIn("kotlinx.coroutines.ExperimentalCoroutinesApi")
optIn("kotlin.js.ExperimentalJsExport")
optIn("kotlinx.serialization.ExperimentalSerializationApi")
// progressiveMode = true // false by default
}
} }
} }
val typescriptModelGenerated by configurations.registering {
afterEvaluate { asProvider()
typescriptAttributes(objects)
val kotlinJsCompilation: KotlinJsCompilation = outgoing.artifact(
kotlin.targets generateTypescript.map {
.flatMap { it.compilations } it.outputs.files.singleFile
.filterIsInstance<KotlinJsCompilation>() }
.first { it.name == KotlinCompilation.MAIN_COMPILATION_NAME } )
val npmProject = kotlinJsCompilation.npmProject
tasks.create<Exec>("tstl") {
group = project.name
standardOutput = System.out
errorOutput = System.err
workingDir = npmProject.dir
executable = when (npmProject.nodeJs.requireConfigured().isWindows) {
true -> "npx.cmd"
false -> "npx"
}
args(parseSpaceSeparatedArgs("tstl --out $temporaryDir"))
}
} }

View file

@ -1,56 +0,0 @@
package dev.adamko.factorioevents.model
import kotlin.js.ExperimentalJsExport
import kotlin.js.JsExport
//
//@JsExport
//@ExperimentalJsExport
//data class FactorioEvent(
// val modVersion: String,
// val tick: F_uint,
// val eventType: String,
// val data: FactorioObjectData,
//)
//
//@JsExport
//abstract class FactorioObjectData {
// abstract val objectName: String
//}
//
//@JsExport
//data class PlayerData(
// override val objectName: String,
// val name: String,
// val characterUnitNumber: F_uint,
// val associatedCharactersUnitNumbers: List<F_uint>,
// val position: PositionData,
//) : FactorioObjectData()
//
//
//@JsExport
//data class PositionData(
// val x: F_int,
// val y: F_int,
//)
//
//
//
//typealias F_float = Float
//typealias F_double = Double
//typealias F_int = Int
//typealias F_int8 = Byte
//
//
////@JsExport
////@ExperimentalJsExport
//typealias F_uint = UInt
////expect class F_uint
//
////expect value class F_uint internal constructor(internal val data: Int)
//expect value class F_uint8 internal constructor(internal val data: Int)
//expect value class F_uint16 internal constructor(internal val data: Int)
//expect value class F_uint64 internal constructor(internal val data: Int)
//
//typealias F_table = Any?
//

View file

@ -1,13 +0,0 @@
package dev.adamko.factorioevents.model
import kotlin.js.*
//
//@JsModule("typed-factorio")
//external class uint
//
//actual typealias F_uint = uint
//actual typealias F_uint8 = UByte
//actual typealias F_uint16 = UShort
//actual typealias F_uint64 = ULong
//

View file

@ -7,8 +7,11 @@ import kotlinx.serialization.json.JsonClassDiscriminator
@Serializable @Serializable
data class FactorioEvent( data class FactorioEvent(
/** Schema versioning */
val modVersion: String, val modVersion: String,
/** game time */
val tick: UInt, val tick: UInt,
/** the initial Factorio event ({defines.events}) trigger */
val eventType: String, val eventType: String,
val data: FactorioObjectData, val data: FactorioObjectData,
) )
@ -33,10 +36,10 @@ data class EntityData(
val active: Boolean, val active: Boolean,
val healthRatio: Float, val healthRatio: Float,
val health: Float?, val health: Float?,
val surface_index: Int, val surfaceIndex: Int,
val unit_number: UInt?, val unitNumber: UInt?,
val position: PositionData, val position: PositionData,
val player_index: UInt?, val playerIndex: UInt?,
) : FactorioObjectData ) : FactorioObjectData
data class SurfaceData( data class SurfaceData(

View file

@ -1,13 +1,14 @@
package dev.adamko.factorioevents.model package dev.adamko.factorioevents.model
import java.io.File
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
import me.ntrrgc.tsGenerator.ClassTransformer import me.ntrrgc.tsGenerator.ClassTransformer
import me.ntrrgc.tsGenerator.TypeScriptGenerator import me.ntrrgc.tsGenerator.TypeScriptGenerator
import me.ntrrgc.tsGenerator.camelCaseToSnakeCase import me.ntrrgc.tsGenerator.camelCaseToSnakeCase
import org.intellij.lang.annotations.Language
fun main(args: Array<String>) {
fun main() {
val gen = val gen =
TypeScriptGenerator( TypeScriptGenerator(
@ -32,9 +33,32 @@ fun main() {
) )
) )
println(gen.definitionsText) val definitions = gen.definitionsText
when (val filename = args.firstOrNull()) {
null -> {
println(definitions)
}
else -> {
val out = File(filename)
out.parentFile.mkdirs()
out.printWriter().use {
it.print(header)
it.print(definitions)
}
println("Generated file: $out")
}
}
} }
@Language("TypeScript")
val header = """
// Generated code - do edit this file manually
""".trimIndent()
object PropertyNameTransformer : ClassTransformer { object PropertyNameTransformer : ClassTransformer {
override fun transformPropertyName( override fun transformPropertyName(
propertyName: String, propertyName: String,

View file

@ -1,4 +1,6 @@
import com.github.gradle.node.npm.task.NpmTask import com.github.gradle.node.npm.task.NpmTask
import dev.adamko.factoriowebmap.configurations.asConsumer
import dev.adamko.factoriowebmap.configurations.typescriptAttributes
import org.apache.tools.ant.filters.ReplaceTokens import org.apache.tools.ant.filters.ReplaceTokens
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
@ -53,6 +55,35 @@ val tstlTask = tasks.register<NpmTask>("typescriptToLua") {
} }
val dataModelTs: Configuration by configurations.creating {
asConsumer()
typescriptAttributes(objects)
}
dependencies {
dataModelTs(projects.modules.factorioEventsDataModel)
}
val updateDataModel by tasks.registering(Sync::class) {
group = project.name
dependsOn(dataModelTs)
from(
dataModelTs.incoming
.artifactView { lenient(true) }
.artifacts
.artifactFiles
.filter { it.exists() }
)
into(layout.projectDirectory.dir("src/main/typescript/generated"))
}
tasks.assemble { dependsOn(updateDataModel) }
idea { idea {
module { module {
sourceDirs.add(mkdir(layout.projectDirectory.dir("src/main/typescript").asFile)) sourceDirs.add(mkdir(layout.projectDirectory.dir("src/main/typescript").asFile))

View file

@ -0,0 +1,45 @@
// Generated code - do edit this file manually
interface FactorioObjectData {
object_name: string;
}
interface FactorioEvent {
data: FactorioObjectData;
event_type: string;
mod_version: string;
tick: uint;
}
interface PositionData {
x: int;
y: int;
}
interface PlayerData extends FactorioObjectData {
associated_character_unit_numbers: uint[];
character_unit_number: uint;
object_name: string;
position_data: PositionData;
}
interface EntityData extends FactorioObjectData {
active: boolean;
health: float | null;
health_ratio: float;
name: string;
object_name: string;
player_index: uint | null;
position: PositionData;
surface_index: int;
type: string;
unit_number: uint | null;
}
interface SurfaceData extends FactorioObjectData {
daytime: float;
index: uint;
name: string;
object_name: string;
}