Skip to content

Commit

Permalink
Allow for manual cursor control (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
cedrickcooke authored Nov 2, 2022
1 parent 3283d73 commit 3dddf9f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
16 changes: 16 additions & 0 deletions core/src/jsMain/kotlin/Cursor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ public open class Cursor internal constructor(
public val primaryKey: dynamic
get() = cursor.primaryKey

public fun `continue`() {
cursor.`continue`()
}

public fun advance(count: Int) {
cursor.advance(count)
}

public fun `continue`(key: Key) {
cursor.`continue`(key.toJs())
}

public fun continuePrimaryKey(key: Key, primaryKey: Key) {
cursor.continuePrimaryKey(key.toJs(), primaryKey.toJs())
}

public enum class Direction(internal val constant: String) {
Next("next"),
NextUnique("nextunique"),
Expand Down
39 changes: 36 additions & 3 deletions core/src/jsMain/kotlin/Transaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.juul.indexeddb
import com.juul.indexeddb.external.IDBCursor
import com.juul.indexeddb.external.IDBRequest
import com.juul.indexeddb.external.IDBTransaction
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
Expand Down Expand Up @@ -46,37 +45,71 @@ public open class Transaction internal constructor(
}
}

@Deprecated(
"In the future, `autoContinue` will be a required parameter.",
ReplaceWith("openCursor(query, direction, cursorStart, autoContinue = true)"),
)
public suspend fun Queryable.openCursor(
query: Key? = null,
direction: Cursor.Direction = Cursor.Direction.Next,
cursorStart: CursorStart? = null,
): Flow<CursorWithValue> = openCursor(
query,
direction,
cursorStart,
autoContinue = true,
)

public suspend fun Queryable.openCursor(
query: Key? = null,
direction: Cursor.Direction = Cursor.Direction.Next,
cursorStart: CursorStart? = null,
autoContinue: Boolean,
): Flow<CursorWithValue> = openCursorImpl(
query,
direction,
cursorStart,
open = this::requestOpenCursor,
wrap = ::CursorWithValue,
autoContinue,
)

@Deprecated(
"In the future, `autoContinue` will be a required parameter.",
ReplaceWith("openKeyCursor(query, direction, cursorStart, autoContinue = true)"),
)
public suspend fun Queryable.openKeyCursor(
query: Key? = null,
direction: Cursor.Direction = Cursor.Direction.Next,
cursorStart: CursorStart? = null,
): Flow<Cursor> = openKeyCursor(
query,
direction,
cursorStart,
autoContinue = true,
)

public suspend fun Queryable.openKeyCursor(
query: Key? = null,
direction: Cursor.Direction = Cursor.Direction.Next,
cursorStart: CursorStart? = null,
autoContinue: Boolean,
): Flow<Cursor> = openCursorImpl(
query,
direction,
cursorStart,
open = this::requestOpenKeyCursor,
wrap = ::Cursor,
autoContinue,
)

@OptIn(ExperimentalCoroutinesApi::class)
private suspend fun <T : Cursor, U : IDBCursor> openCursorImpl(
query: Key?,
direction: Cursor.Direction,
cursorStart: CursorStart?,
open: (Key?, Cursor.Direction) -> Request<U?>,
wrap: (U) -> T,
autoContinue: Boolean,
): Flow<T> = callbackFlow {
var cursorStartAction = cursorStart
val request = open(query, direction).request
Expand All @@ -89,7 +122,7 @@ public open class Transaction internal constructor(
} else if (cursor != null) {
val result = trySend(wrap(cursor))
when {
result.isSuccess -> cursor.`continue`()
result.isSuccess -> if (autoContinue) cursor.`continue`()
result.isFailure -> channel.close(IllegalStateException("Send failed. Did you suspend illegally?"))
result.isClosed -> channel.close()
}
Expand Down
6 changes: 3 additions & 3 deletions core/src/jsTest/kotlin/Samples.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Samples {
val charlie = database.transaction("customers") {
objectStore("customers")
.index("name")
.openCursor()
.openCursor(autoContinue = true)
.map { it.value as Customer }
.first { it.age < 32 }
}
Expand All @@ -73,7 +73,7 @@ class Samples {
val skipTwoYoungest = database.transaction("customers") {
objectStore("customers")
.index("age")
.openCursor(cursorStart = CursorStart.Advance(2))
.openCursor(cursorStart = CursorStart.Advance(2), autoContinue = true)
.map { it.value as Customer }
.map { it.name }
.toList()
Expand All @@ -83,7 +83,7 @@ class Samples {
val skipUntil33 = database.transaction("customers") {
objectStore("customers")
.index("age")
.openCursor(cursorStart = CursorStart.Continue(Key(33)))
.openCursor(cursorStart = CursorStart.Continue(Key(33)), autoContinue = true)
.map { it.value as Customer }
.map { it.name }
.toList()
Expand Down

0 comments on commit 3dddf9f

Please sign in to comment.