Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Add the dependency to your `build.gradle.kts`:

```kotlin
dependencies {
implementation("dev.kdriver:nextjs:0.1.5")
implementation("dev.kdriver:nextjs:0.2.0")
}
```

Expand All @@ -26,10 +26,10 @@ dependencies {
fun main() = runBlocking {
val browser = createBrowser(this)
val tab = browser.get("about:blank")
val allObjects = tab.capturePushesFromJs { // Or `capturePushesFromHtml`
val resolvedObject = tab.capturePushesFromJs { // Or `capturePushesFromHtml`
tab.get(url)
fetchAll()
resolvedNextF() // Resolves Next.js specific data using RSC resolver
}
println("Raw captured objects: ${allObjects.size}")
println(resolvedObject)
}
```
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {

allprojects {
group = "dev.kdriver"
version = "0.1.5"
version = "0.2.0"
project.ext.set("url", "https://github.com/cdpdriver/kdriver-nextjs")
project.ext.set("license.name", "Apache 2.0")
project.ext.set("license.url", "https://www.apache.org/licenses/LICENSE-2.0.txt")
Expand Down
24 changes: 24 additions & 0 deletions nextjs-engine/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,29 @@ mavenPublishing {
}

kotlin {
// Tiers are in accordance with <https://kotlinlang.org/docs/native-target-support.html>
// Tier 1
macosX64()
macosArm64()
iosSimulatorArm64()
iosX64()

// Tier 2
linuxX64()
linuxArm64()
watchosSimulatorArm64()
watchosX64()
watchosArm32()
watchosArm64()
tvosSimulatorArm64()
tvosX64()
tvosArm64()
iosArm64()

// Tier 3
mingwX64()
watchosDeviceArm64()

// jvm & js
jvmToolchain(21)
jvm {
Expand Down Expand Up @@ -63,6 +86,7 @@ kotlin {
val commonMain by getting {
dependencies {
api(libs.kotlinx.serialization.json)
api(project(":nextjs-rsc"))
}
}
val jvmTest by getting {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package dev.kdriver.nextjs

import dev.kdriver.nextjs.rsc.FlightPayloadResolver
import kotlinx.serialization.json.*

/**
* Abstract implementation of [CapturedPushes] that provides common functionality for capturing and fetching push events.
*/
abstract class AbstractCapturedPushes : CapturedPushes {

/**
* Provides the next set of push events as a [JsonArray].
*
* @return A [JsonArray] containing the next push events.
*/
abstract suspend fun provideNextF(): JsonArray
override suspend fun resolvedNextF(): JsonElement {
val resolver = FlightPayloadResolver()
resolver.parsePayloads(provideNextF())
return resolver.getResolvedRoot() ?: error("No resolved root found")
}

@Deprecated("Use resolvedNextF() for single resolved element.")
override suspend fun fetchAll(): List<JsonElement> {
val jsonArray = provideNextF()
val results = mutableListOf<JsonElement>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
package dev.kdriver.nextjs

import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement

/**
* Interface for capturing and fetching push events from a Next.js application.
*/
interface CapturedPushes {

/**
* Provides the next set of push events as a [JsonArray].
*
* @return A [JsonArray] containing the next push events.
*/
suspend fun provideNextF(): JsonArray

/**
* Resolves the next push event into a single JSON element.
*
* @return A [JsonElement] representing the resolved next push event.
*/
suspend fun resolvedNextF(): JsonElement

/**
* Fetches all captured push events as a list of JSON elements.
*
* @return A list of JSON elements representing the captured push events.
*/
@Deprecated("Use resolvedNextF() for single resolved element.")
suspend fun fetchAll(): List<JsonElement>

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlin.test.assertIs
class AbstractCapturedPushesTest {

@Test
fun testFetchAll_parsesMultipleJsonElementsFromPayloads() = runTest {
fun testDeprecatedFetchAll_parsesMultipleJsonElementsFromPayloads() = runTest {
val sut = object : AbstractCapturedPushes() {
override suspend fun provideNextF(): JsonArray {
return Serialization.json.parseToJsonElement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,35 @@ import kotlin.test.assertEquals
import kotlin.test.assertIs

class CapturedPushesFromHtmlTest {
@Test
fun testResolvedFromHtml() = runTest {
val html = """
<html>
<head>
<script>
self.__next_f = [];
self.__next_f.push([1, "0:\"${'$'}L1\"\n"])
</script>
</head>
<body>
<script>
self.__next_f.push([1, "1:I[\"(app-pages-browser)/./node_modules/next/...\",[\"....\"],\"\"]\n"])
self.__next_f.push([1, "2:[\"$\",\"div\",null,{\"className\":\"container\",\"children\":\"${'$'}L3\"}]\n"])
self.__next_f.push([1, "3:[\"$\",\"p\",null,{\"children\":\"Hello World\"}]\n"])
</script>
</body>
</html>
""".trimIndent()

val sut = CapturedPushesFromHtml(html)

val result = sut.resolvedNextF()

println(result)
}

@Test
fun testFetchAll_parsesMultipleJsonElementsFromPayloads() = runTest {
fun testDeprecatedFetchAll_parsesMultipleJsonElementsFromPayloads() = runTest {
val html = """
<html>
<head>
Expand Down
104 changes: 104 additions & 0 deletions nextjs-rsc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
plugins {
alias(libs.plugins.multiplatform)
alias(libs.plugins.serialization)
alias(libs.plugins.kover)
alias(libs.plugins.detekt)
alias(libs.plugins.dokka)
alias(libs.plugins.ksp)
alias(libs.plugins.maven)
}

mavenPublishing {
publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.CENTRAL_PORTAL)
signAllPublications()
pom {
name.set("nextjs-rsc")
description.set("React Server Components (RSC) payload parser for kdriver.")
url.set(project.ext.get("url")?.toString())
licenses {
license {
name.set(project.ext.get("license.name")?.toString())
url.set(project.ext.get("license.url")?.toString())
}
}
developers {
developer {
id.set(project.ext.get("developer.id")?.toString())
name.set(project.ext.get("developer.name")?.toString())
email.set(project.ext.get("developer.email")?.toString())
url.set(project.ext.get("developer.url")?.toString())
}
}
scm {
url.set(project.ext.get("scm.url")?.toString())
}
}
}

kotlin {
// Tiers are in accordance with <https://kotlinlang.org/docs/native-target-support.html>
// Tier 1
macosX64()
macosArm64()
iosSimulatorArm64()
iosX64()

// Tier 2
linuxX64()
linuxArm64()
watchosSimulatorArm64()
watchosX64()
watchosArm32()
watchosArm64()
tvosSimulatorArm64()
tvosX64()
tvosArm64()
iosArm64()

// Tier 3
mingwX64()
watchosDeviceArm64()

// jvm & js
jvmToolchain(21)
jvm {
testRuns.named("test") {
executionTask.configure {
useJUnitPlatform()
}
}
}
js {
generateTypeScriptDefinitions()
binaries.library()
nodejs()
browser()
}

applyDefaultHierarchyTemplate()
sourceSets {
all {
languageSettings.apply {
optIn("kotlin.js.ExperimentalJsExport")
}
}
val commonMain by getting {

Check warning on line 85 in nextjs-rsc/build.gradle.kts

View check run for this annotation

codefactor.io / CodeFactor

nextjs-rsc/build.gradle.kts#L85

Private property `commonMain` is unused. (detekt.UnusedPrivateProperty)
dependencies {
api(libs.kotlinx.serialization.json)
}
}
val jvmTest by getting {

Check warning on line 90 in nextjs-rsc/build.gradle.kts

View check run for this annotation

codefactor.io / CodeFactor

nextjs-rsc/build.gradle.kts#L90

Private property `jvmTest` is unused. (detekt.UnusedPrivateProperty)
dependencies {
implementation(kotlin("test"))
implementation(libs.tests.mockk)
implementation(libs.tests.coroutines)
}
}
}
}

detekt {
buildUponDefaultConfig = true
config.setFrom("${rootProject.projectDir}/detekt.yml")
source.from(file("src/commonMain/kotlin"))
}
Loading