diff --git a/typed/src/main/kotlin/com/lightningkite/lightningserver/typed/sdk/TypescriptFetcherSdk.kt b/typed/src/main/kotlin/com/lightningkite/lightningserver/typed/sdk/TypescriptFetcherSdk.kt index bd6a8de45..8d67f1d8d 100644 --- a/typed/src/main/kotlin/com/lightningkite/lightningserver/typed/sdk/TypescriptFetcherSdk.kt +++ b/typed/src/main/kotlin/com/lightningkite/lightningserver/typed/sdk/TypescriptFetcherSdk.kt @@ -168,9 +168,7 @@ public class TypescriptFetcherSdk( fun Appendable.appendModelImports() = appendLine( "import type { ${ - models.joinToString { - it.tsType().substringBefore('<') - } + models.map { it.tsTopLevelTypeName() }.distinct().joinToString() } } from './${fileStructure.modelsFilename}'" ) @@ -200,61 +198,109 @@ public class TypescriptFetcherSdk( private fun Appendable.appendLsImports() = appendLine("import type { ${fromLightningServerPackage.joinToString()} } from '@lightningkite/lightning-server-simplified'") + @OptIn(ExperimentalSerializationApi::class) context(server: ServerRuntime) private fun Appendable.writeTypeDefinitions(types: List> = server.models()) { val stringSerialNames = HashSet() - - for (type in types) { - if(type.descriptor.isInline) { - val name = type.descriptor.simpleSerialName - if (stringSerialNames.add(name)) { - if(name == "ServerFile") appendLine( - "export type ServerFile = string" - ) - else appendLine( - "export type $name = ${type.innerElement().decontextualize().tsType()} // ${type.descriptor.serialName}" - ) + // TypeScript merges declarations with the same exported name, so nested Kotlin types + // are emitted as namespace members next to their parent interface. We render first, + // collect members like TestModel.ID/Status, then flush each namespace immediately + // after the matching top-level declaration for readability and stable imports. + val namespaces = linkedMapOf>() + val topLevelDeclarations = ArrayList>() + + fun Appendable.appendDecl( + name: String, + emit: Appendable.(String, Int) -> Unit, + ): Pair? { + val namespace = name.substringBefore('.', "") + + if (namespace.isNotEmpty()) { + namespaces.getOrPut(namespace) { ArrayList() } += buildString { + emit(name.substringAfter('.'), 1) } - } else when (type.descriptor.kind) { - StructureKind.CLASS -> { - val genericMap: Map = type - .getGenerics() - ?.withIndex() - ?.associate { (index, value) -> - value.tsType() to "T${if (index > 0) index else ""}" - } - ?: emptyMap() - - fun String.replaceGenerics(): String = - genericMap.entries.fold(this) { acc, (old, new) -> acc.replace(old, new) } + return null + } +// Top Level Declaration Name + return name.substringBefore('<').substringBefore('.') to buildString { + emit(name, 0) + } + } - appendLine("export interface ${type.tsType().replaceGenerics()} {") + fun Appendable.appendNamespace(namespace: String) { + val declarations = namespaces.remove(namespace) ?: return + appendLine("export namespace $namespace {") + declarations.forEachIndexed { index, declaration -> + if (index > 0) appendLine() + append(declaration) + } + appendLine('}') + appendLine() + } + fun renderType(type: KSerializer<*>): Pair? = when (type.descriptor.kind) { + StructureKind.CLASS -> { + val genericMap: Map = type + .getGenerics() + ?.withIndex() + ?.associate { (index, value) -> + value.tsType() to "T${if (index > 0) index else ""}" + } + ?: emptyMap() + + fun String.replaceGenerics(): String = + genericMap.entries + .sortedByDescending { it.key.length } + .fold(this) { acc, (old, new) -> acc.replace(old, new) } + + if (type.descriptor.isInline) { + val valueType = + type.serializableProperties?.firstOrNull()?.serializer?.tsType()?.replaceGenerics() + val name = type.tsType().replaceGenerics() + appendDecl(name, { localName, depth -> + appendIdtLine(depth, "export type $localName = Brand<${valueType}, \"$name\">") + }) + } else { val properties = type .serializableProperties?.map { it.serializer } ?: type.childSerializersOrNull()?.toList() ?: emptyList() - for ((idx, prop) in properties.withIndex()) { - appendLine("\t${type.descriptor.getElementName(idx)}: ${prop.tsType().replaceGenerics()}") - } + val name = type.tsType().replaceGenerics() - appendLine('}') + appendDecl(name, { localName, depth -> + appendIdtLine(depth, "export interface $localName {") + for ((idx, prop) in properties.withIndex()) { + appendIdtLine( + depth + 1, + "${type.descriptor.getElementName(idx)}: ${prop.tsType().replaceGenerics()}" + ) + } + + appendIdtLine(depth, "}") + }) } + } - SerialKind.ENUM -> { - if (erasableTypes) { - append("export type ${type.tsType()} = ") + SerialKind.ENUM -> { + val typeName = type.tsType() + if (erasableTypes) { + appendDecl(typeName, { localName, depth -> + appendIdt(depth) + append("export type $localName = ") for (index in 0 until type.descriptor.elementsCount) { val name = type.descriptor.getElementName(index) append(if (index == 0) "\"$name\"" else "| \"$name\"") } appendLine() - } else { - appendLine("export enum ${type.tsType()} {") + }) + } else { + val typeName = type.tsType(); + appendDecl(typeName, { localName, depth -> + appendIdtLine(depth, "export enum $localName {") for (index in 0 until type.descriptor.elementsCount) { - append('\t') + appendIdt(depth + 1) val name = type.descriptor.getElementName(index) name.forEachIndexed { idx, it -> if ((idx == 0 && it.isJavaIdentifierStart()) || (idx != 0 && it.isJavaIdentifierPart())) @@ -266,57 +312,75 @@ public class TypescriptFetcherSdk( appendLine() } - appendLine('}') - } + appendIdtLine(depth, "}") + }) } + } - PrimitiveKind.STRING -> { - val name = type.descriptor.simpleSerialName - if (name != "String" && stringSerialNames.add(name)) { + PrimitiveKind.STRING -> { + val name = type.descriptor.simpleSerialName + if (name != "String" && stringSerialNames.add(name)) { + name to buildString { appendLine( "export type $name = string // ${type.descriptor.serialName}" ) } - } + } else null + } - is PolymorphicKind -> { - val options = type.sealedOptionsOrNull() ?: continue + is PolymorphicKind -> { + val options = type.sealedOptionsOrNull() ?: return null + val genericMap: Map = type + .getGenerics() + ?.withIndex() + ?.associate { (index, value) -> + value.tsType() to "T${if (index > 0) index else ""}" + } + ?: emptyMap() - val genericMap: Map = type - .getGenerics() - ?.withIndex() - ?.associate { (index, value) -> - value.tsType() to "T${if (index > 0) index else ""}" - } - ?: emptyMap() + fun String.replaceGenerics(): String = + genericMap.entries.fold(this) { acc, (old, new) -> acc.replace(old, new) } - fun String.replaceGenerics(): String = - genericMap.entries.fold(this) { acc, (old, new) -> acc.replace(old, new) } + // A discriminated union of the subtypes. App `@Serializable sealed` types serialize + // flat with a "type" discriminator ({ "type": "", ...subtype fields }); framework + // wrapper types serialize as { "": }. Each subtype is emitted as its own + // interface, so the union just references those by name. - // A discriminated union of the subtypes. App `@Serializable sealed` types serialize - // flat with a "type" discriminator ({ "type": "", ...subtype fields }); framework - // wrapper types serialize as { "": }. Each subtype is emitted as its own - // interface, so the union just references those by name. + val typeName = type.tsType().replaceGenerics() + appendDecl(typeName, { localName, depth -> val wrapper = type.isWrapperSealed() - append("export type ${type.tsType().replaceGenerics()} =") + appendIdt(depth) + append("export type ${localName} =") if (options.isEmpty()) { appendLine(" never") } else { appendLine() for (option in options) { val sub = option.serializer.tsType().replaceGenerics() - if (wrapper) appendIdtLine(1, "| { \"${option.name}\": $sub }") - else appendIdtLine(1, "| ({ type: \"${option.name}\" } & $sub)") + if (wrapper) appendIdtLine(depth + 1, "| { \"${option.name}\": $sub }") + else appendIdtLine(depth + 1, "| ({ type: \"${option.name}\" } & $sub)") } } - } - - else -> continue + }) } + + else -> null + } + + for (type in types) { + renderType(type)?.let { topLevelDeclarations += it } + } + + for ((name, declaration) in topLevelDeclarations) { + append(declaration) appendLine() + appendNamespace(name) } + + namespaces.keys.toList().forEach { appendNamespace(it) } } + /** * Generates the TypeScript interface definition for the API. * @@ -462,21 +526,22 @@ public class TypescriptFetcherSdk( .sortedBy { it.descriptor.simpleSerialName } .distinctBy { it.tsType().substringBefore("<") } // Distinct by generics .filter { - if(it.descriptor.isInline) true - else when (it.descriptor.kind) { + when (it.descriptor.kind) { SerialKind.ENUM -> true - // Inline value classes serialize as their underlying primitive (see tsType), so they get no - // standalone type definition and must not be emitted/imported as model types. - StructureKind.CLASS if (it !is MySealedClassSerializer && !it.descriptor.isInline) -> true + StructureKind.CLASS if (it !is MySealedClassSerializer) -> true PrimitiveKind.STRING if (it.descriptor.simpleSerialName != "String") -> true // Sealed/polymorphic types are emitted as TS discriminated unions (see writeTypeDefinitions). is PolymorphicKind -> true - else -> false } } + context(runtime: ServerRuntime) + private fun KSerializer<*>.tsTopLevelTypeName(): String = tsType() + .substringBefore('<') + .substringBefore('.') + @OptIn(ExperimentalSerializationApi::class) context(runtime: ServerRuntime) private fun KSerializer<*>.tsType(): String = nullElement()?.let { it.tsType() + " | null | undefined" } ?: when { @@ -525,7 +590,8 @@ public class TypescriptFetcherSdk( if (descriptor.serialName == "com.lightningkite.serialization.Partial") { append("DeepPartial") } else { - append(descriptor.simpleSerialName) + val name = descriptor.simpleSerialName + append(descriptor.nestedTsTypeName ?: name) } typeParametersSerializersOrNull() ?.takeUnless { it.isEmpty() } @@ -536,9 +602,16 @@ public class TypescriptFetcherSdk( } private val SerialDescriptor.simpleSerialName: String + get() = serialName.substringBefore('<').substringBefore('/').substringAfterLast('.').removeSuffix("?") + + private val SerialDescriptor.nestedTsTypeName: String? get() { - val fqn = serialName.substringBefore('<').substringBefore('/').removeSuffix("?") - return fqn.split('.').filter { it.first().isUpperCase() }.joinToString("") + val parts = serialName.substringBefore('<').substringBefore('/').split('.') + if (parts.size < 2) return null + val name = simpleSerialName + val parentName = parts[parts.size - 2] + if (parentName.firstOrNull()?.isUpperCase() != true) return null + return "$parentName.$name" } @OptIn(ExperimentalSerializationApi::class) @@ -568,8 +641,9 @@ public class TypescriptFetcherSdk( "DataClassPathPartial", "QueryPartial", "DeepPartial", - "Fetcher" + "Fetcher", + "Brand", ) private val skipFromLsPackage = setOf("Partial") + fromLightningServerPackage -} \ No newline at end of file +} diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/Api.kt b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/Api.kt index fd0be087d..0ce5f5d4b 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/Api.kt +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/Api.kt @@ -39,7 +39,7 @@ interface Api { } val predefinedEndpoints: PredefinedEndpoints - interface ModuleApi : com.lightningkite.lightningserver.typed.ClientModelRestEndpoints { + interface ModuleApi : com.lightningkite.lightningserver.typed.ClientModelRestEndpoints { /** * Test Endpoint * @@ -65,7 +65,7 @@ interface Api { * */ suspend fun inlinedEndpoint2(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int - interface DefaultEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface DefaultEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -89,7 +89,7 @@ interface Api { } val default: DefaultEndpoints - interface DefaultEndpoints2 : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface DefaultEndpoints2 : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -115,7 +115,7 @@ interface Api { } val module: ModuleApi - interface CustomEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface CustomEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -157,9 +157,9 @@ interface Api { * */ suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int - val rest: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints + val rest: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints - val rest2: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints + val rest2: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints } val other: OtherEndpoints } diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/LiveApi.kt b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/LiveApi.kt index 0a355971b..071ed8bec 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/LiveApi.kt +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/LiveApi.kt @@ -23,7 +23,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val predefinedEndpoints = LivePredefinedEndpoints() - inner class LiveModuleApi : Api.ModuleApi, com.lightningkite.lightningserver.typed.ClientModelRestEndpoints by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "m1/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveModuleApi : Api.ModuleApi, com.lightningkite.lightningserver.typed.ClientModelRestEndpoints by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "m1/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(first: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/endpoint/${fetcher.url(first, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) override suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = @@ -31,7 +31,7 @@ class LiveApi(val fetcher: Fetcher) : Api { override suspend fun inlinedEndpoint2(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = fetcher("m1/inline/action/${fetcher.url(id, kotlin.uuid.Uuid.serializer())}/${fetcher.url(category, kotlin.uuid.Uuid.serializer())}", HttpMethod.POST, kotlin.Unit.serializer(), kotlin.Unit, kotlin.Int.serializer()) - inner class LiveDefaultEndpoints : Api.ModuleApi.DefaultEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/second/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveDefaultEndpoints : Api.ModuleApi.DefaultEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/second/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/second/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -43,7 +43,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val default = LiveDefaultEndpoints() - inner class LiveDefaultEndpoints2 : Api.ModuleApi.DefaultEndpoints2, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/duplicate/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveDefaultEndpoints2 : Api.ModuleApi.DefaultEndpoints2, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/duplicate/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/duplicate/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -57,7 +57,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val module = LiveModuleApi() - inner class LiveCustomEndpoints : Api.CustomEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m2/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveCustomEndpoints : Api.CustomEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m2/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m2/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -75,9 +75,9 @@ class LiveApi(val fetcher: Fetcher) : Api { override suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = fetcher("third/inline/action/${fetcher.url(id, kotlin.uuid.Uuid.serializer())}/${fetcher.url(category, kotlin.uuid.Uuid.serializer())}", HttpMethod.POST, kotlin.Unit.serializer(), kotlin.Unit, kotlin.Int.serializer()) - override val rest = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) + override val rest = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) - override val rest2 = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest2", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) + override val rest2 = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest2", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) } override val other = LiveOtherEndpoints() } diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/sdk.kt b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/sdk.kt index e3a03aaf3..c12131cd8 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/sdk.kt +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/kotlin/sdk.kt @@ -43,7 +43,7 @@ interface Api { } val predefinedEndpoints: PredefinedEndpoints - interface ModuleApi : com.lightningkite.lightningserver.typed.ClientModelRestEndpoints { + interface ModuleApi : com.lightningkite.lightningserver.typed.ClientModelRestEndpoints { /** * Test Endpoint * @@ -69,7 +69,7 @@ interface Api { * */ suspend fun inlinedEndpoint2(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int - interface DefaultEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface DefaultEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -93,7 +93,7 @@ interface Api { } val default: DefaultEndpoints - interface DefaultEndpoints2 : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface DefaultEndpoints2 : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -119,7 +119,7 @@ interface Api { } val module: ModuleApi - interface CustomEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { + interface CustomEndpoints : com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket { /** * Test Endpoint * @@ -161,9 +161,9 @@ interface Api { * */ suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int - val rest: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints + val rest: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints - val rest2: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints + val rest2: com.lightningkite.lightningserver.typed.ClientModelRestEndpoints } val other: OtherEndpoints } @@ -185,7 +185,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val predefinedEndpoints = LivePredefinedEndpoints() - inner class LiveModuleApi : Api.ModuleApi, com.lightningkite.lightningserver.typed.ClientModelRestEndpoints by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "m1/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveModuleApi : Api.ModuleApi, com.lightningkite.lightningserver.typed.ClientModelRestEndpoints by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "m1/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(first: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/endpoint/${fetcher.url(first, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) override suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = @@ -193,7 +193,7 @@ class LiveApi(val fetcher: Fetcher) : Api { override suspend fun inlinedEndpoint2(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = fetcher("m1/inline/action/${fetcher.url(id, kotlin.uuid.Uuid.serializer())}/${fetcher.url(category, kotlin.uuid.Uuid.serializer())}", HttpMethod.POST, kotlin.Unit.serializer(), kotlin.Unit, kotlin.Int.serializer()) - inner class LiveDefaultEndpoints : Api.ModuleApi.DefaultEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/second/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveDefaultEndpoints : Api.ModuleApi.DefaultEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/second/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/second/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -205,7 +205,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val default = LiveDefaultEndpoints() - inner class LiveDefaultEndpoints2 : Api.ModuleApi.DefaultEndpoints2, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/duplicate/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveDefaultEndpoints2 : Api.ModuleApi.DefaultEndpoints2, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m1/duplicate/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m1/duplicate/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -219,7 +219,7 @@ class LiveApi(val fetcher: Fetcher) : Api { } override val module = LiveModuleApi() - inner class LiveCustomEndpoints : Api.CustomEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m2/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) { + inner class LiveCustomEndpoints : Api.CustomEndpoints, com.lightningkite.lightningserver.typed.ClientModelRestEndpointsAndUpdatesWebsocket by com.lightningkite.lightningserver.typed.LiveClientModelRestEndpointsAndUpdatesWebsocket(fetcher, "m2/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) { override suspend fun testSdkEndpoint(second: kotlin.String, input: com.lightningkite.lightningserver.typed.sdk.TestInput): kotlin.String = fetcher("m2/endpoint/${fetcher.url(second, kotlin.String.serializer())}", HttpMethod.POST, com.lightningkite.lightningserver.typed.sdk.TestInput.serializer(), input, kotlin.String.serializer()) @@ -237,9 +237,9 @@ class LiveApi(val fetcher: Fetcher) : Api { override suspend fun inlinedEndpoint(id: kotlin.uuid.Uuid, category: kotlin.uuid.Uuid): kotlin.Int = fetcher("third/inline/action/${fetcher.url(id, kotlin.uuid.Uuid.serializer())}/${fetcher.url(category, kotlin.uuid.Uuid.serializer())}", HttpMethod.POST, kotlin.Unit.serializer(), kotlin.Unit, kotlin.Int.serializer()) - override val rest = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) + override val rest = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) - override val rest2 = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest2", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), kotlin.uuid.Uuid.serializer()) + override val rest2 = com.lightningkite.lightningserver.typed.LiveClientModelRestEndpoints(fetcher, "third/rest2", com.lightningkite.lightningserver.typed.sdk.TestModel.serializer(), com.lightningkite.lightningserver.typed.sdk.TestModel.ID.serializer()) } override val other = LiveOtherEndpoints() } diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/Api.ts b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/Api.ts index ebaf46e09..ddb288fa2 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/Api.ts +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/Api.ts @@ -1,5 +1,5 @@ -import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher } from '@lightningkite/lightning-server-simplified' -import type { CollectionUpdates, Mask, Mode, ModelPermissions, Pair, Part, TestInput, TestModel, UpdateRestrictions, Uuid } from './models.ts' +import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher, Brand } from '@lightningkite/lightning-server-simplified' +import type { CollectionUpdates, TestModel, Mask, UpdateRestrictions, ModelPermissions, Pair, TestInput, Uuid } from './models.ts' export interface Api { index(): Promise @@ -28,13 +28,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly default: { testSdkEndpoint(second: string, input: TestInput): Promise @@ -53,13 +53,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { inlinedEndpoint(id: Uuid, category: Uuid): Promise @@ -82,13 +82,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { inlinedEndpoint(id: Uuid, category: Uuid): Promise @@ -112,13 +112,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { inlinedEndpoint(id: Uuid, category: Uuid): Promise @@ -144,13 +144,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> } readonly rest2: { list(input: Query): Promise> @@ -168,13 +168,13 @@ export interface Api { groupCount2(input: GroupCountQuery): Promise> bulkDelete(input: Condition): Promise aggregate(input: AggregateQuery): Promise - detail(id: Uuid): Promise - upsert(id: Uuid, input: TestModel): Promise - replace(id: Uuid, input: TestModel): Promise - modify(id: Uuid, input: Modification): Promise - delete(id: Uuid): Promise - simplifiedModify(id: Uuid, input: Partial): Promise - modifyWithDiff(id: Uuid, input: Modification): Promise> + detail(id: TestModel.ID): Promise + upsert(id: TestModel.ID, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise + modify(id: TestModel.ID, input: Modification): Promise + delete(id: TestModel.ID): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> } } } diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/LiveApi.ts b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/LiveApi.ts index b96106ea6..04e940933 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/LiveApi.ts +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/LiveApi.ts @@ -1,5 +1,5 @@ -import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher } from '@lightningkite/lightning-server-simplified' -import type { CollectionUpdates, Mask, Mode, ModelPermissions, Pair, Part, TestInput, TestModel, UpdateRestrictions, Uuid } from './models.ts' +import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher, Brand } from '@lightningkite/lightning-server-simplified' +import type { CollectionUpdates, TestModel, Mask, UpdateRestrictions, ModelPermissions, Pair, TestInput, Uuid } from './models.ts' import type { Api } from './Api.ts' export class LiveApi implements Api { diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/models.ts b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/models.ts index 5dc3749e2..1da6dee1b 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/models.ts +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/models.ts @@ -1,4 +1,4 @@ -import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher } from '@lightningkite/lightning-server-simplified' +import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher, Brand } from '@lightningkite/lightning-server-simplified' export interface CollectionUpdates { updates: Array @@ -11,11 +11,6 @@ export interface Mask { pairs: Array, Modification>> } -export enum Mode { - Blacklist = "Blacklist", - Whitelist = "Whitelist", -} - export interface ModelPermissions { create: Condition read: Condition @@ -31,25 +26,48 @@ export interface Pair { second: T1 } -export interface Part { - property: DataClassPathPartial - requires: Condition - limitedTo: Condition -} - export interface TestInput { id: number name: string } export interface TestModel { - _id: Uuid + _id: TestModel.ID name: string + statusInfo: TestModel.TestStatusInfo +} + +export namespace TestModel { + export type ID = Brand + + export enum Status { + Active = "Active", + Inactive = "Inactive", + Pending = "Pending", + } + + export interface TestStatusInfo { + status: TestModel.Status + updatedAt: number + } } export interface UpdateRestrictions { - mode: Mode - fields: Array> + mode: UpdateRestrictions.Mode + fields: Array> +} + +export namespace UpdateRestrictions { + export enum Mode { + Blacklist = "Blacklist", + Whitelist = "Whitelist", + } + + export interface Part { + property: DataClassPathPartial + requires: Condition + limitedTo: Condition + } } export type Uuid = string // kotlin.uuid.Uuid diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/sdk.ts b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/sdk.ts index 93c3e2ab4..a20a236d6 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/sdk.ts +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/generated/typescript/sdk.ts @@ -1,4 +1,4 @@ -import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher } from '@lightningkite/lightning-server-simplified' +import type { Query, MassModification, EntryChange, ListChange, Modification, Condition, GroupCountQuery, AggregateQuery, GroupAggregateQuery, Aggregate, SortPart, DataClassPath, DataClassPathPartial, QueryPartial, DeepPartial, Fetcher, Brand } from '@lightningkite/lightning-server-simplified' export interface CollectionUpdates { updates: Array @@ -11,11 +11,6 @@ export interface Mask { pairs: Array, Modification>> } -export enum Mode { - Blacklist = "Blacklist", - Whitelist = "Whitelist", -} - export interface ModelPermissions { create: Condition read: Condition @@ -31,25 +26,48 @@ export interface Pair { second: T1 } -export interface Part { - property: DataClassPathPartial - requires: Condition - limitedTo: Condition -} - export interface TestInput { id: number name: string } export interface TestModel { - _id: Uuid + _id: TestModel.ID name: string + statusInfo: TestModel.TestStatusInfo +} + +export namespace TestModel { + export type ID = Brand + + export enum Status { + Active = "Active", + Inactive = "Inactive", + Pending = "Pending", + } + + export interface TestStatusInfo { + status: TestModel.Status + updatedAt: number + } } export interface UpdateRestrictions { - mode: Mode - fields: Array> + mode: UpdateRestrictions.Mode + fields: Array> +} + +export namespace UpdateRestrictions { + export enum Mode { + Blacklist = "Blacklist", + Whitelist = "Whitelist", + } + + export interface Part { + property: DataClassPathPartial + requires: Condition + limitedTo: Condition + } } export type Uuid = string // kotlin.uuid.Uuid @@ -243,7 +261,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -251,7 +269,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -259,7 +277,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -267,7 +285,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -275,7 +293,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -283,7 +301,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -291,7 +309,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly default: { /** @@ -429,7 +447,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -437,7 +455,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -445,7 +463,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -453,7 +471,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -461,7 +479,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -469,7 +487,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -477,7 +495,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { /** @@ -626,7 +644,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -634,7 +652,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -642,7 +660,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -650,7 +668,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -658,7 +676,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -666,7 +684,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -674,7 +692,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { /** @@ -824,7 +842,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -832,7 +850,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -840,7 +858,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -848,7 +866,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -856,7 +874,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -864,7 +882,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -872,7 +890,7 @@ export interface Api { * * **Auth Requirements:** Authenticated * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> readonly notInlined: { /** @@ -1031,7 +1049,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -1039,7 +1057,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -1047,7 +1065,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -1055,7 +1073,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -1063,7 +1081,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -1071,7 +1089,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -1079,7 +1097,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> } readonly rest2: { /** @@ -1209,7 +1227,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - detail(id: Uuid): Promise + detail(id: TestModel.ID): Promise /** * Upsert * @@ -1217,7 +1235,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - upsert(id: Uuid, input: TestModel): Promise + upsert(id: TestModel.ID, input: TestModel): Promise /** * Replace * @@ -1225,7 +1243,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - replace(id: Uuid, input: TestModel): Promise + replace(id: TestModel.ID, input: TestModel): Promise /** * Modify * @@ -1233,7 +1251,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modify(id: Uuid, input: Modification): Promise + modify(id: TestModel.ID, input: Modification): Promise /** * Delete * @@ -1241,7 +1259,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - delete(id: Uuid): Promise + delete(id: TestModel.ID): Promise /** * Simplified Modify * @@ -1249,7 +1267,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - simplifiedModify(id: Uuid, input: Partial): Promise + simplifiedModify(id: TestModel.ID, input: Partial): Promise /** * Modify with Diff * @@ -1257,7 +1275,7 @@ export interface Api { * * **Auth Requirements:** No Requirements * */ - modifyWithDiff(id: Uuid, input: Modification): Promise> + modifyWithDiff(id: TestModel.ID, input: Modification): Promise> } } } diff --git a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/server.kt b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/server.kt index 55acd5619..a71bb1ac8 100644 --- a/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/server.kt +++ b/typed/src/test/kotlin/com/lightningkite/lightningserver/typed/sdk/server.kt @@ -89,9 +89,27 @@ private val testEndpoint = explicitApiHttpHandler, HasId<*>?, @Serializable data class TestModel( - override val _id: Uuid = Uuid.random(), + override val _id: ID = ID(), val name: String, -) : HasId + val statusInfo: TestStatusInfo = TestStatusInfo(), +) : HasId { + @JvmInline + @Serializable + value class ID(override val raw: Uuid = Uuid.random()) : TypedId { + override fun toString(): String = raw.toString() + } + + enum class Status { + Active, + Inactive, + Pending, + } + @Serializable + data class TestStatusInfo( + val status: Status = Status.Active, + val updatedAt: Int = 0, + ) +} object Module : ServerBuilder() { val info = Server.database.modelInfo(