diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml new file mode 100644 index 00000000..68806cf6 --- /dev/null +++ b/.github/workflows/docs-deploy.yml @@ -0,0 +1,52 @@ +name: Deploy Docs + +on: + push: + branches: [ 'main' ] + +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + - uses: actions/cache@v3 + with: + path: ~/.konan + key: ${{ runner.os }}-${{ hashFiles('**/.lock') }} + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Build Docs + run: | + ./gradlew \ + -PGITHUB_PUBLISH_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + dokkaGenerate + shell: bash + - name: Upload static files as artifact + id: deployment + uses: actions/upload-pages-artifact@v3 + with: + path: build/dokka/html + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index da36a00a..17e391ee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,9 @@ +import com.sun.net.httpserver.HttpExchange +import com.sun.net.httpserver.HttpServer +import java.net.InetSocketAddress +import java.net.URLDecoder +import java.nio.file.Files + plugins { alias(libs.plugins.jetbrainsCompose) apply false alias(libs.plugins.compose.compiler) apply false @@ -16,6 +22,8 @@ plugins { alias(libs.plugins.kotlinter) apply false alias(libs.plugins.keeper) apply false alias(libs.plugins.kotlin.atomicfu) apply false + id("org.jetbrains.dokka") version libs.versions.dokkaBase + id("dokka-convention") } allprojects { @@ -54,6 +62,58 @@ subprojects { version = LIBRARY_VERSION } -tasks.register("clean") { +tasks.getByName("clean") { delete(rootProject.layout.buildDirectory) } + +// Merges individual module docs into a single HTML output +dependencies { + dokka(project(":core:")) + dokka(project(":connectors:supabase")) + dokka(project(":compose:")) +} + +dokka { + moduleName.set("PowerSync Kotlin") +} + +// Serve the generated Dokka documentation using a simple HTTP server +// File changes are not watched here +tasks.register("serveDokka") { + group = "dokka" + dependsOn("dokkaGenerate") + doLast { + val server = HttpServer.create(InetSocketAddress(0), 0) + val root = file("build/dokka/html") + + val handler = + com.sun.net.httpserver.HttpHandler { exchange: HttpExchange -> + val rawPath = exchange.requestURI.path + val cleanPath = URLDecoder.decode(rawPath.removePrefix("/"), "UTF-8") + val requestedFile = File(root, cleanPath) + + val file = + when { + requestedFile.exists() && !requestedFile.isDirectory -> requestedFile + else -> File(root, "index.html") // fallback + } + + val contentType = + Files.probeContentType(file.toPath()) ?: "application/octet-stream" + val bytes = file.readBytes() + exchange.responseHeaders.add("Content-Type", contentType) + exchange.sendResponseHeaders(200, bytes.size.toLong()) + exchange.responseBody.use { it.write(bytes) } + } + + server.createContext("/", handler) + server.executor = null + server.start() + + println("📘 Serving Dokka docs at http://localhost:${server.address.port}/") + println("Press Ctrl+C to stop.") + + // Keep the task alive + Thread.currentThread().join() + } +} diff --git a/compose/build.gradle.kts b/compose/build.gradle.kts index dd16112c..aabc9354 100644 --- a/compose/build.gradle.kts +++ b/compose/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.compose.compiler) alias(libs.plugins.kotlinter) id("com.powersync.plugins.sonatype") + id("dokka-convention") } kotlin { @@ -45,3 +46,7 @@ android { } setupGithubRepository() + +dokka { + moduleName.set("PowerSync Compose") +} diff --git a/connectors/supabase/build.gradle.kts b/connectors/supabase/build.gradle.kts index 5763e39d..4de82464 100644 --- a/connectors/supabase/build.gradle.kts +++ b/connectors/supabase/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.androidLibrary) alias(libs.plugins.kotlinter) id("com.powersync.plugins.sonatype") + id("dokka-convention") } kotlin { @@ -51,3 +52,7 @@ android { } setupGithubRepository() + +dokka { + moduleName.set("PowerSync Supabase Connector") +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index c1165245..87a44af8 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -19,6 +19,7 @@ plugins { id("com.powersync.plugins.sharedbuild") alias(libs.plugins.mokkery) alias(libs.plugins.kotlin.atomicfu) + id("dokka-convention") } val binariesFolder = project.layout.buildDirectory.dir("binaries/desktop") @@ -295,3 +296,7 @@ tasks.withType { } } setupGithubRepository() + +dokka { + moduleName.set("PowerSync Core") +} diff --git a/core/src/androidMain/kotlin/BuildConfig.kt b/core/src/androidMain/kotlin/BuildConfig.kt index 08f66eec..f52fcaa8 100644 --- a/core/src/androidMain/kotlin/BuildConfig.kt +++ b/core/src/androidMain/kotlin/BuildConfig.kt @@ -1,5 +1,5 @@ @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") -public actual object BuildConfig { - public actual val isDebug: Boolean +internal actual object BuildConfig { + actual val isDebug: Boolean get() = com.powersync.BuildConfig.DEBUG } diff --git a/core/src/appleMain/kotlin/BuildConfig.kt b/core/src/appleMain/kotlin/BuildConfig.kt index 1005f70c..f18cc336 100644 --- a/core/src/appleMain/kotlin/BuildConfig.kt +++ b/core/src/appleMain/kotlin/BuildConfig.kt @@ -2,7 +2,7 @@ import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") -public actual object BuildConfig { +internal actual object BuildConfig { @OptIn(ExperimentalNativeApi::class) - public actual val isDebug: Boolean = Platform.isDebugBinary + actual val isDebug: Boolean = Platform.isDebugBinary } diff --git a/core/src/commonMain/kotlin/BuildConfig.kt b/core/src/commonMain/kotlin/BuildConfig.kt index 599450e5..81f23796 100644 --- a/core/src/commonMain/kotlin/BuildConfig.kt +++ b/core/src/commonMain/kotlin/BuildConfig.kt @@ -1,4 +1,4 @@ @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") -public expect object BuildConfig { - public val isDebug: Boolean +internal expect object BuildConfig { + val isDebug: Boolean } diff --git a/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt b/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt index b9038e9e..61c92b39 100644 --- a/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt +++ b/core/src/commonMain/kotlin/com/powersync/db/schema/Schema.kt @@ -2,6 +2,12 @@ package com.powersync.db.schema import kotlinx.serialization.Serializable +/** + * The schema used by the database. + * + * The implementation uses the schema as a "VIEW" on top of JSON data. + * No migrations are required on the client. + */ public data class Schema( val tables: List, ) { @@ -9,8 +15,17 @@ public data class Schema( validate() } + /** + * Secondary constructor to create a schema with a variable number of tables. + */ public constructor(vararg tables: Table) : this(tables.asList()) + /** + * Validates the schema by ensuring there are no duplicate table names + * and that each table is valid. + * + * @throws AssertionError if duplicate table names are found. + */ public fun validate() { val tableNames = mutableSetOf() tables.forEach { table -> diff --git a/core/src/jvmMain/kotlin/BuildConfig.kt b/core/src/jvmMain/kotlin/BuildConfig.kt index c3260bed..86924a14 100644 --- a/core/src/jvmMain/kotlin/BuildConfig.kt +++ b/core/src/jvmMain/kotlin/BuildConfig.kt @@ -1,12 +1,12 @@ @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") -public actual object BuildConfig { +internal actual object BuildConfig { /* To debug on the JVM, you can: - Set the com.powersync.debug property with System.setProperty("com.powersync.debug", true) BEFORE calling any powersync API. - Start your java program with the -Dcom.powersync.debug=true command line argument. - Set the POWERSYNC_JVM_DEBUG environment variable to "true" before starting your program. */ - public actual val isDebug: Boolean = + actual val isDebug: Boolean = System.getProperty("com.powersync.debug") == "true" || System.getenv("POWERSYNC_JVM_DEBUG") == "true" } diff --git a/docs/assets/discord.svg b/docs/assets/discord.svg new file mode 100644 index 00000000..727a2e3e --- /dev/null +++ b/docs/assets/discord.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/docs/assets/doc-styles.css b/docs/assets/doc-styles.css new file mode 100644 index 00000000..3b85dcab --- /dev/null +++ b/docs/assets/doc-styles.css @@ -0,0 +1,34 @@ +:root { + --dokka-logo-image-url: url('../images/powersync-logo.png'); +} + +.footer-container { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 8px; + margin-top: auto; + box-sizing: border-box; + background-color: var(--footer-background); + color: var(--footer-font-color); +} + +.footer-title { + margin-bottom: 8px; +} + +.footer-column { + flex: 1 1 0; + align-items: center; + text-align: center; + min-width: 300px; + padding: 8px; +} + +.footer-icon-row { + display: flex; + justify-content: center; + align-items: center; + gap: 8px; + flex-wrap: wrap; + } diff --git a/docs/assets/dokka-templates/includes/footer.ftl b/docs/assets/dokka-templates/includes/footer.ftl new file mode 100644 index 00000000..36483bb6 --- /dev/null +++ b/docs/assets/dokka-templates/includes/footer.ftl @@ -0,0 +1,48 @@ +<#macro display> +<@template_cmd name="pathToRoot"> +
+ + + + +
+ + \ No newline at end of file diff --git a/docs/assets/github.svg b/docs/assets/github.svg new file mode 100644 index 00000000..b41d8046 --- /dev/null +++ b/docs/assets/github.svg @@ -0,0 +1,22 @@ + + + + + + diff --git a/docs/assets/linkedin.svg b/docs/assets/linkedin.svg new file mode 100644 index 00000000..bf74d81f --- /dev/null +++ b/docs/assets/linkedin.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/docs/assets/logo-icon.svg b/docs/assets/logo-icon.svg new file mode 100644 index 00000000..f361e6d9 --- /dev/null +++ b/docs/assets/logo-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/assets/powersync-logo.png b/docs/assets/powersync-logo.png new file mode 100644 index 00000000..8d7111c8 Binary files /dev/null and b/docs/assets/powersync-logo.png differ diff --git a/docs/assets/web.svg b/docs/assets/web.svg new file mode 100644 index 00000000..e67cca52 --- /dev/null +++ b/docs/assets/web.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/assets/x.svg b/docs/assets/x.svg new file mode 100644 index 00000000..d30639eb --- /dev/null +++ b/docs/assets/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/assets/youtube.svg b/docs/assets/youtube.svg new file mode 100644 index 00000000..9245ed8c --- /dev/null +++ b/docs/assets/youtube.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/gradle.properties b/gradle.properties index c5c974e7..f1a61d99 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,3 +31,5 @@ POM_DEVELOPER_ID=powersync POM_DEVELOPER_NAME=PowerSync SDK Team POM_DEVELOPER_URL=https://powersync.com/ POM_DEVELOPER_EMAIL=support@journeyapps.com +#Dokka +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 336a60e3..bd5f8496 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,7 @@ android-minSdk = "24" android-targetSdk = "35" android-compileSdk = "35" configurationAnnotations = "0.9.5" +dokkaBase = "2.0.0" gradleDownloadTask = "5.5.0" java = "17" idea = "243.22562.218" # Meerkat | 2024.3.1 (see https://plugins.jetbrains.com/docs/intellij/android-studio-releases-list.html) @@ -56,6 +57,7 @@ junitVersion = "1.2.1" [libraries] configuration-annotations = { module = "co.touchlab.skie:configuration-annotations", version.ref = "configurationAnnotations" } +dokka-gradle-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokkaBase" } gradle-download-task = { module = "de.undercouch:gradle-download-task", version.ref = "gradleDownloadTask" } kermit = { module = "co.touchlab:kermit", version.ref = "kermit" } kermit-test = { module = "co.touchlab:kermit-test", version.ref = "kermit" } diff --git a/plugins/build-plugin/build.gradle.kts b/plugins/build-plugin/build.gradle.kts index 1690f112..4335a91a 100644 --- a/plugins/build-plugin/build.gradle.kts +++ b/plugins/build-plugin/build.gradle.kts @@ -3,8 +3,8 @@ plugins { } gradlePlugin { - // Define the plugin - val sonatypeCentralUpload by plugins.creating { + // Define the plugin + val sharedBuild by plugins.creating { id = "com.powersync.plugins.sharedbuild" implementationClass = "com.powersync.plugins.sharedbuild.SharedBuildPlugin" } @@ -13,4 +13,5 @@ gradlePlugin { dependencies { implementation(libs.gradle.download.task) implementation(libs.kotlin.gradle.plugin) + implementation(libs.dokka.gradle.plugin) } diff --git a/plugins/build-plugin/src/main/kotlin/dokka-convention.gradle.kts b/plugins/build-plugin/src/main/kotlin/dokka-convention.gradle.kts new file mode 100644 index 00000000..2bdc662f --- /dev/null +++ b/plugins/build-plugin/src/main/kotlin/dokka-convention.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("org.jetbrains.dokka") +} + +// Shared Dokka config for additional assets +dokka { + pluginsConfiguration.html { + val docsAssetsDir = rootProject.file("docs/assets") + + customAssets.from(docsAssetsDir.resolve("powersync-logo.png")) + customAssets.from(docsAssetsDir.resolve("logo-icon.svg")) + customAssets.from(docsAssetsDir.resolve("discord.svg")) + customAssets.from(docsAssetsDir.resolve("github.svg")) + customAssets.from(docsAssetsDir.resolve("web.svg")) + customAssets.from(docsAssetsDir.resolve("x.svg")) + customAssets.from(docsAssetsDir.resolve("youtube.svg")) + customAssets.from(docsAssetsDir.resolve("linkedin.svg")) + customStyleSheets.from(docsAssetsDir.resolve("doc-styles.css")) + templatesDir = file(docsAssetsDir.resolve("dokka-templates")) + } +}