Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
29471d1
added channel helpers for realtime in the client sdks
ArnabChatterjee20k Dec 18, 2025
3f13cb1
Add Channel support to SDKs and templates
ArnabChatterjee20k Dec 18, 2025
5d19169
reverted changes
ArnabChatterjee20k Dec 18, 2025
b18671f
Refactor Channel references to use NIOCore.Channel and remove unused …
ArnabChatterjee20k Dec 18, 2025
fd57b65
Refractor channel to use builder pattern
ArnabChatterjee20k Dec 19, 2025
3e2402d
updated flutter config
ArnabChatterjee20k Dec 19, 2025
4ff8dd6
Refactor channel handling and subscription logic across multiple temp…
ArnabChatterjee20k Dec 30, 2025
61710ea
Refactor channel and interface definitions for improved clarity and c…
ArnabChatterjee20k Dec 30, 2025
9252cc3
fixed flutter
ArnabChatterjee20k Dec 30, 2025
4c3bef7
updated kotlin and swift
ArnabChatterjee20k Dec 30, 2025
05046c8
fixed swift
ArnabChatterjee20k Dec 30, 2025
9f5f635
Refactor channel method names for consistency across languages
ArnabChatterjee20k Jan 9, 2026
0b840f9
updated bucket
ArnabChatterjee20k Jan 9, 2026
7571e2d
updated react native and web ts
ArnabChatterjee20k Jan 9, 2026
2ed26c9
updated channel and resolved channel validation in web
ArnabChatterjee20k Jan 9, 2026
77147bd
added overloading for type strictness in kotlin
ArnabChatterjee20k Jan 9, 2026
6b30e48
removed leftovers
ArnabChatterjee20k Jan 9, 2026
cd88974
updated leftover
ArnabChatterjee20k Jan 9, 2026
d248155
fixed failing swift tests
ArnabChatterjee20k Jan 9, 2026
b0533b1
fixed failing swift tests
ArnabChatterjee20k Jan 9, 2026
903bdb3
Merge remote-tracking branch 'origin/dat-971' into dat-971
ArnabChatterjee20k Jan 9, 2026
18152a1
revamped realtime channel support for the js realtime
ArnabChatterjee20k Jan 12, 2026
9a74e33
refactor: enhance channel structure and type safety across multiple l…
ArnabChatterjee20k Jan 12, 2026
6d627f3
Merge remote-tracking branch 'origin/master' into dat-971
ArnabChatterjee20k Jan 12, 2026
dde2c4b
refactor: update channel interfaces for improved type safety
ArnabChatterjee20k Jan 12, 2026
3ed2d3e
updated kotlin
ArnabChatterjee20k Jan 12, 2026
163e7fc
updated swift issue
ArnabChatterjee20k Jan 12, 2026
45a8b61
Merge remote-tracking branch 'origin/master' into dat-971
ArnabChatterjee20k Jan 13, 2026
8af59f4
fixed android client build
ArnabChatterjee20k Jan 13, 2026
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
5 changes: 5 additions & 0 deletions src/SDK/Language/Android.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public function getFiles(): array
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/ID.kt',
'template' => '/android/library/src/main/java/io/package/ID.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Channel.kt',
'template' => '/android/library/src/main/java/io/package/Channel.kt.twig',
],
[
'scope' => 'default',
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Query.kt',
Expand Down
5 changes: 5 additions & 0 deletions src/SDK/Language/Apple.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public function getFiles(): array
'destination' => '/Sources/{{ spec.title | caseUcfirst}}/ID.swift',
'template' => 'swift/Sources/ID.swift.twig',
],
[
'scope' => 'default',
'destination' => '/Sources/{{ spec.title | caseUcfirst}}/Channel.swift',
'template' => 'apple/Sources/Channel.swift.twig',
],
[
'scope' => 'default',
'destination' => '/Sources/{{ spec.title | caseUcfirst}}/Query.swift',
Expand Down
10 changes: 10 additions & 0 deletions src/SDK/Language/Flutter.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public function getFiles(): array
'destination' => '/lib/id.dart',
'template' => 'dart/lib/id.dart.twig',
],
[
'scope' => 'default',
'destination' => '/lib/channel.dart',
'template' => 'flutter/lib/channel.dart.twig',
],
[
'scope' => 'default',
'destination' => '/lib/query.dart',
Expand Down Expand Up @@ -290,6 +295,11 @@ public function getFiles(): array
'destination' => '/test/role_test.dart',
'template' => 'dart/test/role_test.dart.twig',
],
[
'scope' => 'default',
'destination' => '/test/channel_test.dart',
'template' => 'flutter/test/src/channel_test.dart.twig',
],
[
'scope' => 'default',
'destination' => '/test/src/cookie_manager_test.dart',
Expand Down
5 changes: 5 additions & 0 deletions src/SDK/Language/ReactNative.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public function getFiles(): array
'destination' => 'src/id.ts',
'template' => 'react-native/src/id.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/channel.ts',
'template' => 'react-native/src/channel.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/query.ts',
Expand Down
5 changes: 5 additions & 0 deletions src/SDK/Language/Web.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public function getFiles(): array
'destination' => 'src/id.ts',
'template' => 'web/src/id.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/channel.ts',
'template' => 'web/src/channel.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/query.ts',
Expand Down
137 changes: 137 additions & 0 deletions templates/android/library/src/main/java/io/package/Channel.kt.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package {{ sdk.namespace | caseDot }}

// The result of building the channel.
class ResolvedChannel(private val value: String) {
override fun toString(): String {
return value
}
}

// Helper for normalizing IDs
Comment thread
abnegate marked this conversation as resolved.
Outdated
private fun normalize(id: String): String {
val trimmed = id.trim()
return if (trimmed.isEmpty()) "*" else trimmed
}

// Interface for actionable channels
interface Actionable {
val channel: String
fun create(): ResolvedChannel
fun update(): ResolvedChannel
fun delete(): ResolvedChannel
}

interface IDatabase {
Comment thread
abnegate marked this conversation as resolved.
Outdated
fun collection(id: String = "*"): ICollection
}

interface ICollection {
fun document(id: String = "*"): IDocument
}

interface IDocument : Actionable

interface ITablesDB {
fun table(id: String = "*"): ITable
}

interface ITable {
fun row(id: String = "*"): IRow
}

interface IRow : Actionable

interface IBucket {
fun file(id: String = "*"): IFile
}

interface IFile : Actionable

interface IFunction {
fun execution(id: String = "*"): IExecution
}

interface IExecution : Actionable

private class ChannelBuilder(
private val segments: List<String>
) : IDatabase, ICollection, IDocument,
ITablesDB, ITable, IRow,
IBucket, IFile,
IFunction, IExecution, Actionable {

companion object {
fun start(segments: List<String>) = ChannelBuilder(segments)
}

private fun next(segment: String, id: String): ChannelBuilder {
return ChannelBuilder(segments + listOf(segment, normalize(id)))
}

override fun collection(id: String): ICollection =
next("collections", id)

override fun document(id: String): IDocument =
next("documents", id)

override fun table(id: String): ITable =
next("tables", id)

override fun row(id: String): IRow =
next("rows", id)

override fun file(id: String): IFile =
next("files", id)

override fun execution(id: String): IExecution =
next("executions", id)

override val channel: String
get() = segments.joinToString(".")

override fun create(): ResolvedChannel =
ResolvedChannel("$channel.create")

override fun update(): ResolvedChannel =
ResolvedChannel("$channel.update")

override fun delete(): ResolvedChannel =
ResolvedChannel("$channel.delete")

override fun toString(): String = channel
}

class Channel private constructor() {

companion object {

fun database(id: String = "*"): IDatabase =
ChannelBuilder.start(listOf("databases", normalize(id)))

fun tablesdb(id: String = "*"): ITablesDB =
ChannelBuilder.start(listOf("tablesdb", normalize(id)))

fun buckets(id: String = "*"): IBucket =
ChannelBuilder.start(listOf("buckets", normalize(id)))

fun functions(id: String = "*"): IFunction =
ChannelBuilder.start(listOf("functions", normalize(id)))

fun teams(id: String = "*"): Actionable =
ChannelBuilder.start(listOf("teams", normalize(id)))

fun memberships(id: String = "*"): Actionable =
ChannelBuilder.start(listOf("memberships", normalize(id)))
Comment thread
abnegate marked this conversation as resolved.
Outdated

fun account(userId: String = ""): String {
val id = normalize(userId)
return if (id == "*") "account" else "account.$id"
}

// Global events
const val documents = "documents"
const val rows = "rows"
const val files = "files"
const val executions = "executions"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package {{ sdk.namespace | caseDot }}.services

import {{ sdk.namespace | caseDot }}.Service
import {{ sdk.namespace | caseDot }}.Client
import {{ sdk.namespace | caseDot }}.Actionable
import {{ sdk.namespace | caseDot }}.ResolvedChannel
import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.title | caseUcfirst }}Exception
import {{ sdk.namespace | caseDot }}.extensions.forEachAsync
import {{ sdk.namespace | caseDot }}.extensions.fromJson
Expand Down Expand Up @@ -109,6 +111,30 @@ class Realtime(client: Client) : Service(client), CoroutineScope {
else -> 60000L
}

/**
* Convert channel value to string
* Checks if it's an Actionable instance (use .channel),
* then ResolvedChannel (use .toString()),
* otherwise treats as string
*/
private fun channelToString(channel: Any): String {
return when {
channel is String -> channel
channel is Actionable -> channel.channel
channel is ResolvedChannel -> channel.toString()
else -> channel.toString()
}
}

fun subscribe(
vararg channels: Any,
Comment thread
abnegate marked this conversation as resolved.
Outdated
callback: (RealtimeResponseEvent<Any>) -> Unit,
) = subscribe(
channels = channels.map { channelToString(it) }.toTypedArray(),
Any::class.java,
callback
)

fun subscribe(
vararg channels: String,
callback: (RealtimeResponseEvent<Any>) -> Unit,
Expand All @@ -118,6 +144,18 @@ class Realtime(client: Client) : Service(client), CoroutineScope {
callback
)

fun <T> subscribe(
vararg channels: Any,
payloadType: Class<T>,
callback: (RealtimeResponseEvent<T>) -> Unit,
): RealtimeSubscription {
return subscribe(
channels = channels.map { channelToString(it) }.toTypedArray(),
payloadType = payloadType,
callback = callback
)
}

fun <T> subscribe(
vararg channels: String,
payloadType: Class<T>,
Expand Down
Loading
Loading