Closed RyoichiroNagami closed 1 day ago
@marcprux
I'm reading the source now and looking at it with a few modifications, but would like to discuss the direction.
I'm looking at two patterns that I'm considering as ways to implement this
The first is. It's a form that follows the Supabase swift call. I could reproduce this by mimicking the existing source.
public class SupabaseClient {
...etc codes
public func rpc(_ fn: String) async throws -> PostgrestResponse<Void> {
PostgrestResponse(result: await client.postgrest.rpc(fn))
}
}
public struct PostgrestResponse<T> {
private let result: io.github.jan.supabase.postgrest.result.PostgrestResult
init(result: io.github.jan.supabase.postgrest.result.PostgrestResult) {
self.result = result
}
// dummy function
// supabase-kt rpc not call execute
public func execute() -> PostgrestResponse {
return self
}
public var count: Int? {
result.countOrNull()?.toInt()
}
public var value: T? {
nil
}
public var data: Data {
let res: String = result.data
return res.data(using: String.Encoding.utf8) ?? Data()
}
//public let response: HTTPURLResponse
//public let count: Int?
//public let value: T
// public var status: Int {
// response.statusCode
// }
}
let value = try await client.rpc("function_name").execute().data
let dto: CodableStructureName = try JSONDecoder().decode(CodableStructureName.self, from: value)
I don't need the execute process after the ppc function call on the kotlin side.
This would require redundancy in the single point code.
// dummy function
// supabase-kt rpc not call execute
public func execute() -> PostgrestResponse {
return self
}
It could be implemented by adding an execute process to PostgrestResponse to return its own value, but I'm having a bit of trouble with that since it's a completely useless process.
If you want to solve that, I wonder if you could extend SupabaseClient and solve it in the following way? I think.
#if !SKIP
extension SupabaseClient {
public func skipRpc(_ fn: String) async throws -> Data {
return try await self.rpc(fn).execute().data
}
}
#endif
#if SKIP
public class SupabaseClient {
public func skipRpc(fn: String) async -> Data {
// SKIP INSERT:
// client.postgrest.rpc(fn).data().data(using = StringEncoding.utf8) ?: Data()
}
}
#endif
let value = try await client.skipRpc("function_name")
let res: CodableStructureName = try JSONDecoder().decode(CodableStructureName.self, from: value!)
I feel like if you don't write documentation, they won't know how to use it, and it takes a little time for the user side to understand it.
Honestly, I could implement it either way, I just want to make sure we have a policy. Which one do you think is better?
*Personally, I think Plan1 is fine.
@marcprux @aabewhite
If you find out anything, I'd love to know.
I'm writing a process to call supabase rpc when there is a parameter, but I can't get it to work.
public func rpc(_ fn: String) async throws -> PostgrestResponse<Void> {
PostgrestResponse(result: await client.postgrest.rpc(fn))
}
open suspend fun rpc(fn: String, params: Any): PostgrestResponse<Unit> = Async.run l@{
return@l PostgrestResponse(result = client.postgrest.rpc(fn, params))
}
SkipSupabase.kt:71:62 None of the following candidates is applicable:
I tried it with similar values, using the korlin supabase docs as a guide with using SKIP INSERT:
I'm getting the same error:'-(
https://docs-ajzc160j5-supabase.vercel.app/docs/reference/kotlin/installing
My knowledge of Kotlin serialization was vague. I will read this document carefully and try again tomorrow.
It is surprising that the function is not getting matched. I wonder if it might have to do with the parameter being a reified type:
suspend inline fun <reified T : Any> Postgrest.rpc(
function: String,
parameters: T,
noinline request: RpcRequestBuilder.() -> Unit = {},
): PostgrestResult
You should be able to still call it with an Any
, though.
What happens if you manually specify the argument names? E.g.:
supabase.postgrest.rpc(function = "echo_city", parameters = rpcParams)
It might help if you look at the gradle log and paste the full context of the error, which might give other hints about the problem.
@marcprux The error when embedding the kotlin code directly was still that there was no type consistency!
supabase.postgrest.rpc(function = "echo_city", parameters = rpcParams)
I embedded the above code directly and got this output.
SkipSupabase.kt:101:62 None of the following candidates is applicable:
SkipSupabase.kt:110:59 Argument type mismatch: actual type is 'skip.supabase.City', but 'kotlinx.serialization.json.JsonObject' was expected.
Sorry, I just didn't have much time to work on it today.
I'm in the process of setting it up so I can get the gradle logs.
memo If you set the parameter to the following, the compile will pass
kotlinx.serialization.json.JsonObject
If there is no type biosynthesis in the calling process, it will result in a compile error.
@marcprux Is the following the correct way to take Grade logs?
gradle -p . /Android launchDebug
gradle -p ./Android launchDebug
[1/1] Compiling plugin Create SkipLink
[2/2] Compiling plugin skipstone
Building for debugging...
[2/5] Write swift-version--58304C5D6DBC2206.txt
Build complete! (0.22s)
Kotlin does not yet support 22 JDK target, falling back to Kotlin JVM_21 JVM target
> Task :skip-plugins:compileKotlin UP-TO-DATE
Kotlin does not yet support 22 JDK target, falling back to Kotlin JVM_21 JVM target
FAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting the sdk.dir path in your project's local properties file at '/Users/nagamiryoichiro/Documents/work/git/KochiDempApp/mow-karte-educator/project-name/Android/local.properties'.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.10.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 1s
5 actionable tasks: 1 executed, 4 up-to-date
I tried to check, but the version of the JVM doesn't seem to be supported,
SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting the sdk.dir path in your project's local properties file at '/Users/nagamiryoichiro/Documents/work/git/KochiDempApp/mow-karte-educator/project-name/Android/local.properties'.
Try setting your ANDROID_HOME
environment with something like:
export ANDROID_HOME=$HOME/Library/Android/sdk
I'm in the process of setting it up so I can get the gradle logs.
You should be able to view the Gradle logs directly from within Xcode by clicking on the error that mentions the log. It should open as a text file within Xcode.
I just implemented basic RPC function calling in 0.0.4 (in https://github.com/skiptools/skip-supabase/pull/5). Note that it doesn't yet support passing parameters to RPC functions, nor does it support returning a Codable result (but you can get the data
of the result and parse it yourself).
Hopefully that is enough to get you started.
@marcprux Thank you.
But I also plan to use rpc with parameters.
I will investigate once I get the latest version so that I can continue to call it there as well.
PS. I guess it's the time difference, but sorry for not getting back to you quicker.
@marcprux modified to call rpc function with parameter and created PR
However, it is not perfect, and the
The parameter type only supports Dictionary<String, String>.
Test code is included, but now it fails because the rpc function is not set on the supabase side.
However, I have successfully called the rpc function in my environment as shown in the image attached in the PR.
As far as I remember, the Supabase swift library didn't support mixed types yet for RPC function parameters, but you could mix them by using an AnyJSON dictionary. I don't have access to the code right now to confirm but in case it helps, it could save some time debugging the issue with mixed data types
Test code is included, but now it fails because the rpc function is not set on the supabase side.
Look great! Can you let me know how you define the public.rpc_test_with_param(testParam1, testParam2)
function? I can create the same one in the demo schema so the test cases pass.
but you could mix them by using an AnyJSON dictionary
And for the record, we do have an equivalent AnyJSON
type for the Kotlin side that should be compatible with the Swift side (and thus can be used with Skip without any further coercion). But as you can see, dict2JsonObject
is left as an "exercise for the reader".
I tried implementing dict2JsonObject
but I have no idea how to do it. What are the steps to do it?
I tried implementing
dict2JsonObject
but I have no idea how to do it. What are the steps to do it?
If I knew, I would have implemented it. 🤷
I guess I would walk through the AnyJSON
dict and use the kotlinx.serialization.json.JsonObject
API to build up a JsonObject equivalent of the keys, values, arrays, and null and stuff. It should be fairly rote, but just require some trial-and-error and good test cases.
@marcprux
Look great! Can you let me know how you define the public.rpc_test_with_param(testParam1, testParam2) function? I can create the same one in the demo schema so the test cases pass.
I just checked the Github history and it looks like you have the rpc function ready for us
Thank you very much.
I've merged https://github.com/skiptools/skip-supabase/pull/7 and released skip-supabase 0.0.5. Thanks for all the work, and we look forward to future contributions!
Currently
the supabase-skip package does not support the rpc function
Goal
Use supabase-skip package to call rpc function
Implementation Issues
Different way to call supabase rpc function in swift and kotlin example: swift requires a call to execute function when calling rpc function, but kotlin does not
The expected return type of PostgrestResponse.value is Generics, but skip-tool does not currently support decoding using Generics. skip-tools decode
Supabase Document