rocketraman
04/27/2022, 6:34 PMcommonMain
, frontendMain
, and backendMain
. This is fine for now, but the next iteration of this will likely have desktop, android and iOS targets as well. I'll want a source set or library that has common code across all the frontends (but not backends, as some of that common code has no JVM platform target e.g. GitLive firebase-auth).
Any advice/experience with structuring this kind of project? (More in comments)rocketraman
04/27/2022, 6:35 PMcommonMain
, frontendMain
, backendMain
with all API interfaces but no backend implementations yet. Expose this as a multi-platform library.
2) Backend project depends on the RPC library, implements all the RPC interfaces, and contains the server-side Kvision init.
3) Frontend project which depends on the RPC library, has a commonMain across all the frontends that contains the logic to call the RPCs, and all of the frontend code.
Is this type of project setup possible with KVision?Robert Jaros
04/27/2022, 7:15 PMRobert Jaros
04/27/2022, 7:16 PMrocketraman
04/27/2022, 7:18 PMBig Chungus
04/27/2022, 10:17 PMBig Chungus
04/27/2022, 10:18 PMBig Chungus
04/27/2022, 10:19 PMrocketraman
04/28/2022, 4:32 AMrocketraman
04/28/2022, 6:51 PMshared
module. But I don't want to define my implementations there -- those should go in the backend
module.
Unfortunately, at build time I get:
> Task :shared:compileKotlinBackend FAILED
e: /home/raman/source/foo/shared/build/generated-src/common/com/foo/rpcs/FooRpcServiceManager.kt: (9, 14): Expected class 'FooRpcService' has no actual declaration in module <shared> for JVM
Is there a Gradle incantation I can use to tell the compiler not to expect the actuals for the JVM platform in that module? Or do I have to create implementations in shared which delegate to the real implementations in backend
?Big Chungus
04/28/2022, 6:53 PMRobert Jaros
04/28/2022, 6:55 PM@OptionalExpectation
but isn't it only for annotations?rocketraman
04/28/2022, 6:55 PMrocketraman
04/28/2022, 6:57 PMThis annotation is not applicable to target 'class'
.rocketraman
04/28/2022, 6:58 PM@Target(ANNOTATION_CLASS)
Big Chungus
04/28/2022, 6:58 PMrocketraman
04/28/2022, 7:02 PMexpect
but leaves the actual
implementation to a consumer.Big Chungus
04/28/2022, 7:03 PMBig Chungus
04/28/2022, 7:03 PMrocketraman
04/28/2022, 7:03 PMrocketraman
04/28/2022, 7:06 PMinterface RealIFooRpcService: IFooRpcService
actual class FooRpcService @Inject constructor(delegate: RealIFooRpcService) : IFooRpcService by delegate
Big Chungus
04/29/2022, 8:07 AMBig Chungus
04/29/2022, 8:08 AMrocketraman
04/29/2022, 1:09 PMExpect_without_actual
does not seem to exist, still can't find anything similar.rocketraman
04/29/2022, 1:11 PMApplicationCall
. I change to delegate via a factory passing in call as a parameter, which works great, though its a bit boiler-platey:
typealias RealIFooRpcServiceFactory = (ApplicationCall) -> RealIFooRpcService
interface RealIFooRpcService: IFooRpcService {
val call: ApplicationCall
}
actual class FooRpcService @Inject constructor(factory: RealIFooRpcServiceFactory, call: ApplicationCall)
: IFooRpcService by factory(call)
With that change (and dealing with a bunch of refactoring because smart-casts are not possible across module boundaries, argh -- https://youtrack.jetbrains.com/issue/KT-50534), the new project structure works great.